python 爬蟲進階 - js逆向

前言

首先我們需要了解一下 Python基本語法默垄、爬蟲庫,html的查詢惜犀,數(shù)據(jù)的處理與保存

Python

https://www.runoob.com/python/python-tutorial.html

  • 基礎(chǔ)知識 語法與特性

requests

https://www.cnblogs.com/lanyinhao/p/9634742.html

  • 使用Apache2 licensed 許可證的HTTP庫不从,代替了urllib
    支持HTTP連接保持和連接池,支持使用cookie保持會話把曼,支持文件上傳,支持自動響應(yīng)內(nèi)容的編碼漓穿,支持國際化的URL和POST數(shù)據(jù)自動編碼祝迂。

Beautiful Soup

https://cuiqingcai.com/1319.html

  • 提供一些簡單的、python式的函數(shù)用來處理導(dǎo)航器净、搜索、修改分析樹等功能当凡。

爬蟲與js逆向

百度翻譯

百度翻譯爬蟲山害,通過百度翻譯接口查詢

分析

  • 打開百度翻譯

url : https://fanyi.baidu.com/#en/zh/

分析流程

  1. 將瀏覽器切換至手機端,這樣查看請求的參數(shù)可能會較少沿量,點擊下圖中的按鈕:
image.png
image.png
  1. 查看請求接口
image.png
image.png

image.png
image.png

image.png
image.png
  1. 查看請求參數(shù)是否有變化
  • 圖一:
image.png
image.png
  • 圖二:
image.png
image.png

經(jīng)過分析浪慌,我們發(fā)現(xiàn)這里有兩個參數(shù)發(fā)生變化,經(jīng)過推斷朴则,這里的參數(shù)可能是使用js生成的权纤,所以我們這里要對接口進行分析,破解,得到這里的值

分析結(jié)果

--分析目標--- ----分析結(jié)果-------------------
請求URL分析 https://fanyi.baidu.com/v2transapi
請求方式分析 POST
請求參數(shù)分析 參看請求參數(shù)分析
請求頭分析 參看請求頭分析
請求參數(shù)分析
參數(shù)KEY 分析結(jié)果
query 翻譯單詞(變化)
from en(固定值不變)
to zh(固定值不變)
token 900aa0a84929561d52bbee8c9222c0aa(經(jīng)過請求測試汹想,我們發(fā)現(xiàn)可以為固定值)
sign 54706.276099

JS 逆向流程

注意: 在js逆向中外邓,不是你要精通js才可以js逆向,你要懂一點js就可以做逆向古掏,重要的逆向思維损话,對問題的思考方式

chrome 調(diào)試技巧

  1. search 打開查詢面板
  2. 查詢面板可以通過關(guān)鍵字查找所有出現(xiàn)關(guān)鍵字地方的代碼
  3. 點擊跟蹤代碼并且可以把代碼格式化
  4. 對格式化的代碼進行設(shè)置斷點
  5. 鼠標光標移動到上面可以查看當前運行代碼變量值,函數(shù)原始代碼地方等等
JS 逆向流程
  1. 通過關(guān)鍵詞切入到代碼中槽唾,切入到發(fā)送請求的代碼行丧枪,通過請求的url中提取關(guān)鍵字
  2. 在發(fā)送請求的代碼添加斷點,并且觸發(fā)發(fā)送請求庞萍,確認尋找的代碼是否正確
  3. 往上逆向拧烦,尋找目標參數(shù)以及生成邏輯
  4. 利用js2py模擬執(zhí)行生成邏輯獲取想要的內(nèi)容

根據(jù)逆向流程查找我們所需的js代碼

  1. 搜索關(guān)鍵字
image.png
image.png
  1. 跟進代碼,分析AJAX請求
image.png
image.png
  1. 查找我們需要的值
image.png
image.png
  • 準確的找到我們需要的值
image.png
image.png
  • 復(fù)制我們需要的js代碼
  • 代碼如下:
function e(r) {
        var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
        if (null === o) {
            var t = r.length;
            t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr(-10, 10))
        } else {
            for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)
                "" !== e[C] && f.push.apply(f, a(e[C].split(""))),
                C !== h - 1 && f.push(o[C]);
            var g = f.length;
            g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice(-10).join(""))
        }
        var u = void 0
          , l = "" + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);
        u = null !== i ? i : (i = window[l] || "") || "";
        for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {
            var A = r.charCodeAt(v);
            128 > A ? S[c++] = A : (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)),
            S[c++] = A >> 18 | 240,
            S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224,
            S[c++] = A >> 6 & 63 | 128),
            S[c++] = 63 & A | 128)
        }
        for (var p = m, F = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++)
            p += S[b],
            p = n(p, F);
        return p = n(p, D),
        p ^= s,
        0 > p && (p = (2147483647 & p) + 2147483648),
        p %= 1e6,
        p.toString() + "." + (p ^ m)
    }

編寫爬蟲代碼

# !/usr/bin/python3
# -*- coding: utf-8 -*-

import js2py
import requests

js_ctx = js2py.EvalJs()

# 0:英譯中 1:中譯英
t_mode = 0


class Translation(object):

    def __init__(self, query):
        # 初始化
        self.url = "https://fanyi.baidu.com/v2transapi?from={0}&to={1}"
        self.query = query
        self.headers = {
            "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
            "Referer": "https://fanyi.baidu.com/",
            "Cookie": "BAIDUID=714BFAAF02DA927F583935C7A354949A:FG=1; BIDUPSID=714BFAAF02DA927F583935C7A354949A; PSTM=1553390486; delPer=0; PSINO=5; H_PS_PSSID=28742_1463_21125_18559_28723_28557_28697_28585_28640_28604_28626_22160; locale=zh; from_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; Hm_lvt_afd111fa62852d1f37001d1f980b6800=1553658863,1553766321,1553769980,1553770442; Hm_lpvt_afd111fa62852d1f37001d1f980b6800=1553770442; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1553766258,1553766321,1553769980,1553770442; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1553770442"
        }

    # js逆向獲取sign的值
    def make_sign(self):
        with open("translation.js", "r", encoding="utf-8") as f:
            js_ctx.execute(f.read())

        # 調(diào)用js中的函數(shù)生成sign
        sign = js_ctx.e(self.query)
        # 將sign加入到data中
        return sign

    def make_data(self, sign):
        data = {
            "query": self.query,
            "token": "6f5c83b84d69ad3633abdf18abcb030d",
            "sign": sign
        }
        return data

    def get_content(self, data):
        if t_mode == 0:
            from_str = "en"
            to_str = "zh"
        else:
            from_str = "zh"
            to_str = "en"

        response = requests.post(
            url=self.url.format(from_str, to_str),
            headers=self.headers,
            data=data
        )
        return response.json()['trans_result']['data'][0]['dst']

    def run(self):
        # 獲取sign的值
        sign = self.make_sign()
        # 構(gòu)建參數(shù)
        data = self.make_data(sign)
        # 獲取翻譯內(nèi)容
        content = self.get_content(data)
        print(content)


if __name__ == '__main__':
    t_mode = int(input("請輸入翻譯模式(0:英譯中 1:中譯英):"))
    query = input("請輸入您要翻譯的內(nèi)容:")
    translation = Translation(query)
    translation.run()

注意

  • 此時我們運行代碼會報錯誤恋博,會講我們?nèi)鄙?r 的值

解決辦法:回到瀏覽器仁热,我們查找 r 的值,并將生成 r 的值的函數(shù)榜聂,加入到我們之前創(chuàng)建的 js 文件中啼器,放在 G 函數(shù)的上面

image.png
image.png
  • 生成r的代碼,如下所示
function n(r, o) {
        for (var t = 0; t < o.length - 2; t += 3) {
            var a = o.charAt(t + 2);
            a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),
            a = "+" === o.charAt(t + 1) ? r >>> a : r << a,
            r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a
        }
        return r
    }
  • 我們重新運行代碼糙臼,發(fā)現(xiàn)又會遇到一個錯誤玷或,說是缺少 i 的值悄蕾,所以我們的解決辦法還是马昙,繼續(xù)進行 js 逆向栓辜,查找i的值
image.png
image.png
  • 逆向分析
  1. 我們回到 function a()中永高,找到需要使用 i值的地方隧土,打上斷點
image.png
image.png
  1. 打上斷點之后刷新一下頁面,我們再次將鼠標放在 i上,我們會看到一個浮點字符串命爬,此時我們不確定 i 的值是否是變化的曹傀,所以我們換一個翻譯的單詞,刷新頁面饲宛,再次查看 i 的值皆愉,我們發(fā)現(xiàn) i 的值是固定的,所以我們可以在代碼中艇抠,直接定義一個固定的i 值.
image.png
image.png

我們在自定義的 js 代碼最上面一行寫入:

var i = "320305.131321201"

最后

運行代碼幕庐,成功,完成了一次簡單的百度翻譯的 js 逆向嘗試家淤。

QQ音樂下載

qq音樂下載是怎樣的流程

分析流程

  • 打開QQ音樂

url : https://y.qq.com/

  1. 將瀏覽器切換至手機端异剥,這樣查看請求的參數(shù)可能會較少,點擊下圖中的按鈕:
image.png
image.png
  1. 查看請求接口
image.png
image.png

image.png
image.png
  1. 通過單一歌曲的鏈接查看必須的傳遞參數(shù) song_mid 繼續(xù)搜尋可用鏈接:
image.png
image.png

根據(jù)逆向流程查找我們所需的js代碼

  1. 可查看必要參數(shù)sign值與data絮重,拼接data冤寿,查看參數(shù)sign的得出
image.png
image.png
  1. debug 調(diào)試 獲取到j(luò)s的方法與sign值的獲取js代碼
image.png
image.png

image.png
image.png
  1. getSecuritySign內(nèi)部主要處理數(shù)據(jù)的js 方法如上 復(fù)制至sign.js中保存使用
  2. 該鏈接獲取到的鏈接拼接為音樂的源
image.png
image.png

最后拼接音樂源歹苦,即可完成下載

參考

https://github.com/Kr1s77/awesome-python-login-model

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市督怜,隨后出現(xiàn)的幾起案子殴瘦,更是在濱河造成了極大的恐慌,老刑警劉巖亮蛔,帶你破解...
    沈念sama閱讀 212,332評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痴施,死亡現(xiàn)場離奇詭異,居然都是意外死亡究流,警方通過查閱死者的電腦和手機辣吃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芬探,“玉大人神得,你說我怎么就攤上這事⊥捣拢” “怎么了哩簿?”我有些...
    開封第一講書人閱讀 157,812評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酝静。 經(jīng)常有香客問我节榜,道長,這世上最難降的妖魔是什么别智? 我笑而不...
    開封第一講書人閱讀 56,607評論 1 284
  • 正文 為了忘掉前任宗苍,我火速辦了婚禮,結(jié)果婚禮上薄榛,老公的妹妹穿的比我還像新娘讳窟。我一直安慰自己,他們只是感情好敞恋,可當我...
    茶點故事閱讀 65,728評論 6 386
  • 文/花漫 我一把揭開白布丽啡。 她就那樣靜靜地躺著,像睡著了一般硬猫。 火紅的嫁衣襯著肌膚如雪补箍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,919評論 1 290
  • 那天啸蜜,我揣著相機與錄音馏予,去河邊找鬼。 笑死盔性,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的呢岗。 我是一名探鬼主播冕香,決...
    沈念sama閱讀 39,071評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼蛹尝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了悉尾?” 一聲冷哼從身側(cè)響起突那,我...
    開封第一講書人閱讀 37,802評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎构眯,沒想到半個月后愕难,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,256評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡惫霸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,576評論 2 327
  • 正文 我和宋清朗相戀三年猫缭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壹店。...
    茶點故事閱讀 38,712評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡猜丹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出硅卢,到底是詐尸還是另有隱情射窒,我是刑警寧澤,帶...
    沈念sama閱讀 34,389評論 4 332
  • 正文 年R本政府宣布将塑,位于F島的核電站脉顿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏点寥。R本人自食惡果不足惜艾疟,卻給世界環(huán)境...
    茶點故事閱讀 40,032評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望开财。 院中可真熱鬧汉柒,春花似錦、人聲如沸责鳍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽历葛。三九已至正塌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恤溶,已是汗流浹背乓诽。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咒程,地道東北人鸠天。 一個月前我還...
    沈念sama閱讀 46,473評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像帐姻,于是被迫代替她去往敵國和親稠集。 傳聞我的和親對象是個殘疾皇子奶段,可洞房花燭夜當晚...
    茶點故事閱讀 43,606評論 2 350