日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python网络爬虫系列(十一)——JS的解析

發(fā)布時(shí)間:2024/7/5 python 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python网络爬虫系列(十一)——JS的解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

JS的解析

學(xué)習(xí)目標(biāo):
  • 了解 定位js的方法
  • 了解 添加斷點(diǎn)觀察js的執(zhí)行過(guò)程的方法
  • 應(yīng)用 js2py獲取js的方法
  • 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í)行方式大致分為兩種:

  • 在了解了js內(nèi)容和執(zhí)行順序之后,通過(guò)python來(lái)完成js的執(zhí)行過(guò)程,得到結(jié)果
  • 在了解了js內(nèi)容和執(zhí)行順序之后,使用類(lèi)似js2py的模塊來(lái)執(zhí)js代碼,得到結(jié)果
  • 但是在使用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)})}
    從代碼中我們知道:
  • 我們要登錄需要對(duì)密碼進(jìn)行加密和獲取rkey字段的值
  • rkey字段的值我們直接發(fā)送請(qǐng)求rkey請(qǐng)求就可以獲得
  • 密碼是先反轉(zhuǎn)然后使用RSA進(jìn)行加密, js代碼很復(fù)雜, 我們希望能通過(guò)在python中執(zhí)行js來(lái)實(shí)現(xiàn)
  • 實(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é)

  • 通過(guò)在chrome中觀察元素的綁定事件可以確定js
  • 通過(guò)在chrome中search all file 搜索關(guān)鍵字可以確定js的位置
  • 觀察js的數(shù)據(jù)生成過(guò)程可以使用添加斷點(diǎn)的方式觀察
  • js2py的使用
    • 需要準(zhǔn)備js的內(nèi)容
    • 生成js的執(zhí)行環(huán)境
    • 在執(zhí)行環(huán)境中執(zhí)行js的字符串,傳入數(shù)據(jù),獲取結(jié)果
  • 【綜合案例】:有道翻譯
    知識(shí)點(diǎn):
    1、python中的哈希處理:md5()

    import js2pyimport hashlibdata = 'python37'# 創(chuàng)建hash對(duì)象 md5 = hashlib.md5()# 向hash對(duì)象中添加需要做hash運(yùn)算的字符串 md5.update(data.encode())# 獲取字符串的hash值 result = md5.hexdigest() print(result)


    分析過(guò)程:進(jìn)行抓包:



    接下來(lái)通過(guò)search相關(guān)內(nèi)容進(jìn)行尋找:

    import requests import hashlib import time import random import jsonclass Youdao(object):def __init__(self):self.url='http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'self.headers = {'User-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36','Cookie': "OUTFOX_SEARCH_USER_ID=-1628507307@10.108.160.17; OUTFOX_SEARCH_USER_ID_NCOO=1058312939.7835485; _ntes_nnid=7c814c8475605712d1b72e0446d52cf2,1590040388694; JSESSIONID=aaaRXPpDC6D_h4ZVYTYmx; ___rl__test__cookies=1594283781148",'Referer': 'http://fanyi.youdao.com/'}self.formdata = Noneself.word = input("請(qǐng)輸入需要翻譯的單詞或句子:")def generate_formdata(self):'''ts: r = "" + (new Date).getTime(),salt: ts + parseInt(10 * Math.random(), 10),sign: n.md5("fanyideskweb" + e + i + "mmbP%A-r6U3Nw(n]BjuEU")'''ts = str(int(time.time()*1000))# print(ts)salt = ts + str(random.randint(0,9))# print(salt)temstr = "fanyideskweb" + self.word + salt + "mmbP%A-r6U3Nw(n]BjuEU"# 創(chuàng)建hash對(duì)象md5 = hashlib.md5()# 向hash對(duì)象中添加需要做hash運(yùn)算的字符串.注意,字符串需要轉(zhuǎn)換成bytes類(lèi)型md5.update(temstr.encode())# 將結(jié)果轉(zhuǎn)成16進(jìn)制sign = md5.hexdigest()self.formdata = {"i": self.word,"from": "AUTO","to": "AUTO","smartresult": "dict","client": "fanyideskweb","salt": salt,"sign": sign,"ts": ts,"bv": "02a6ad4308a3443b3732d855273259bf","doctype": "json","version": "2.1","keyfrom": "fanyi.web","action": "FY_BY_REALTlME"}def get_data(self):response = requests.post(self.url,data=self.formdata,headers =self.headers)return response.contentdef parse_data(self,data):# print(type(data.decode()))str = data.decode()# print(type(json.loads(str)))dict_data = json.loads(str)print("有道翻譯結(jié)果:" + dict_data['translateResult'][0][0]['tgt'])def run(self):# url# headers# formdataself.generate_formdata()# print(self.formdata)# 發(fā)送請(qǐng)求,獲取響應(yīng)data = self.get_data()# print(data)# 解析數(shù)據(jù)self.parse_data(data)if __name__ == '__main__':youdao = Youdao()youdao.run()

    運(yùn)行結(jié)果:

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的python网络爬虫系列(十一)——JS的解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。