多线程爬取图片(生产者-消费者模式)

通过生产者-消费者模式实现多线程爬取图片:

  1、生产者通过不断爬取网页中图片的url存入图片队列中

  2、消费者通过图片队列中的url爬取图片并下载到本地

  3、多线程的方式,爬取与下载同时进行,直到子线程结束,输出爬取时间

 

 1 #多线程下载图片
 2 #生产者-消费者模式
 3 import requests,queue,threading
 4 from lxml import etree
 5 from queue import Queue
 6 import os,time
 7 #生产者,将每个图片的url放入队列中
 8 class product(threading.Thread):
 9     headers = {
10         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
11     }
12     #初始化
13     def __init__(self,page_url,img_url):
14         super(product,self).__init__()
15         self.page_url = page_url
16         self.img_url = img_url
17     #子线程运行
18     def run(self):
19         while True:
20             #如果图片url爬去完毕,则跳出循环,结束子线程
21             if self.page_url.empty():
22                 break;
23 
24             #获取将爬取的页面url,并解析
25             html = self.page_url.get()
26             self.parse_html(html)
27     #获取图片的url
28     def parse_html(self,html):
29         request = requests.get(html, headers=self.headers)
30         html = etree.HTML(request.text)
31         #解析html
32         imgs = html.xpath("//div[@class='page-content text-center']//img[@class!='gif']", encodding='gbk')
33         for img in imgs:
34             href = img.get("data-original")
35             name = img.get("alt")
36             #获取后缀
37             suffix = os.path.splitext(href)[1]
38             filename = "img\\" + name + suffix
39             print(filename)
40             #将爬取的图片url和图片名字加入图片队列中
41             self.img_url.put((href,filename))
42 #消费者,根据图片url爬取图片
43 class consume(threading.Thread):
44     def __init__(self,page_url,img_url):
45         super(consume,self).__init__()
46         self.page_url = page_url
47         self.img_url = img_url
48     def run(self):
49         while True:
50             #如果图片队列为空且页面队列为空,则推出循环
51             if self.page_url.empty() and self.img_url.empty():
52                 break
53             href,filename = self.img_url.get()
54             res = requests.get(href)
55             with open(filename, 'wb') as fp:
56                 fp.write(res.content)
57 def main():
58     #基本url
59     base_url = "http://www.doutula.com/photo/list/?page={}"
60     #设置页面队列为10,图片队列为200
61     page_url = Queue(10)
62     img_url = Queue(200)
63     #把需要爬取的网页url放入队列中
64     for i in range(1,10):
65         url = base_url.format(i)
66         page_url.put(url)
67     #设置生产者,开始爬取每个网页的图片地址
68     for i in range(8):
69         t = product(page_url,img_url)
70         t.start()
71     #设置消费者,根据图片队列中的url爬取图片
72     for j in range(8):
73         tt = consume(page_url,img_url)
74         tt.start()
75         #设置消费者子线程运行完之后,才会推出main主线程
76         tt.join()
77 
78 if __name__ == '__main__':
79     times = time.time()
80     tmain = threading.Thread(target=main)
81     tmain.start()
82     tmain.join()
83     times1 = time.time()
84     print(times1-times)

 

你可能感兴趣的:(多线程爬取图片(生产者-消费者模式))