使用正則運算式和 requests 模塊
前要知識
| 所需模塊 | 學習路徑 |
|---|---|
| re | re模塊知識總結 |
| requests | request模塊學習路徑 |
通過 re 和 requests 模塊便可完成簡單的圖片爬取功能,
行動開始
我們以素材8網站為例,對素材8首頁存在的圖片進行爬取,
# 首先匯入我們所需要用到的包
import re
import requests
# get 是request里的一個方法 它的意思是:從指定的資源請求資料,
ret = requests.get("https://www.sucai8.com/")
# 這里的ret.text是將請求到的資料轉化為文本格式讀取,其實也就是頁面的html代碼內容
# 具體的輸出內容就不進行展示了,感興趣可以動手嘗試
print(ret.text)
這里加一點點的前端知識:一個網頁里面的所有元素都有它們自己的標簽,圖片對應的標簽格式是 < img 內置元素 /> ,這里我通過將文本匯入 Linux,并用 grep 方法過濾出所有的圖片標簽:

通過 Linux 對文本內容進行選中處理后,我仔細看了所有的圖片內容格式標簽,對內容進行判斷: src 是圖片存放的路徑,后面有 alt,width,class 等對圖片進行設定的內置元素,因此我產生了初步的正則運算式的想法:
# 使用正則運算式斷言(這個是正則運算式中挺有意思的部分,后續會專門出一期講解)
rets_1 = re.findall(r'(?<=<img src=")(.+)(?=" (?:alt=.+>|width.+>|class.+/>))', ret.text)
# 通過使用斷言設定圖片存放路徑的左邊內容格式和右邊格式內容對其的路徑進行匹配 我們來嘗試看一下得到的結果
print(rets_1)

這里得到的結果并不是我們想要的那種僅有圖片的格式,后面的13張圖片都能正常的得到存盤路徑,但是前面的出現了過長的問題,在我仔細讀了 Linux 過濾的文本后,我估計是貪婪匹配出了問題,在上面的內容中使用貪婪匹配就會導致輸出的內容超出我們的預期(做爬蟲的時候千萬記得不要用貪婪匹配!不要用貪婪匹配! 因為HTML不同元素的格式內容都很接近,所以使用貪婪匹配容易出現問題,),于是我將代碼改成:
rets_2 = re.findall(r'(?<=<img src=")(.+?)(?=" (?:alt=.+>|width.+>|class.+/>))', ret.text)
print(rets_2)

ok 所有圖片都以預期的格式正常輸出,
然后我們開始考慮,想要把這些圖片下載下來應該怎么辦呢?
是不是可以使用 requests.get(‘圖片儲存路徑’) 然后用它的 content 方法(回傳的是bytes型也就是二進制的資料),將內容寫入檔案,應該就是我們想要下載的圖片了!
開始敲!
import os
# 因為我想把檔案儲存到當前路徑下所以使用 os 模塊找到當前路徑
head = "https://www.sucai8.com"
# 因為檔案的存盤路徑是 網址 + 我們得到的存盤路徑 (這里涉及一點前端的知識 有興趣可以去了解一下) 所以我們下一步是需要對前面得到的路徑都加一段頭內容
list_result = [head+temp for temp in rets_2]
# 這樣我們就得到了所有圖片的存盤路徑 可以直接通過requests.get()對路徑進行訪問
print(list_result)

ok,我們看到每張想要下載的圖片都是可以點進去的鏈接的時候就完成了下載的前期準備作業,
然后下載內容的代碼如下:
for i in range(len(list_result)):
print(f"正在下載第{i+1}張圖片,下載地址:{list_result[i]}")
# os.path.dirname 這個就是得到當前存在的路徑
d_path = os.path.dirname(__file__)
# de_path 就是在路徑的后面加上一個圖片的格式,png/jpg/gif 通過split(".")進行字串分隔,然后訪問它的格式名
de_path = d_path + f'/{i+1}' + f'.{list_result[i].split(".")[3]}'
# 打開檔案(如果不存在就新建)將content得到的內容進行寫入
with open(de_path, 'wb') as fp:
fp.write(d_pic.content)
fp.close()
代碼直接運行試試!


所有的圖片都下載成功了!
但是還是覺得代碼并不完整(別問,問就是處女座!)
考慮如果網速不佳的情況下,下載請求過長就要輸出訪問超時,改圖片無法下載,如果在規定時間內訪問就可以下載,是不是代碼會更加完整一些?于是將代碼改良后,如下:
for i in range(len(list_result)):
print(f"正在下載第{i+1}張圖片,下載地址:{list_result[i]}")
# try except else 是例外處理陳述句
# 如果 try 的要求不被滿足就會觸發 except 的例外請求
# 如果 try 正常執行 在 try 的內容執行完畢之后就繼續執行else陳述句
try:
d_pic = requests.get(list_result[i], timeout=5)
except TimeoutError:
print("訪問超時,該圖片無法下載")
else:
d_path = os.path.dirname(__file__)
de_path = d_path + f'/{i+1}' + f'.{list_result[i].split(".")[3]}'
with open(de_path, 'wb') as fp:
fp.write(d_pic.content)
fp.close()
至此 整個代碼程序已經寫完了,并且圖片都正常下載可以直接打開觀看圖片的內容,將該次爬蟲實驗的所有代碼貼在下面:
import requests
import re
import os
ret = requests.get("https://www.sucai8.com/")
# print(ret.text)
head = "https://www.sucai8.com"
# rets_1 = re.findall(r'(?<=<img src=")(.+)(?=" class.+/>)', ret.text)
rets_2 = re.findall(r'(?<=<img src=")(.+?)(?=" (?:alt=.+>|width.+>|class.+/>))', ret.text)
# print(rets_1)
# print(rets_2)
list_result = [head+temp for temp in rets_2]
# print(list_result)
for i in range(len(list_result)):
print(f"正在下載第{i+1}張圖片,下載地址:{list_result[i]}")
try:
d_pic = requests.get(list_result[i], timeout=5)
except TimeoutError:
print("訪問超時,該圖片無法下載")
else:
d_path = os.path.dirname(__file__)
de_path = d_path + f'/{i+1}' + f'.{list_result[i].split(".")[3]}'
with open(de_path, 'wb') as fp:
fp.write(d_pic.content)
fp.close()
ok 此次爬蟲結束!
如果感興趣想要深入了解學習 歡迎來 三創 一起交流學習!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/279263.html
標籤:python
