最終目的:能通過輸入關鍵字進行搜索,爬取相應的圖片存儲到本地或者數據庫
首先打開百度圖片的網站,搜索任意一個關鍵字,比如說:水果,得到如下的界面
分析:
1、百度圖片搜索結果的頁面源代碼不包含需要提取的圖片信息,需要借助Chrome調試工具(F12調出)分析請求的URL地址
2、圖片顯示頁面沒有翻頁按鈕,但是頁面一直往下拉會生成新的圖片,這是典型的AJAX數據
F12打開調試工具,刷新網頁,點擊選中Network選項卡中的XHR標簽(這個標簽加載的就是AJAX請求),此時只能看到一條loginfo開頭的信息,字面上可以理解為和登錄相關的內容,先不管它
把網頁往下拖動,可以看到有新的信息加載出來
這些加載出來的都是以acjson開頭的信息,點擊之后查看Headers、Preview、Response標簽,可以看出來這里面包含了我們需要的圖片信息
對比一下這幾條信息的headers中Request URL可以得出參數中有三個值在變化,一個psm,一個pn,還有一個14。。。開頭的數字,經過測試可以發現,實際上pn的值是最關鍵的,它影響翻頁,其他兩個可有可無。(對比url建議用一些在線代碼對比工具,要不然眼睛要瞎)
下面開始寫代碼:
一、請求網頁,獲取html文本(百度圖片有防盜鏈,加個Referer)
# 獲取動態頁面返回的文本
def get_page_html(page_url): headers = { 'Referer': 'https://image.baidu.com/search/index?tn=baiduimage', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36' } try: r = requests.get(page_url, headers=headers) if r.status_code == 200: r.encoding = r.apparent_encoding return r.text else: print('請求失敗') except Exception as e: print(e)
二、使用正則表達式提取真實圖片的地址(選的是小圖,大圖在objURL里,需要經過簡單的解密)
# 從文本中提取出真實圖片地址
def parse_result(text): url_real = re.findall('"thumbURL":"(.*?)",', text) return url_real
三、請求圖片的url,返回content(圖片信息需要以二進制寫入)
# 獲取圖片的content
def get_image_content(url_real): headers = { 'Referer': url_real, 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36' } try: r = requests.get(url_real, headers=headers) if r.status_code == 200: r.encoding = r.apparent_encoding return r.content else: print('請求失敗') except Exception as e: print(e)
四、保存圖片(因為是測試,我寫的是絕對地址,正常需要用相對地址)
# 將圖片的content寫入文件
def save_pic(url_real, content): root = 'D://baiduimage//' path = root + url_real.split('/')[-1] if not os.path.exists(root): os.mkdir(root) if not os.path.exists(path): with open(path, 'wb') as f: f.write(content) print('圖片{}保存成功,地址在{}'.format(url_real, path)) else: pass
五、定義一個主函數(百度圖片每次最多請求30張,即使改了其他請求參數也最多60張)
# 主函數
def main(): keyword = input('請輸入你要查詢的關鍵字: ')
'''
按照標准, URL 只允許一部分 ASCII 字符(數字字母和部分符號),其他的字符(如漢字)是不符合 URL 標准的。
所以 URL 中使用其他字符就需要進行 URL 編碼。python3中使用urllib.parse.quote進行編碼
''' keyword_quote = urllib.parse.quote(keyword) depth = int(input("請輸入要爬取的頁數(每頁30張圖): ")) for i in range(depth): url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord+=&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&word={}&z=&ic=0&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&step_word={}&pn={}&rn=30&gsm=1e&1541136876386='.format( keyword_quote, keyword_quote, i * 30) html = get_page_html(url) real_urls = parse_result(html) for real_url in real_urls: content = get_image_content(real_url) save_pic(real_url, content)
六、最后寫一個函數入口
# 函數入口
if __name__ == '__main__': main()
當然,實現整個過程最好是先把整體的框架寫好,那樣思路最清晰。
關於百度圖片的爬取就到這里,源代碼地址:傳送門