python网络爬虫系列(十一)——JS的解析
JS的解析
學(xué)習(xí)目標(biāo):
1 確定js的位置
對(duì)于前面人人網(wǎng)的案例,我們知道了url地址中有部分參數(shù),但是參數(shù)是如何生成的呢?
毫無(wú)疑問(wèn),參數(shù)肯定是js生成的,那么如何獲取這些參數(shù)的規(guī)律呢?通過(guò)下面的學(xué)習(xí)來(lái)了解
1.1 觀察按鈕的綁定js事件
通過(guò)點(diǎn)擊按鈕,然后點(diǎn)擊Event Listener,部分網(wǎng)站可以找到綁定的事件,對(duì)應(yīng)的,只需要點(diǎn)擊即可跳轉(zhuǎn)到j(luò)s的位置
1.2 通過(guò)search all file 來(lái)搜索
部分網(wǎng)站的按鈕可能并沒(méi)有綁定js事件監(jiān)聽(tīng),那么這個(gè)時(shí)候可以通過(guò)搜索請(qǐng)求中的關(guān)鍵字來(lái)找到j(luò)s的位置,比如livecell
點(diǎn)擊美化輸出選項(xiàng)
可以繼續(xù)在其中搜索關(guān)鍵字
2 觀察js的執(zhí)行過(guò)程
找到j(luò)s的位置之后,我們可以來(lái)通過(guò)觀察js的位置,找到j(luò)s具體在如何執(zhí)行,后續(xù)我們可以通過(guò)python程序來(lái)模擬js的執(zhí)行,或者是使用類(lèi)似js2py直接把js代碼轉(zhuǎn)化為python程序去執(zhí)行
觀察js的執(zhí)行過(guò)程最簡(jiǎn)單的方式是添加斷點(diǎn)
添加斷點(diǎn)的方式:在左邊行號(hào)點(diǎn)擊即可添加,對(duì)應(yīng)的右邊BreakPoints中會(huì)出現(xiàn)現(xiàn)有的所有斷點(diǎn)
添加斷點(diǎn)之后繼續(xù)點(diǎn)擊登錄,每次程序在斷點(diǎn)位置都會(huì)停止,通過(guò)如果該行有變量產(chǎn)生,都會(huì)把變量的結(jié)果展示在Scoope中
在上圖的右上角有1,2,3三個(gè)功能,分別表示:
- 1:繼續(xù)執(zhí)行到下一個(gè)斷點(diǎn)
- 2:進(jìn)入調(diào)用的函數(shù)中
- 3:從調(diào)用的函數(shù)中跳出來(lái)
3 js2py的使用
在知道了js如何生成我們想要的數(shù)據(jù)之后,那么接下來(lái)我們就需要使用程序獲取js執(zhí)行之后的結(jié)果了
3.1 js2py的介紹
js2py是一個(gè)js的翻譯工具,也是一個(gè)通過(guò)純python實(shí)現(xiàn)的js的解釋器,github上源碼與示例
3.2 js的執(zhí)行思路
js的執(zhí)行方式大致分為兩種:
但是在使用python程序?qū)崿F(xiàn)js的執(zhí)行時(shí)候,需要觀察的js的每一個(gè)步驟,非常麻煩,所以更多的時(shí)候我們會(huì)選擇使用類(lèi)似js2py的模塊去執(zhí)行js,接下來(lái)我們來(lái)使用js2py實(shí)現(xiàn)人人網(wǎng)登錄參數(shù)的獲取
3.3 具體的實(shí)現(xiàn)
定位進(jìn)行登錄js代碼
formSubmit: function() {var e, t = {};$(".login").addEventListener("click", function() {t.phoneNum = $(".phonenum").value,t.password = $(".password").value,e = loginValidate(t),t.c1 = c1 || 0,e.flag ? ajaxFunc("get", "http://activity.renren.com/livecell/rKey", "", function(e) {var n = JSON.parse(e).data;if (0 == n.code) {t.password = t.password.split("").reverse().join(""),setMaxDigits(130);var o = new RSAKeyPair(n.e,"",n.n), r = encryptedString(o, t.password);t.password = r,t.rKey = n.rkey} elsetoast("公鑰獲取失敗"),t.rKey = "";ajaxFunc("post", "http://activity.renren.com/livecell/ajax/clog", t, function(e) {var e = JSON.parse(e).logInfo;0 == e.code ? location.href = localStorage.getItem("url") || "" : toast(e.msg || "登錄出錯(cuò)")})}) : toast(e.msg)})}從代碼中我們知道:
實(shí)現(xiàn)思路:
使用session發(fā)送rKey獲取登錄需要信息
- url: http://activity.renren.com/livecell/rKey
- 方法: get
根據(jù)獲取信息對(duì)密碼進(jìn)行加密
2.1 準(zhǔn)備用戶(hù)名和密碼
2.2 使用js2py生成js的執(zhí)行環(huán)境:context
2.3 拷貝使用到j(luò)s文件的內(nèi)容到本項(xiàng)目中
2.4 讀取js文件的內(nèi)容,使用context來(lái)執(zhí)行它們
2.5 向context環(huán)境中添加需要數(shù)據(jù)
2.6 使用context執(zhí)行加密密碼的js字符串
2.7 通過(guò)context獲取加密后密碼信息
使用session發(fā)送登錄請(qǐng)求
-
URL: http://activity.renren.com/livecell/ajax/clog
-
請(qǐng)求方法: POST
-
數(shù)據(jù):
phoneNum: xxxxxxx password: (加密后生產(chǎn)的) c1: 0 rKey: rkey請(qǐng)求獲取的
具體代碼
需要提前下載幾個(gè)js文件到本地:
BigInt.js
RSA.js
Barrett.js
import requests import json import js2py# - 實(shí)現(xiàn)思路: # - 使用session發(fā)送rKey獲取登錄需要信息 # - url: http://activity.renren.com/livecell/rKey # - 方法: get # 獲取session對(duì)象 session = requests.session() headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36","X-Requested-With": "XMLHttpRequest","Content-Type":"application/x-www-form-urlencoded" } # 設(shè)置session的請(qǐng)求頭信息 session.headers = headersresponse = session.get("http://activity.renren.com/livecell/rKey") # print(response.content.decode()) n = json.loads(response.content)['data']# - 根據(jù)獲取信息對(duì)密碼進(jìn)行加密 # - 準(zhǔn)備用戶(hù)名和密碼 phoneNum = "131..." password = "****" # - 使用js2py生成js的執(zhí)行環(huán)境:context context = js2py.EvalJs() # - 拷貝使用到j(luò)s文件的內(nèi)容到本項(xiàng)目中 # - 讀取js文件的內(nèi)容,使用context來(lái)執(zhí)行它們 with open("BigInt.js", 'r', encoding='utf8') as f:context.execute(f.read())with open("RSA.js", 'r', encoding='utf8') as f:context.execute(f.read()) with open("Barrett.js", 'r', encoding='utf8') as f:context.execute(f.read())# - 向context環(huán)境中添加需要數(shù)據(jù) context.t = {'password': password} context.n = n # - 執(zhí)行加密密碼的js字符 js = '''t.password = t.password.split("").reverse().join(""),setMaxDigits(130);var o = new RSAKeyPair(n.e,"",n.n), r = encryptedString(o, t.password);''' context.execute(js) # - 通過(guò)context獲取加密后密碼信息 # print(context.r) password = context.r # - 使用session發(fā)送登錄請(qǐng)求 # - URL: http://activity.renren.com/livecell/ajax/clog # - 請(qǐng)求方法: POST # - 數(shù)據(jù): # - phoneNum: 15565280933 # - password: (加密后生產(chǎn)的) # - c1: 0 # - rKey: rkey請(qǐng)求獲取的 data = {'phoneNum': '131....','password': password,'c1':0,'rKey':n['rkey'] }# print(session.headers) response = session.post("http://activity.renren.com/livecell/ajax/clog", data=data) print(response.content.decode())# 訪(fǎng)問(wèn)登錄的資源 response = session.get("http://activity.renren.com/home#profile") print(response.content.decode())小結(jié)
- 需要準(zhǔn)備js的內(nèi)容
- 生成js的執(zhí)行環(huán)境
- 在執(zhí)行環(huán)境中執(zhí)行js的字符串,傳入數(shù)據(jù),獲取結(jié)果
【綜合案例】:有道翻譯
知識(shí)點(diǎn):
1、python中的哈希處理:md5()
分析過(guò)程:進(jìn)行抓包:
接下來(lái)通過(guò)search相關(guān)內(nèi)容進(jìn)行尋找:
運(yùn)行結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的python网络爬虫系列(十一)——JS的解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 三、PHP基础——HTTP协议 文件编
- 下一篇: 已安装Anaconda情况下,命令行pi