Scrapy基礎(十四)————知乎模擬登陸
#-*-coding:utf-8 -*-
__author__ = "ruoniao"
__date__ = "2017/5/31 20:59"
之前我們通過爬取伯樂在線的文章,伯樂在線對爬取沒有什麽限制,這次爬取知乎,就有了爬取限制,首先就是
登錄限制;為破解限制,首先就是模擬登錄
模擬登陸首先要明白的就是session和cookie機制:
簡單的說(個人理解):
http是一種無狀態的協議,為解決用戶每次都需要輸入密碼登錄的煩惱,也為了服務器能夠記住每次請求的瀏覽器,就有了會話機制,
就是每次對話不需要問你是誰,瀏覽器只需要將服務器原先發送給瀏覽器的ID原封不動的還給服務器,這樣服務器就可以在自己的
下次請求直接發送給服務器就行
總之:為了服務器和瀏覽器之間互相確認身份,服務器生成一個session_id並且保存在服務器,還有給瀏覽器一份,瀏覽器將這個session_id寫入cookie,
發送給服務器,服務器對照自己保存在本地的,就能互相確認身份;不同的是:cookie中還帶了用戶的個人信息等
cookie是存儲在本地的記錄某個網站的個人信息的機制
session是存儲在服務器中的記錄某個瀏覽器(用戶)的信息的機制,更安全;
不同的網站模擬登錄的策略不同,不同的網站要進行不同的分析;但都是大同小異;做過web的明白,無非就是用戶的驗證;較難的就是識別驗證碼了
知乎的登錄破解:
1:這裏遇到了坑,因為在firebug中測試時,post到url時沒有填寫驗證碼;而通過requests post到URL
具體參數時報錯:驗證碼錯誤,這就很納悶了;
2:原來:當向首頁get時,因為有cookies,所以登錄時就不需要填寫驗證碼;通過代碼時沒有加cookies,需要填寫驗證碼
而驗證碼不好識別,只能更換思路
3: 模擬瀏覽器的行為,若當初為取的xsrf時get帶上cookie,下次登錄就不需要驗證碼了
其中cookies= {}或CookieJar
5:將cookies以字典的形式post方便操作,只需要在firebug中的cookies復制為字典的格式
以CookieJar的形式:因為cookie是保存在硬盤的,可以參考這篇博文
6:因為cookie是有生存周期的額,為了下面重新登錄,可以將登錄後的cookie以txt的形式保存在本地,下次直接load就可以
實例代碼註釋
1 import requests 2 #適合python2和python3版本的導包 3 try: 4 import cookielib 5 except: 6 import http.cookiejar as cookielib 7 import re 8 from urllib import parse, request 9 10 #使用會話機制向url發送request,提高效率,不必每次都發請求(類比瀏覽器直接在本標簽頁操作,不需重新產生新的標簽頁) 11 session = requests.session() 12 #將會話產生的cookies保存在本地 13 session.cookies = cookielib.LWPCookieJar(filename="cookies.txt") 14 15 #瀏覽器版本信息,目的是偽裝成一個瀏覽器,讓服務器認為我們的代碼是一個瀏覽器請求而不是爬蟲,避免被拒絕 16 headers = { 17 "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0", 18 "Host":"www.zhihu.com", 19 "Referer":"https://www.zhihu.com/", 20 } 21 22 #獲取登錄xsrf 23 def get_xsrf(): 24 25 url = "https://www.zhihu.com/#signin" 26 27 try: 28 #帶上cookie,避免產生驗證碼識別 29 req = session.get(url=url,cookies=cookies,headers=headers) 30 #通過正則表達式解析出 xsrf 類比csrf機制 31 xsrf = re.findall(‘<input type="hidden" name="_xsrf" value="(.*?)"/>‘,req.text) 32 if xsrf: 33 xsrf = xsrf[0] 34 print(xsrf) 35 return xsrf 36 else: 37 return xsrf 38 except Exception as e: 39 print(e) 40 print("failed download") 41 42 43 44 #知乎登錄 45 def zhihu_login(account,password): 46 47 #首先獲取xsrf 48 xsrf = get_xsrf() 49 #判斷是手機號:以手機號登錄,提交表單和提交URL不同,構造不同的URL和表單 50 if re.match("\d{10}",account): 51 52 url = "https://www.zhihu.com/login/phone_num" 53 data={ 54 "_xsrf":xsrf, 55 ‘remember_me‘: ‘true‘, 56 "password":password, 57 "phone_num":account 58 } 59 if ‘@‘ in account: 60 url = "https://www.zhihu.com/login/email" 61 data={ 62 "_xsrf":xsrf, 63 ‘remember_me‘: ‘true‘, 64 "password":password, 65 "email":account 66 } 67 #將獲取到的xsrf加載到cookie中 68 cookies["_xsrf"] = xsrf 69 #帶上表單,頭信息,cookies申請登錄 70 r = session.post(url=url,data=data,headers=headers,cookies=cookies) 71 print(r.text) 72 #登錄成功將cookies保存到本地 73 session.cookies.save() 74 75 76 #獲取首頁;登錄後可直接獲取,因為session中已經(帶了)加載了cookie 77 def get_index(): 78 response = session.get("https://www.zhihu.com/",headers=headers) 79 print(response.status_code) 80 #將首頁寫入本地文件 81 with open("index_page.html","wb") as f: 82 f.write(response.text.encode("utf-8")) 83 print("write ok") 84 85 #查看登錄狀態;向一個只有登錄的頁面get,若登錄會返回200;否則304,會重定向到登錄頁(重定向後會返回200) 86 def is_login(): 87 url = "https://www.zhihu.com/inbox" 88 #allow_redirects 禁止重定向 89 response = session.get(url=url,headers=headers,allow_redirects=False) 90 #判斷是否登錄 91 if response.status_code != 200: 92 return False 93 else: 94 return True 95 96 97 #先嘗試本地cookie登錄,不成功使用瀏覽器copy下來的cookies重新登錄,生成本地cookies 98 try: 99 #先嘗試加載之前保存在本地的cookies 100 session.cookies.load(ignore_discard=True) 101 print("cookies 已記載") 102 except: 103 #沒加載就重新登錄 104 print("cookie 未加載") 105 #這個cookie是從firebug中復制來的 106 cookies = { 107 "d_c0":"", 108 "l_cap_id":"", 109 "r_cap_id":"", 110 "cap_id":"", 111 "_zap":"", 112 "__utmc":"", 113 "__utmb":"", 114 "__utmv":"", 115 "__utma":"", 116 "__utmz":"", 117 "q_c1":""118 119 } 120 #調用登錄函數,成功後會更新cookie到本地 121 zhihu_login("[email protected]","19971013zf") 122 #更新成功後重新加載cookies 123 session.cookies.load(ignore_discard=True) 124 125 126 print(is_login())
Scrapy基礎(十四)————知乎模擬登陸