今天試着把前面那個爬取圖片的爬蟲改成了多線程爬取,雖然最后可以爬取存儲圖片了,但仍存在一些問題。網址還是那個網址https://www.quanjing.com/category/1286521/1.html,
下面是代碼,難點直接在后面注釋了。
# 多線程爬取,每個線程爬取一個頁面
import requests
import threading
import queue
from bs4 import BeautifulSoup
import re
import time
string = "https://www.quanjing.com/category/1286521/"
pipei = re.compile('<img.*?lowsrc="(.*?)"')
class spiders(threading.Thread):
name = 1 # 累加變量,用來給每張圖片命名
def __init__(self, queue, page):
threading.Thread.__init__(self)
self.queue = queue
self.page = page
def run(self): # 定義線程開始函數
while not self.queue.empty():
url = self.queue.get_nowait()
# print(url)
self.request_url(url)
def request_url(self, url): # 爬取並存儲每一頁的圖片
html = requests.get(url=url).text
soup = BeautifulSoup(html, 'lxml')
li = str(soup.find_all(attrs={'class': "gallery_list"})) # 根據class標簽屬性找出所有的圖片鏈接
lianjies = re.findall(pipei, li) # 正則匹配出一頁中每一個圖片的鏈接
for lianjie in lianjies:
result = requests.get(url=lianjie).content # 獲取圖片的二進制數據
# 以二進制的方式存儲圖片
with open('E:\py project\quanjingwang\image{0}\{1}.jpg'.format(self.page, self.name), 'ab+') as f:
f.write(result)
print("第{0}張存儲完成".format(self.name))
self.name += 1 # 命名
# 創建多線程函數
def main():
url_queue = queue.Queue()
for i in range(1, 11):
url = string + str(i) + ".html"
url_queue.put(url)
thread_list = [] # 線程列表
thread_counter = 5 # 線程數量,根據線程數量在相同目錄下創建image0-4五個文件夾,用於存儲對應線程的爬取結果,image0對應線程1
for i in range(thread_counter):
t = spiders(url_queue, i)
thread_list.append(t)
for t in thread_list:
t.start()
# for t in thread_list:
# print("線程id:%d" % t.ident) # 獲取線程id
# print("線程name:%s" % t.getName()) # 獲取線程名
for t in thread_list:
t.join()
if __name__ == '__main__':
start_time = time.time()
main()
print("五線程用時:%f" % (time.time() - start_time))
剛開始,我想把爬取的所有圖片都放在一個文件夾了,但卻由於命名的問題,總是被覆蓋,每次都只有一頁的圖片,最后用類中的靜態變量解決(name)。不過就在剛在突然想到完全可以換一種命名方式解決,比如每張圖片都有一個自己的標題,用標題命名不但解決的這個問題,還更加直觀、利用查找。(自己tcl。。。若文章有錯誤,歡迎大家隨之指正。。。)
