python多線程爬取壁紙 媽媽再也(yě)不(bù)擔心我沒壁紙了(le/liǎo)!
發表時(shí)間:2020-10-19
發布人(rén):融晨科技
浏覽次數:82
基于(yú)上(shàng)次的(de)簡單爬蟲之(zhī)後,這(zhè)次的(de)爬蟲添加了(le/liǎo)多線程的(de)新元素,使爬取的(de)速度在(zài)原來(lái)的(de)基礎上(shàng)快了(le/liǎo)N倍,話不(bù)多說(shuō),來(lái)看代碼
首先我們選擇的(de)網站還是(shì)上(shàng)次的(de)H128壁紙,不(bù)知道(dào)具體流程的(de)可以(yǐ)看下上(shàng)次寫的(de)入門代碼
傳送門!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
打開網站,這(zhè)裏我選擇的(de)是(shì)動漫專區的(de)壁紙,我們的(de)目的(de)是(shì)把所有動漫壁紙爬下來(lái),我們發現一共有98頁圖片
所以(yǐ)我們要(yào / yāo)做的(de)是(shì)觀察每頁圖片鏈接的(de)關系,我們打開第二頁圖片觀察
發現兩頁圖片的(de)鏈接分别是(shì)
https://www.h128.com/pc/anime/0/2/1920x1080/t/1.html
https://www.h128.com/pc/anime/0/2/1920x1080/t/2.html
我們發現兩個(gè)網頁隻有t/後面的(de)數據不(bù)同由此我們觀察後面幾頁,最終我們發現/t/後面的(de)數字就(jiù)是(shì)代表頁數,所以(yǐ)在(zài)最開始我們建立一個(gè)函數來(lái)存放我們需要(yào / yāo)的(de)網頁鏈接
如下:
page_links_list = ['https://www.h128.com/pc/anime/0/2/1920x1080/t/1.html']
def GetUrls(page_links_list):
pages = int(input("請輸入你想爬取的(de)頁數:"))
if pages > 1:
for page in range(2, pages + 1):
url = 'https://www.h128.com/pc/anime/0/2/1920x1080/t/' + str(page) + '.html'
page_links_list.append(url)
else:
page_links_list = page_links_list
然後就(jiù)是(shì)我們多線程的(de)應用了(le/liǎo),我們要(yào / yāo)用的(de)是(shì)python的(de)threading模塊首先需要(yào / yāo)導入threading
import threading
首先建立一個(gè)glock 用來(lái)控制
gLock = threading.Lock()
**threading 提供了(le/liǎo) Lock 類,該類能夠在(zài)某個(gè)線程訪問某個(gè)變量的(de)時(shí)候對變量加鎖,此時(shí)其它線程就(jiù)不(bù)能訪問該變量,直到(dào)該 Lock 被釋放其它線程才能夠訪問該變量
**
我們爬蟲需要(yào / yāo)生産者進程和(hé / huò)消費者進程,生産者的(de)線程專門用來(lái)生産一些數據,然後存放到(dào)一個(gè)中間的(de)變量中。消費者再從這(zhè)個(gè)中間的(de)變量中取出(chū)數據進行消費。但是(shì)因爲(wéi / wèi)要(yào / yāo)使用中間變量,中間變量經常是(shì)一些全局變量,因此需要(yào / yāo)使用鎖來(lái)保證數據完整性。在(zài)這(zhè)個(gè)代碼中生産者進程負責來(lái)獲取我們圖片的(de)url,而(ér)消費者進程的(de)目的(de)是(shì)下載圖片。
生産者代碼如下:
class Generant(threading.Thread):
def run(self):
while len(page_links_list) > 0:
gLock.acquire() #上(shàng)鎖
page_url = page_links_list.pop()
gLock.release() #釋放鎖
r = requests.get(page_url,headers = headers)
r.raise_for_status()
r.encoding = r.apparent_encoding
a = re.findall('<img src="https:(.*?)" alt',r.text)
gLock.acquire() #上(shàng)鎖
for i in a :
x = 'https:' + i
x = x.replace('w_487', 'w_1421').replace('h_274', 'h_799')
img_links_list.append(x)
gLock.release() #釋放鎖
消費者代碼如下
class Consumer(threading.Thread,):
def run(self):
while True:
gLock.acquire()
if len(img_links_list) == 0:
gLock.release()
continue
else:
img_url = img_links_list.pop()
gLock.release()
filename = img_url.split('?')[0].split('/')[-1]
r = requests.get(img_url)
print('正在(zài)下載:', filename)
path = './picture/' + filename
with open(path,'wb') as f:
f.write(r.content)
f.close()
if len(img_links_list) == 0:
end = time.time()
print("消耗的(de)時(shí)間爲(wéi / wèi):", (end - start))
exit()
最後的(de)代碼就(jiù)是(shì)啓動線程
for x in range(5):
Generant().start()
for x in range(5):
Consumer().start()
觀看運行結果:
這(zhè)裏是(shì)下載了(le/liǎo)50頁圖片的(de)時(shí)間,比起單線程還是(shì)很快的(de)。
最後附上(shàng)完整代碼
下面展示一些 内聯代碼片
。
import threading
import requests
import re
import time
import os
page_links_list = ['https://www.h128.com/pc/anime/0/2/1920x1080/t/1.html']
img_links_list = []
headers = {
"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
}
def GetUrls(page_links_list):
pages = int(input("請輸入你想爬取的(de)頁數:"))
if pages > 1:
for page in range(2, pages + 1):
url = 'https://www.h128.com/pc/anime/0/2/1920x1080/t/' + str(page) + '.html'
page_links_list.append(url)
else:
page_links_list = page_links_list
gLock = threading.Lock()
class Generant(threading.Thread):
def run(self):
while len(page_links_list) > 0:
gLock.acquire() #上(shàng)鎖
page_url = page_links_list.pop()
gLock.release() #釋放鎖
r = requests.get(page_url,headers = headers)
r.raise_for_status()
r.encoding = r.apparent_encoding
a = re.findall('<img src="https:(.*?)" alt',r.text)
gLock.acquire() #上(shàng)鎖
for i in a :
x = 'https:' + i
x = x.replace('w_487', 'w_1421').replace('h_274', 'h_799')
img_links_list.append(x)
gLock.release() #釋放鎖
class Consumer(threading.Thread,):
def run(self):
while True:
gLock.acquire()
if len(img_links_list) == 0:
gLock.release()
continue
else:
img_url = img_links_list.pop()
gLock.release()
filename = img_url.split('?')[0].split('/')[-1]
r = requests.get(img_url)
print('正在(zài)下載:', filename)
path = './picture/' + filename
with open(path,'wb') as f:
f.write(r.content)
f.close()
if len(img_links_list) == 0:
end = time.time()
print("消耗的(de)時(shí)間爲(wéi / wèi):", (end - start))
exit()
if __name__ == '__main__':
GetUrls(page_links_list)
if os.path.exists('./picture'):
print("文件已存在(zài)")
else:
os.mkdir('./picture')
start = time.time()
for x in range(5):
Generant().start()
for x in range(5):
Consumer().start()
最後如果想要(yào / yāo)全站的(de)圖片隻要(yào / yāo)把鏈接改一下就(jiù)OK