摘要:介紹了使用Scrapy登錄簡單網站的流程,不涉及驗證碼破解
簡單登錄
很多時候,你都會發現你需要爬取數據的網站都有一個登錄機制,大多數情況下,都要求你輸入正確的用戶名和密碼。現在就模擬這種情況,在瀏覽器打開網頁:http://127.0.0.1:9312/dynamic,首先打開調試器,然后點擊Elements標簽,查看登錄表單的源代碼
再點擊Network標簽,然后在用戶名框里輸入user,在密碼框里輸入pass,再點擊login按鈕
點擊調試器里的login頁面,觀察下面的情況
點擊調試器里的gated頁面,觀察下面的情況
HTTP的cookie是由服務器發送給瀏覽器,由一些文本和數字組成的字符串,之后瀏覽器訪問服務器的任何請求里都會帶着這個cookie來標識你的身份和session,從而能夠讓你修改在這個網站上的個人信息。
總的來說,一個登錄操作會包含幾個從瀏覽器到服務器的往返操作,而Scrapy會自動處理這些操作。
login.py的源代碼地址:
繼續在上面的名為easy的spider上擴展代碼,首先將easy.py復制為login.py,然后做以下修改:
-
將spider的名稱修改為login
-
這里會使用FormRequest類來登錄,這個類與之前的Request類很相似,只是帶有額外的formdata參數用來傳送登錄的表單信息(用戶名和密碼),為了使用這個類,需要使用以下語句導入:from scrapy.http import FormRequest
-
然后用startrequests()函數來代替starturls語句,這樣做的原因是我們需要定制更多的參數,最后的函數是這樣的
# Start with a login request def start_requests(self): return [ FormRequest( "http://web:9312/dynamic/login", formdata={"user": "user", "pass": "pass"} #formdata字典里的key名就是第一張圖中用紅線標注的input標簽中的name值 )]
就這么簡單,Scrapy會自動為我們處理cookie,只要我們登錄成功了,它就會像一個瀏覽器一樣自動傳送cookie.
現在運行這個spider:scrapy crawl login
可以看到上面紅線處首先向login頁面提交了一個POST請求,然后重定向到了gated頁面,再用一個GET請求得到了該頁面,如果用錯了用戶名和密碼,就會得到錯誤的結果
上面是一個極其簡單的登錄機制,大多數網站其實會使用更加復雜的登錄機制,下面的這個例子就使用了隱藏數據
帶有隱藏數據的登錄
在瀏覽器打開頁面:http://127.0.0.1:9312/dynamic/nonce,然后用調試器定位到登錄按鈕,可以看到如下界面
與第一個登錄情況不同的是可以看到這個表單有一個叫做nonce的隱藏字段,當你按下Login按鈕時,向服務器發送的數據包括用戶名和密碼,還有這個屬性的值。你不可能猜到這個屬性的值,因為這是一個一次性的隨機數,這意味着你在Scrapy登錄時需要兩個發送兩個請求,首先得到表單里的數據,然后再填充登錄數據,Scrapy已經集成了這些功能。
noncelogin.py文件的源代碼地址:
將之前的login.py文件復制為noncelogin.py文件,做如下改變:
-
導入Request:from scrapy.http import Request
-
將spider的名稱修改為noncelogin
-
將start_request函數修改如下
#這個函數返回了一個Request,在這個Request中已經指定了回調函數為parse_welcome,所以會把response傳送到parse_welcome函數上 def start_requests(self): return [ Request("http://web:9312/dynamic/nonce", callback=self.parse_welcome) ]
- 增加一個parse_welcome函數如下
#接收到了包含表單全部數據的response(此時用戶名和密碼都是空,但是已經獲取到了隱藏字段nonce的值),然后填充用戶名和密碼再登錄 def parse_welcome(self, response): return FormRequest.from_response( response, formdata={"user": "user", "pass": "pass"} )
運行該spider:scrapy crawl noncelogin
之前所說的登錄過程發送了兩個請求指的就是上面標記了順序1和2的兩個請求(一個GET,一個POST)
值得注意的是form_response函數
(http://doc.scrapy.org/en/1.0/topics/request-response.html#topics-request-response-ref-request-userlogin),這個函數值得仔細研究,如果在登錄頁面有多個表單,此時就要用參數來指定究竟把用戶名和密碼填充到哪個表單上,同時,函數也默認模擬了對登錄按鈕的點擊行為,要是網站使用了javascript來控制登錄,此時函數的默認點擊行為就可能出錯,通過設置dont_click為True來禁止模擬點擊.
上面只是使用了兩個步驟來登錄,但在面對更加復雜的登錄方式時就需要組織更多的步驟.