Scrapy基礎(十四)————知乎模擬登錄

#-*-coding:utf-8 -*-
__author__ = "ruoniao"
__date__ = "2017/5/31 20:59"

  以前咱們經過爬取伯樂在線的文章,伯樂在線對爬取沒有什麼限制,此次爬取知乎,就有了爬取限制,首先就是
登陸限制;爲破解限制,首先就是模擬登陸html

模擬登錄首先要明白的就是session和cookie機制:   

簡單的說(我的理解):
  http是一種無狀態的協議,爲解決用戶每次都須要輸入密碼登陸的煩惱,也爲了服務器可以記住每次請求的瀏覽器,就有了會話機制,python

就是每次對話不須要問你是誰,瀏覽器只須要將服務器原先發送給瀏覽器的ID原封不動的還給服務器,這樣服務器就能夠在本身的
數據庫中查找這個ID就能夠,而只有這個ID是沒用的,若想要用戶登陸,還須要用用戶名和密碼,加密後以cookie的形式存儲在本地,web

下次請求直接發送給服務器就行正則表達式

  總之:爲了服務器和瀏覽器之間互相確認身份,服務器生成一個session_id而且保存在服務器,還有給瀏覽器一份,瀏覽器將這個session_id寫入cookie,chrome

發送給服務器,服務器對照本身保存在本地的,就能互相確認身份;不一樣的是:cookie中還帶了用戶的我的信息等數據庫

    
        cookie是存儲在本地的記錄某個網站的我的信息的機制
        session是存儲在服務器中的記錄某個瀏覽器(用戶)的信息的機制,更安全;
具體理解可參考這篇文章
  瀏覽器

不一樣的網站模擬登陸的策略不一樣,不一樣的網站要進行不一樣的分析;但都是大同小異;作過web的明白,無非就是用戶的驗證;較難的就是識別驗證碼了 

安全

 

知乎的登陸破解   

    

    1:這裏遇到了坑,由於在firebug中測試時,post到url時沒有填寫驗證碼;而經過requests post到URL
   具體參數時報錯:驗證碼錯誤,這就很納悶了;
    2:原來:當向首頁get時,由於有cookies,因此登陸時就不須要填寫驗證碼;經過代碼時沒有加cookies,須要填寫驗證碼
    而驗證碼很差識別,只能更換思路
    3: 模擬瀏覽器的行爲,若當初爲取的xsrf時get帶上cookie,下次登陸就不須要驗證碼了
    4:那麼怎麼才能將cookie post到URL呢?瞭解requests.post()方法的知道:post()可帶的參數不少
    其中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("342200377@qq.com","")
122     #更新成功後從新加載cookies
123     session.cookies.load(ignore_discard=True)
124 
125 
126 print(is_login())
相關文章
相關標籤/搜索