Python爬虫抓取图片到本地
一:目标站点信息
彼岸桌面 网址为:http://www.netbian.com/
二:目标站点分析
(1):构造页面的URL列表
我们需要做的是爬取网站上给定页数的图片,所以,我们首先需要的就是观察各个页面链接之间的关系,进而构造出需要爬取页面的url列表。
可以看出,从第二页开始之后的页面链接只是后面的数字不同,我们可以写个简单的代码,获取页面的url列表
(2):获取一个页面中所有的图片的链接
我们已经获取了所有页面的链接,但是没有获取每张图片的链接,所以,接下来我们需要做的就是获取一个页面中的所有图片的链接。在这里,我们以第一页为例,获取每张图片的链接,其他页面类似。
首先在页面中右键->查看元素,然后点击查看器左边的那个小光标,再把鼠标放在随意一个图片上,这样就定位到这个图片所在的代码位置了;我们可以知道,每个页面有18张图片,接下来,我们需要采用标签去定位页面中的图片的具体位置,如下图所示,我们使用 div.list li a img 刚好定位到了18个img标签。img标签中就包含了我们需要的图片链接。
(3):将图片下载到本地
有了图片链接后,我们需要将图片下载到本地,在这里我们以第一张图片为例进行下载
(4):获取图片的简单爬虫
结合以上三个部分,构造页面的url列表、获取一个页面中的所有图片链接和将图片下载到本地。构造一个完整但效率不高的爬虫。
以上这部分代码就可以完整的运行了,但是效率不高,因为是下载图片,需要一个个排队进行下载。所以,为了解决这个问题,下面的代码我们就使用了多线程来实现图片的爬取和下载。
(5)用Python多线程爬取图片并下载到本地
多线程我们使用的是Python自带的threading模块。并且我们使用了一种叫做生产者和消费者的模式,生产者专门用来从每个页面中获取图片的下载链接存储到一个全局列表中。而消费者专门从这个全局列表中提取图片链接进行下载。
需要注意的是,在多线程中使用全局变量要用锁来保证数据的一致性。
import urllib
import threading
from bs4 import BeautifulSoup
import requests
import os
import time
import lxml
page_links_list=[‘http://www.netbian.com/’]
img_links_list = []
#获取爬取的页数和页面链接
def GetUrls(page_links_list):
pages = int(input(‘请输入你想爬取的页数:’))
if pages > 1:
for page in range(2, pages + 1):
url = ‘http://www.netbian.com/index_’ + str(page) + ‘.htm’
page_links_list.append(url)
else:
page_links_list=page_links_list
#初始化锁,创建一把锁
gLock=threading.Lock()
#生产者,负责从每个页面中获取图片的链接
class Producer(threading.Thread):
def run(self):
while len(page_links_list)>0:
#上锁
gLock.acquire()
#默认取出列表中的最后一个元素
page_url=page_links_list.pop()
#释放锁
gLock.release()
#获取img标签
html = requests.get(page_url).content.decode('gbk')
soup = BeautifulSoup(html, 'lxml')
imgs = soup.select("div.list li a img")
#加锁3
gLock.acquire()
for img in imgs:
img_link = img['src']
img_links_list.append(img_link)
#释放锁
gLock.release()
#print(len(img_links_list))
#消费者,负责从获取的图片链接中下载图片
class Consumer(threading.Thread,):
def run(self):
print("%s is running"%threading.current_thread())
while True:
#print(len(img_links_list))
#上锁
gLock.acquire()
if len(img_links_list)==0:
#不管什么情况,都要释放锁
gLock.release()
continue
else:
img_url=img_links_list.pop()
#print(img_links_list)
gLock.release()
filename=img_url.split(’/’)[-1]
print(‘正在下载:’, filename)
path = ‘./images/’+filename
urllib.request.urlretrieve(img_url, filename=path)
if len(img_links_list)==0:
end=time.time()
print(“消耗的时间为:”, (end - start))
exit()
if name == ‘main’:
GetUrls(page_links_list)
os.mkdir(’./images’)
start=time.time()
# 5个生产者线程,去从页面中爬取图片链接
for x in range(5):
Producer().start()
# 10个消费者线程,去从中提取下载链接,然后下载
for x in range(10):
Consumer().start()