python多線程爬蟲+批量下載斗圖啦圖片項目(關注、持續更新)


python多線程爬蟲項目()

爬取目標:斗圖啦(起始url:http://www.doutula.com/photo/list/?page=1)

爬取內容:斗圖啦全網圖片

使用工具:requests庫實現發送請求、獲取響應。  

     xpath實現數據解析、提取和清洗  

     threading模塊實現多線程爬蟲

爬取結果:

 

思路:由於該爬蟲存在網絡密集IO和磁盤密集IO,存在大量等待時間,遂采用多線程方式爬取。

設計:本文采用多為結構化代碼的面向對象封裝設計思路,使用生產消費者模型,完成多線程的調度、爬取。

直接放代碼(詳細說明在注釋里,歡迎同行相互交流、學習~):

 1 import os
 2 import threading
 3 import re
 4 from queue import Queue
 5 import requests
 6 from urllib import request
 7 from lxml import etree
 8 
 9 # 定義一個全局變量,存儲請求頭headers數據
10 headers = {
11     "User-Agent": "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"
12 }
13 
14 class Producter(threading.Thread):
15     """
16     生產者模型:負責從起始url隊列中提取url,進行解析,將得到的圖片地址放入img圖片隊列中
17     """
18     def __init__(self, page_queue, img_queue, *args, **kwargs):
19         # 改寫父類threading.Thread的__init__方法,添加默認值
20         super(Producter, self).__init__(*args, **kwargs)
21         # 添加對象屬性
22         self.page_queue = page_queue
23         self.img_queue = img_queue
24 
25     def run(self):
26         """
27         實現消費者模型的主要業務邏輯
28         """ 
29         while True:
30             # 當請求隊列為空,生產者停止生產
31             if self.page_queue.empty():
32                 break
33             # 獲取起始url隊列的對象,進行頁面解析
34             url = self.page_queue.get()
35             self.parse_url(url)
36 
37     def parse_url(self, url):
38         """
39         實現解析指定頁面的功能
40         :param url: 傳入待處理的頁面url
41         """
42         response = requests.get(url=url, headers=headers)
43         html = etree.HTML(response.text)
44         # 使用lxml庫里HTML解析器進行數據解析,利用xpath語法解析得到指定數據,返回一個element對象列表
45         url_gifs = html.xpath("//div[@class='page-content text-center']//img[@class!='gif']")
46         for url_gif in url_gifs:
47             # element.get(屬性名)可以獲取屬性值
48             url_name = url_gif.get("alt")
49             # 正則表達式替換非法字符
50             url_name = re.sub(r"[\!!\.\??]", "", url_name).strip()
51             url_link = url_gif.get("data-original")
52             # os模塊中os.path.splitext()可以獲取url的后綴名
53             url_suffix = os.path.splitext(url_link)[1]
54             filename = url_name + url_suffix
55             # 隊列的put()里面傳的是元組或者列表
56             self.img_queue.put((url_link, filename)) 
57 
58 class Consumer(threading.Thread):
59     """
60     消費者模型的主要業務邏輯
61     """
62     
63     def __init__(self, page_queue, img_queue, *args, **kwargs):
64         super(Consumer, self).__init__(*args, **kwargs)
65         self.page_queue = page_queue
66         self.img_queue = img_queue
67 
68     def run(self):
69         """
70         實現讀取圖片url內容的功能
71         """
72         while True:
73             if self.page_queue.empty() and self.img_queue.empty():
74                 break
75             url, filename = self.img_queue.get()
76             # urllib庫里面的request模塊可以讀取圖片url內容
77             request.urlretrieve(url, "GIF/" + filename)
78             # 控制台輸出提示信息
79             print(filename + "-------下載完成!")
80 
81 def main():
82     # 創建page隊列,存放請求的起始url;創建img隊列,存放圖片data的url
83     page_queue = Queue(100) # 設置隊列的最大存儲數量
84     img_queue = Queue(1000) # 設置隊列的最大存儲數量
85     for i in range(100):
86         start_url_format = "http://www.doutula.com/photo/list/?page={}".format(i)
87         # print(start_url_format) #調試代碼用
88         page_queue.put(start_url_format) #將獲取的起始url放入隊列中
89     # 生成多線程對象(多個生產者、消費者)。實現發送請求,獲取響應,解析頁面,獲取數據
90     for i in range(10):
91         t = Producter(page_queue, img_queue)
92         t.start()
93     for i in range(10):
94         t = Consumer(page_queue, img_queue)
95         t.start()
96 
97 if __name__ == '__main__':
98     main()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM