1. 程式人生 > 其它 >爬蟲實戰:通過百度關鍵詞爬取大量圖片

爬蟲實戰:通過百度關鍵詞爬取大量圖片

技術標籤:爬蟲爬蟲python

目標地址: http://image.baidu.com/
輸入美女

分析網址
元網址見圖

貼上過來卻如下
(在這裡你會看到,明明在瀏覽器URL欄看到的是中文,但是複製url,貼上到記事本或程式碼裡面,就會變成如下這樣???)

https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1610771025434_R&pv=&
ic=&nc=1&z=&hd=&latest=&copyright=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E7%BE%8E%E5%A5%B3

在很多網站的URL中對一些get的引數或關鍵字進行編碼,所以我們複製出來的時候,會出現問題。

URL的編碼和解碼

import urllib
from urllib import parse
import urllib.request

data =
{'word': '美女'} # Python3的urlencode需要從parse中呼叫,可以看到urlencode()接受的是一個字典 print(urllib.parse.urlencode(data)) # 通過urllib.request.unquote()方法,把URL編碼字串,轉換回原先字串 print(urllib.request.unquote('word=%E7%BE%8E%E5%A5%B3'))

分析原始碼
F12或者頁面上右鍵審查元素。開啟以後,定位到圖片的位置

複製下面這個網址
注意有轉義字元

imgurl="https:\/\/ss0.bdstatic.com\/70cFvHSh_Q1YnxGkpoWK1HF6hhy\/it\/u=2718853745,1288801299&fm=214&gp=0.jpg"

然後在當前網頁的空白地方右鍵:檢視網頁原始碼
使用快捷鍵CTRl+F
查詢(我這裡 輸入 gp=0.jpg 通過輸入圖片網址最後幾個字元來定點陣圖片)

這個圖片怎麼有很多地址,到底用哪個呢?可以看到有thumbURL,objURL等等。
通過分析可以知道,前面兩個是縮小的版本,hover是滑鼠移動過後顯示的版本,objURL對應的那個地址,應該是我們需要的,不信可以開啟這幾個網址看看,發現obj那個最大最清晰。

編寫正則表示式或者XPath表示式

pic_url = re.findall(’“objURL”:"(.*?)",,html,re.S)

objurl後面的,全匹配

找到本機電腦網路的headers
有的時候,我們無法爬取一些網頁,會出現403錯誤,因為這些網頁為了防止別人惡意採集資訊所以進行了一些反爬蟲的設定。
我們可以設定一些Headers資訊,模擬成瀏覽器去訪問這些網站,就能解決這個問題。
首先,單擊網頁中的百度一下,即讓網頁發生一個動作,下方窗口出現了很多資料,如圖。

此時單擊圖中的www.baidu.com,出現如圖

在Headers,往下拖動,找到User-agent
這一串資訊就是我們下面模擬瀏覽器用到的資訊,複製出來。

所有程式碼
語言python

from urllib.parse import quote
import string
import re
from urllib import request
import  urllib.request
word = input('關鍵詞:')
url = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + word + '&ct=201326592&v=flip'
url = quote(url, safe=string.printable)# # 解決ascii編碼報錯問題,不報錯則可以註釋掉
#模擬成瀏覽器
headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3947.100 Safari/537.36")
opener=urllib.request.build_opener()
opener.addheaders=[headers]
#將opener安裝為全域性
urllib.request.install_opener(opener)
#讀取網頁


url_request=request.Request(url)
url_response = request.urlopen(url_request,timeout=10)   # 請求資料,可以和上一句合併.表示一次http訪問請求的時間最多10秒,一旦超過,本次請求中斷,但是不進入下一條,而是繼續重複請求這一條
html = url_response.read().decode('utf-8')  # 加編碼,重要!轉換為字串編碼,read()得到的是byte格式的。

jpglist = re.findall('"thumbURL":"(.*?)",',html,re.S)	#re.S將字串作為整體,在整體中進行匹配。,thumbURL可以匹配其他格式的圖
print(len(jpglist))
n = 1
for each in jpglist:
    print(each)
    try:
        request.urlretrieve(each,'D:\\deeplearn\\xuexicaogao\\圖片\\%s.jpg' %n) #爬下載的圖片放置在提前建好的資料夾裡
    except Exception as e:
        print(e)
    finally:
        print('下載完成。')
    n+=1
    if n==90:
        break
print('結束')

程式碼解析
爬蟲報錯UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 45-47: ordinal not…
原因 python 預設的編碼是ascii,當程式中出現非ascii編碼時,python的處理常常會報這樣的錯UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0x?? in position 1: ordinal not in range(128),python沒辦法處理非ascii編碼的,此時需要自己設定將python的預設編碼,一般設定為utf8的編碼格式。
使用urllib.parse.quote進行轉換。

結果資料夾

程式碼版本2
語言python

import urllib
import urllib.request
from urllib.parse import quote
import re
import os

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
    "referer": "https://image.baidu.com"
}
print("****************************************************************************************")
keyword = input("請輸入要下載的圖片:")
last_dir = "C://Users//Shineion//Desktop//爬蟲圖"
dir = "C://Users//Shineion//Desktop//爬蟲圖//" + keyword
if os.path.exists(last_dir):
    if os.path.exists(dir):
        print("資料夾已經存在")
    else:
        os.mkdir(dir)
        print(dir + "已經建立成功")
else:
    os.mkdir(last_dir)
    if os.path.exists(dir):
        print("資料夾已經存在")
    else:
        os.mkdir(dir)
        print(dir + "已經建立成功")
keyword1 = quote(keyword, encoding="utf-8")
url = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + keyword1 + '&ct=201326592&v=flip'
req = urllib.request.Request(url, headers=headers)
f = urllib.request.urlopen(req).read().decode("utf-8")
key = r'thumbURL":"(.+?)"'
key1 = re.compile(key)
num = 0
for string in re.findall(key1, f):
    print("正在下載" + string)
    f_req = urllib.request.Request(string, headers=headers)
    f_url = urllib.request.urlopen(f_req).read()
    fs = open(dir + "/" + keyword + str(num) + ".jpg", "wb+")
    fs.write(f_url)
    fs.close()
    num += 1
    print(string + "已下載成功")
input("按任意鍵結束程式:")

注意問題:程式碼容易卡住,在獲取某一圖片時卡住
在這裡插入圖片描述
作者:電氣-餘登武