2 模擬登陸_Post表單方式(針對chinaunix有效,針對csdn失效,並說明緣由)

 

參考精通Python網絡爬蟲實戰php

首先,針對chinaunixhtml

import urllib.request #原書做者提供的測試url
url="http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LctlC" headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5193.400 QQBrowser/10.0.1066.400") postdata=urllib.parse.urlencode({ "username":"xiaojieshisilang", "password":"XXXXX" }).encode('utf-8') req=urllib.request.Request(url,postdata) req.add_header(headers[0],headers[1]) data=urllib.request.urlopen(req).read() #print (data)
fhandle=open("./8.html","wb") fhandle.write(data) fhandle.close() #設置要爬去的該網站下其餘網頁的網址
url2="http://bbs.chinaunix.net/forum.php?mod=guide&view=my"#這是從網頁登陸之後,才能進入的我的空間。
req2=urllib.request.Request(url2,postdata) req2.add_header(headers[0],headers[1]) data2=urllib.request.urlopen(req2).read() #print (data2)
fhandle=open("./8_2.html","wb") fhandle.write(data2) fhandle.close()

 上面的password須要你本身去註冊。node

關鍵點在於獲取用於針對post用戶名和密碼信息以後的那個URL,以及構建PostData表單字典。python

第一,如何獲取URL呢?

F12打開調試界面。git

輸入錯誤的用戶名add和密碼add,能夠看到URL信息以下:github

 

以及FormData信息以下:web

同時,咱們就能構造出chrome

postdata=urllib.parse.urlencode({
    "username":"xiaojieshisilang",
    "password":"XXXXXXXXXXX"
}).encode('utf-8')

  這裏要填入正確的用戶名和密碼。瀏覽器

最後代碼的運行結果是:打開8_html服務器

同時,8-2.html則是:

 

 

關於構建postData時的名稱,除了用F12調試的方式。

另一種是,直接放在文本框,用右鍵檢查的方式,從而定位到相應的源碼,取出表單的名稱,好比:username和password。

下面針對CSDN進行相似操做

輸入錯誤的用戶名和密碼

 

 

這個時候,查看Form Data,即表單數據。

import urllib.request
url="https://passport.csdn.net/account/verify" headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5193.400 QQBrowser/10.0.1066.400") postdata=urllib.parse.urlencode({ "username":"183247166@qq.com", "password":"XXXXXX" }).encode('utf-8') req=urllib.request.Request(url,postdata) req.add_header(headers[0],headers[1]) data=urllib.request.urlopen(req).read() #print (data)
fhandle=open("./8.html","wb") fhandle.write(data) fhandle.close() #設置要爬去的該網站下其餘網頁的網址
url2="https://download.csdn.net/my"#這是從網頁登陸之後,才能進入的我的空間。
req2=urllib.request.Request(url2,postdata) req2.add_header(headers[0],headers[1]) data2=urllib.request.urlopen(req2).read() #print (data2)
fhandle=open("./8_2.html","wb") fhandle.write(data2) fhandle.close()

結果是:

 

不能正確登陸csdn,而且爬蟲。

這說明,csdn的驗證機制,不是簡單的一個post就能完成的。

失敗緣由分析

https://blog.csdn.net/yanggd1987/article/details/52127436

這個連接是前人的博客。你們同時能夠參考Python3網絡爬蟲開發實戰一書中的觀點,要先獲取隱藏表單中的值,而後再構造post數據,用python模擬登陸。

可是,最新版本,截止到當前時間2018年7月13日09:54:03時,csdn的驗證機制變了。具體以下:

用F12進行調試時,追蹤post請求數據,能夠看到,相比於之前各個博文中的多了一個fkid值。

以前的:

values = {

        "username":"用戶名",

        "password":"密碼",

        "lt":lt,

        "execution":execution,

        "_eventId":"submit"
}

  如今的:

嘗試抓取隱藏表單數據。咱們F12調試的時候,選擇Preseve log選項,選擇chrome瀏覽器。

刷新csdn的登陸界面,能夠看到開發者模式記錄的第一個請求實Get請求,訪問的是https://passport.csdn.net/account/login,相似於github的機制,這個時候,訪問這個頁面,會忘隱藏表單中填入相關的數據。具體請求的信息以下:

 

服務器會Response一些set_cookie的信息,要求瀏覽器客戶端設置cookie文件。

這些暫時不用考慮。

咱們點擊「掃碼登陸」,而後鼠標放在密碼的文本框上,右鍵選擇檢查,能夠看到:

FORM中隱藏表單中的lt,execution等都已經填入了相關值。你能夠進一步作實驗,每次刷新login頁面,這些值都會變化。咱們發現fkid這個新屬性(csdn最新添加的屬性)並無值。還是value。咱們參考Python3網絡爬蟲開發實戰中的方法編寫以下代碼取出隱藏表單的值:

這裏面用到XPATH。

如何知道XPATH,直接在F12模式的表單input位置,右鍵選擇copy XPATH便可。

import urllib.request
import requests
from lxml import etree
#獲取加載的it/execution/fkid等的值
headers = {
            'Referer': 'https://www.csdn.net/',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5193.400 QQBrowser/10.0.1066.400',
            'Host': 'passport.csdn.net'
        }
login_url="https://passport.csdn.net/account/login"
session = requests.Session()
response = session.get(login_url, headers=headers)
selector=etree.HTML(response.text)
execution=selector.xpath('//input[@name="execution"]/@value')[0]
print (execution)
_eventId=selector.xpath('//input[@name="_eventId"]/@value')[0]
print (_eventId)
lt=selector.xpath('//input[@name="lt"]/@value')[0]
print (lt)
fkid=selector.xpath('//*[@id="fkid"]/@value')[0]
print (fkid)

能夠看到,fkid的值根本不存在。這個時候,咱們就要思考post數據中明明發出了fkid值,爲何這裏不存在。(由於運行js代碼更新的表單數據是不能經過在網頁中抓取的。

咱們查看網頁預加載的幾個js文件,找到以下js代碼:

https://csdnimg.cn/release/passport/history/js/apps/login.js?v=1.3.9

它裏面有:

 

也即初始化的時候,就爲登陸按鈕註冊了一個onclick函數,執行的內容是,檢查用戶名,檢查密碼,而後計算fkid的值。

咱們下斷點,而後在瀏覽器中隨便輸入abd做爲用戶名,隨便輸入abd做爲密碼。

而後跟蹤到81行代碼處。

到達斷點位置之後,在console控制檯取出真正的fkid值。

 

SMSdk是csdn開發者加入到window屬性中的。

將鼠標放在SMSdk上,會顯示其中的getDeviceId方法,

鼠標放在getDeviceId上,右鍵show function definition

能夠看到代碼被混淆了,目的的就是防止被別人看。

用python寫一個功能徹底相同的代碼不太現實。若是知道機制,還能夠用python從網頁中取出某些元素,而後算出fkid,傳回服務器,同用戶名、密碼一塊兒造成驗證。可是如今不知道機制,就連計算的js代碼都被混淆了。

因而:第一,輸入是什麼,也就是從頁面中取出哪些值進行計算,這個不肯定。我猜想csdn取得就是webflow的流水號,你能夠看csdn的登陸頁面的源碼。第二,運算過程怎麼樣,也不知道。

這個時候,只能用python執行js程序。這個時候想到了node.js。

具體過程不在展開。你會發現遇到一個問題,就是直接調用混淆化後的js代碼,會提示window沒有定義。由於node.js中使用的是global做爲全局屬性,而window則是瀏覽器中才有的。

也就是說,會發現無法用node.js執行這些js代碼。因此這種直接用python去模擬這麼複雜的驗證過程,比較困難。選擇採用一些可以模擬瀏覽器的框架。注意,不單純是模擬發送請求,接收返回的urllib包,而是模擬瀏覽器行爲!這些就是針對相似csdn這種有複雜驗證機制的爬蟲。

因而就產生了第三篇博文,

3 使用selenium模擬登陸csdn

用selenium進行模擬登陸,保存cookie。

相關文章
相關標籤/搜索