相比上文,主要多了一個加密密碼的處理
思路流程
1.首先通過瀏覽器(這裏用的是360瀏覽器)訪問有道登陸界面(‘http://account.youdao.com/loginservice=dict&back_url=http://dict.youdao.com/wordbook/wordlist%3Fkeyfrom%3Dlogin_from_dict2.index),
2.點擊F12,並點擊F5刷新,單擊Network可以看到如下get請求,同時勾選Preserve log
3.隨便輸入一個賬號密碼後,點擊登陸,找到Post請求(注意觀察,此時的post請求對應的網址是‘https://logindict.youdao.com/login/acc/login’)
4.找到From Data ,即爲post請求所要提交的數據,多次嘗試輸入賬號密碼,可以發現變化的量只有'ru','username','password',細心的朋友發現password與自己輸入的明顯不同,這是由於密碼經過了加密處理。
5.先處理參數‘ru’,同時點擊ctrl+shift+F,在搜索框內輸入'ru',在get請求中找到我們所需的參數,由此可以推測,在每次請求、響應後,服務器都會給出一個‘ru’對應的數值,作爲下一次post請求的表單參數。大家可以進行驗證,記錄本次響應的'ru'值,觀察下一次請求所需的'ru'值,發現是一致的。
6.最後也是最難的密碼加密,通過嘗試,如果直接給password傳入正確的密碼,爬蟲模擬登陸是失敗的。可以參考有道登陸解密。
搜索password,最後一行發現敏感內容,可以猜測是通過md5加密
再次搜索md5,發現在js文件裏出現了對應函數,
我們將js文件保存,後通過python庫execjs調用函數並求出加密後的值,具體可以參考Python3 ExecJS爬坑
最後就可以通過Session的方法進行模擬登陸了!
實操
1.首先導入必要的庫
import requests
import bs4
import execjs
2.提取'ru'的值
#有道登陸網址
url='http://account.youdao.com/login?service=dict&back_url=http://dict.youdao.com/wordbook/wordlist%3Fkeyfrom%3Dlogin_from_dict2.index'
#創建Session對象
sess=requests.Session()
#初次訪問
res=sess.get(url,allow_redirects=True)
#將複雜的html轉化爲樹形結構,方便提取
soup=bs4.BeautifulSoup(res.content)
ru=soup.find('form').find_all('input')[4]['value']
print(ru)
輸出結果如下:
3.獲取加密後的密碼
#打開保存的js文件
with open('logincom.js','r',encoding='utf-8') as f:
js_str=f.read()
ctx = execjs.compile(js_str)
#輸入自己的賬號密碼
password='XXXXXXX'
#ctx.call()的兩個參數依此爲調用函數和調用函數所需的值
password = ctx.call("hex_md5", password)
print(password)
輸出如下:
4.構建表單數據,datas
datas={'app':'web',
'tp':'urstoken',
'cf':3,
'fr':1,
'ru':ru,
'product':'DICT',
'type':1,
'um':'true',
#輸入自己的賬號
'username':'[email protected]',
'password':password
}
5.模擬登陸
#post請求網址
url1='https://logindict.youdao.com/login/acc/login'
#發出post請求
res=sess.post(url1,data=datas,allow_redirects=True)
soup=bs4.BeautifulSoup(res.content)
print(soup)
將輸出結果複製粘貼到xxx.txt文件內,保存爲.html格式,然後雙擊打開,得到如下(如果出現亂碼,將txt編碼格式改爲‘utf-8’後再保存)
完整代碼如下:
import requests
import bs4
import execjs
url='http://account.youdao.com/login?service=dict&back_url=http://dict.youdao.com/wordbook/wordlist%3Fkeyfrom%3Dlogin_from_dict2.index'
sess=requests.Session()
res=sess.get(url)
soup=bs4.BeautifulSoup(res.content)
ru=soup.find('form').find_all('input')[4]['value']
with open('logincom.js','r',encoding='utf-8') as f:
js_str=f.read()
ctx = execjs.compile(js_str)
password='xxxxxxxxx'
password = ctx.call("hex_md5", password)
datas={'app':'web',
'tp':'urstoken',
'cf':3,
'fr':1,
'ru':ru,
'product':'DICT',
'type':1,
'um':'true',
'username':'[email protected]',
'password':password
}
url1='https://logindict.youdao.com/login/acc/login'
res=sess.post(url1,data=datas)
soup=bs4.BeautifulSoup(res.content)
print(soup)