多執行緒爬取圖片(生產者-消費者模式)
阿新 • • 發佈:2019-01-05
通過生產者-消費者模式實現多執行緒爬取圖片:
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_url17 #子執行緒執行 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 28def 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)