微信圖片_20200417222718.jpg
全文介紹:
接著上篇文章车海,我們已經(jīng)實(shí)現(xiàn)圖片的下載碧浊,但是我們發(fā)現(xiàn)整個(gè)爬取過程中涂邀,因?yàn)槭褂昧?strong>for循環(huán)嵌套,導(dǎo)致每次遍歷辉词,都會打開文件在關(guān)閉必孤,打開文件在關(guān)閉(套娃)。所以需要注意for循環(huán)的使用瑞躺,其次下載圖片是整個(gè)程序中最耗時(shí)的敷搪,如果需要提升爬取速度,那么我們可以從這個(gè)方向入手幢哨,實(shí)現(xiàn)多線程爬取
涉及內(nèi)容:
- 爬蟲基本流程
- requests庫基本使用
- urllib.parse模塊
- threading模塊
圖例說明:
- 請求與響應(yīng)
sequenceDiagram
瀏覽器->>服務(wù)器: 請求
服務(wù)器-->>瀏覽器: 響應(yīng)
- 爬蟲基本流程
graph TD
A[目標(biāo)網(wǎng)站] -->|分析網(wǎng)站| B(url)
B --> C[模擬瀏覽器請求資源]
C -->D[解析網(wǎng)頁]
D-->E[保存數(shù)據(jù)]
正文:
1.導(dǎo)入
import urllib.parse
import threading
import requests
2.發(fā)送請求赡勘,獲取響應(yīng)
def get_page(url):
page = requests.get(url)
page = page.content
# 將 bytes 轉(zhuǎn)化為 字符串
page = page.decode('utf-8')
return page
3.關(guān)鍵字以及翻頁
def pages_from_duitang(label):
url = 'https://www.duitang.com/napi/blog/list/by_search/?kw={}&start={}'
pages = []
# 將中文轉(zhuǎn)化成url編碼
label = urllib.parse.quote(label)
# 0-3600 步長100
for index in range(0, 3600, 100):
# 將這兩個(gè)變量替換占位符{}
u = url.format(label, index)
print(u)
page = get_page(u)
pages.append(page)
return pages
4.獲取一個(gè)頁面上的所有圖片子鏈接
def findall_pages(page, startpart, endpart):
all_string = []
end = 0
# -1代表找不到 意思就是匹配到就執(zhí)行循環(huán)
while page.find(startpart, end) != -1:
# 匹配第一個(gè)字符,從下標(biāo)0開始匹配到的位置下標(biāo)捞镰,并將字符長短傳給start變量
start = page.find(startpart, end) + len(startpart)
# 將從第一個(gè)需要匹配的字符串后面的字符開始闸与,匹配第二個(gè)需要匹配的字符出現(xiàn)的位置,并將這個(gè)下標(biāo)值賦給end變量
end = page.find(endpart, start)
# 切片 取兩個(gè)所要匹配字符 之間的部分也就是圖片url
string = page[start:end]
# 存入列表
all_string.append(string)
return all_string
5.爬取全部頁面
def pic_url_from_pages(pages):
pic_url = []
for page in pages:
url = findall_pages(page, 'path":"', '"')
pic_url.extend(url) # 合并列表
return pic_url
6.下載圖片
def pic_download(url, n):
r = requests.get(url)
path = r"C:\Users\Mark\Desktop\新建文件夾 (2)\%s.jpg" %n
with open(path, 'wb')as d:
d.write(r.content)
7.調(diào)用函數(shù)
之前的函數(shù)就像是一個(gè)一個(gè)的零件岸售,現(xiàn)在我們要拼裝這些零件践樱,這個(gè)車才開的起來!??
def main(label):
pages = pages_from_duitang(label)
pic_url = pic_url_from_pages(pages)
n = 0
for url in pic_url:
n += 1
print('正在下載第 {} 張圖片'.format(n))
pic_download(url,n)
main('型雇瑁花')
已完成
- 函數(shù)封裝
- 多線程
8.多線程的實(shí)現(xiàn)
栗子來了
排隊(duì)上廁所:商城經(jīng)常會有人排隊(duì)上廁所拷邢,而一個(gè)廁所(進(jìn)程)是可以有多個(gè)坑位(線程),每當(dāng)有位置空著時(shí)就會有下一個(gè)人進(jìn)來屎慢,進(jìn)來后為了讓別人知道這個(gè)位置有人了(避免爭奪)瞭稼,避免尷尬忽洛,需要上鎖,完事兒环肘,出來時(shí)解鎖就行欲虚,然后再有一個(gè)人進(jìn)來......
1587388722298.png
- 首先設(shè)置信號量
thread_lock = threading.BoundedSemaphore(value=5) # value 可以改,但不可過大
- 然后就是主函數(shù)中對于下載圖片這個(gè)函數(shù)使用多線程
def main(label):
pages = pages_from_duitang(label)
pic_url = pic_url_from_pages(pages)
n = 0
for url in pic_url:
n += 1
print('正在下載第 {} 張圖片'.format(n))
# 上鎖
thread_lock.acquire()
## 下載 這個(gè)方法丟進(jìn)線程池
t = threading.Thread(target=pic_download, args=(url, n))
t.start()
pic_download(url,n)
main('英雄聯(lián)盟')
- 圖片下載完畢悔雹,需要解鎖
thread_lock.release()
效果:
image
注意身體复哆,就不放過多的正能量圖片了
微信圖片_20200417223207.jpg