基於cookie爬蟲--Pixabay高清圖片爬取

前言

由於公衆號每次都須要圖片才能羣發,但人爲一張張下載又很傻,因此想到用爬蟲去爬取。本文旨在總結下一個簡單的爬蟲步驟,加深本身的印象,若有表達不許確的地方望指出,一塊兒學習。本文爬蟲使用python語言,基於cookie的爬取,所爬取的圖片來自於pixabay網站。html

爬蟲步驟

1.目的
首先須要明確爬蟲的目標是什麼?由於公衆號規定最大上傳5M內的圖片,因此個人目標是範圍內的最高分辨率的圖片。 python

2.起始url
接着要明確你爬取的起始連接,也就是你一開始請求的網頁,這個網頁應該具備你想要的東西。我選擇的是pixabay的搜索頁面https://pixabay.com/zh/images/search/, 它內容以下:
初始urlgit

該頁面的圖片即是咱們想要的東西。接着發現該頁面存在下一頁按鈕,能夠緩一口氣了,還好不是動態加載頁面,點擊下一頁,觀察url的變化,能夠發現第二頁的url結尾多了?pagi=2,多驗證幾個,能夠總結出起始頁面爲https://pixabay.com/zh/images/search/?pagi=1更改最後的數字能夠實現切換頁數功能github

3.分析頁面信息
右鍵檢查進入開發者模式,最上方須要關注element和network,其中element是請求url後response的正文內容,network是請求url後的加載過程,能夠查看具體的請求頭與響應頭以及其餘參數。
開發者模式正則表達式

先選任意一張圖片右鍵檢查,以下:
一張圖片數據庫

能夠發現裏面有不少連接,隨便打開一個都是這張圖片,只是size不一樣,很明顯這些圖是縮略圖,若是對圖片分辨率不作要求,咱們能夠直接爬取這些連接並下載,便可。可是個人目標是高畫質的圖片,因此須要繼續尋找高畫質圖片的連接才行。 瀏覽器

點開一張圖,重複上面過程,發現這張圖也只是分辨率高了一點而已,不知足要求。接着目光移到免費下載按鈕上,能夠發現其中1920*1279是知足咱們要求的最高分辨率圖像:
免費下載按鈕服務器

鼠標放「查看」上,右鍵檢查
1920高清圖連接cookie

其中href字段後面就是目標地址,將href接在首頁地址後,就造成了一個完整的高清圖片請求連接,https://pixabay.com/zh/images/download/landscape-4508444_1920.jpgsession

接着須要作的就是用代碼去請求這個連接,並下載服務器返回響應體中的content

4.整理思路

(1)請求起始base_url,獲取img字段中的圖片名稱name;
(2)將獲取的名稱組合成一個完整連接download_url; https://pixabay.com/zh/images/download/imgname.jpg
(3)請求上述鏈接,並將響應的content進行下載;
(4)修改起始url中的頁數,並重復2-3步

代碼實現

1.請求起始url,並獲取圖片名稱

import re  #正則表達式
import requests #請求url
from lxml import etree #解析起始url正文內容

#get請求起始連接,並返回正文內容
html = requests.get(base_url).text 
#解析正文內容
tree = etree.HTML(html)
#提取縮略圖連接,我選擇的是data-lazy字段
img_name = tree.xpath('//img/@data-lazy')
#提取圖片名字構成高分辨率圖片連接
img_url=[]
#月-日-時-分,正則表達式匹配,只保留圖片名
reg = re.compile(r"/[0-9]{2}/[0-9]{2}/[0-9]{2}/[0-9]{2}/(.*)__")
#這是一個頁面的全部圖片連接
for i in img_name:
    name=re.findall(reg, i) #提取名字,name是一個列表
    #組合高分辨率圖片連接,若是不加1920,可獲取原始圖片,通常在5M以上
    img_url.append(download_url+name[0]+"_1920.jpg")

2.請求下載url,並將響應內容進行下載

#保存路徑
img_path = img_root+name+".jpg"  
#請求高清圖片
img = requests.get(download_url)
#將響應的內容進行下載,下載其實就是寫操做
with open(img_path, 'wb') as f:
    f.write(img.content)

3.循環請求
將上面的兩個模塊放入for循環中,便可。

問題分析

上面基本上就是一個簡單爬蟲的結構,既不用模擬登陸,也不用模擬動態請求。雖然結構正確,可是按照上面代碼進行爬取,是爬不到任何東西,由於你會被阻擋在下面的界面,而你下載的圖片內容只是它的文本內容
you are a robot

其實能夠模擬這個過程,將download_url從無痕模式正常模式下打開,就會發如今正常模式下能夠看圖片,而在無痕模式下出現的是上圖界面。出現這個差異,緣由出自於cookie。

cookie與session

1.概念
因爲HTTP協議是無狀態協議,因此服務端須要記錄用戶的狀態時,就須要用某種機制來識具體的用戶,這個機制就是session,其中session是保存在服務端的,有一個惟一標識。舉個栗子:

當你進行購物車下單時,因爲HTTP協議無狀態,其並不知道是哪一個用戶操做的,因此服務端要爲特定的用戶建立了特定的session來標識這個用戶,而且跟蹤用戶,這樣才知道購物車裏面有什麼。

那服務端又如何識別特定的客戶呢?答案就是cookie。每次HTTP請求的時候,客戶端都會發送相應的cookie信息到服務端。實際上大多數的應用都是用cookie來實現session跟蹤的,第一次建立session的時候,服務端會在HTTP協議中告訴客戶端,須要在cookie裏面記錄一個session ID,之後每次請求把這個會話ID發送到服務器,就能肯定是哪一個客戶端。

2.做用
如上所說,cookie能夠用來讓服務端「認識」客戶端。除此以外,cookie還能夠用來跳過登陸環節,再舉個栗子:

設想你第一次登陸一個網站,輸入帳號密碼後,進入它的主頁,此時你關掉頁面並從新訪問一次,你會發現此次不用輸入帳號密碼,直接進入了主頁。

你必定經歷過上述場景,緣由就是,瀏覽器將這個登陸信息寫到cookie裏,並存儲在了本地磁盤。下次訪問網頁時,網頁腳本就能夠讀取這個信息,並自動幫你把用戶名和密碼填寫了。這也是cookie名稱的由來,給用戶的一點甜頭。

3.小結
(1)session是服務端保存的一個數據結構,用來跟蹤用戶的狀態,這個數據能夠保存在集羣、數據庫、文件中;
(2)cookie是客戶端保存用戶信息的一種機制,用來記錄用戶的一些信息,也是實現session的一種方式。

總結

1.怎麼獲取cookie
從正常模式下請求download_url(提早打開開發者模式),查看network下的請求過程:
請求過程

上圖左邊從上到下就是請求的順序,第一個是請求的download_url,第二個是返回的圖片內容。上圖右邊的response headers是響應體,裏面有返回內容的一些信息,如content-length等,當content-length(正文長度)爲0,說明沒有請求到數據。requests headers是請求體,是請求頁面須要發給服務器端的信息,其中就包含cookie,以及爬蟲常常用到的user-agent

大體的請求過程以下:瀏覽器提交攜帶cookie的請求體 -> 服務端接收後經過cookie肯定sessionid -> 返回響應體 -> 經過響應體中給的location字段從新請求 -> 服務端返回圖片內容 -> 瀏覽器接收後顯示
響應體

2.怎麼攜帶cookie請求

#yourcookie = {"xxx":"sdsaf"}
html = requests.get(download_url, cookies = yourcookie)

3.不足與解決方向
cookie請求仍是存在侷限性

  • 同一cookie屢次訪問服務器時,服務器會進行從新驗證,判斷是不是爬蟲訪問。這個很好識別,通常爬蟲對服務器的訪問呈線性關係。針對此,能夠經過睡眠時間變化來模擬人爲訪問,但當睡眠時間過長又會使得爬蟲效率過低。
  • 使用cookie爬蟲,就不能經過修改user-agent或ip代理來模擬不一樣人的訪問,由於cookie是具備惟一性的。

所以本文代碼就出現弊端,抓取十幾回就須要人爲進行驗證,並從新抓取。但就目前爬取的圖片數量已經夠公衆號使用,因此有機會再解決吧。解決方向-能夠模擬人爲點擊認證吧。完整代碼能夠訪問github
)獲取。

最後展現下爬取的效果:
pixabay-result

【關注公衆號DoCode,每日一道LeetCode,將零碎時間利用起來】

相關文章
相關標籤/搜索