中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數

發布時間:2021-12-08 11:45:03 來源:億速云 閱讀:154 作者:小新 欄目:云計算

小編給大家分享一下網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、了解加密過程

    1.1 通過觀察網絡請求

        發現如下接口包含所要的數據。包含該頁最新評論,以及所有熱評

     網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數

    再看它評論的參數,著實讓人有點懵逼

    網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數

  很多人看見這一串字符,可能簡單看下前后接口有沒數據就放棄了。好了,不賣關子。這章分析下整個參數的加密過程,實現最終模擬請求拿到數據。

 1.2 找請求參數

     可以看的到,它的參數有兩個,一個是params,一個是encSecKey并且都是經過加密的,我們就要分析它在js中的位置F12打開source搜索encSecKey)

    網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數

     進入js內部,經過斷點調試發現這里就是生成最終參數的地方

    1.3 觀察參數變化

    模擬不同分頁請求,觀察變化。效果如下圖:

網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數

對比參數變化,得出參數構成:

  • csrf_token :始終空字符串

  • cursor :第一頁默認-1;請求下一頁時該參數為上一頁最后一條評論時間戳(防止數據重復)

  • offset :移動評論數

  • orderType :默認1

  • pageNo :頁碼

  • pageSize :默認20

  • rid : R_SO_4_  + 歌曲ID

  • threadId : R_SO_4_  + 歌曲ID

自此,我們已經知道整個參數的構成,接下來就看下網易云是如何進行參數加密的

二、分析加密函數

            通過斷點已經知道,下面這段js代碼為我們分析的重點

          var bZj0x = window.asrsea(JSON.stringify(i2x), bkk0x(["流淚", "強"]), bkk0x(YS7L.md), bkk0x(["愛心", "女孩", "驚恐", "大笑"]));
            e2x.data = j2x.cr3x({
                params: bZj0x.encText,
                encSecKey: bZj0x.encSecKey
            })

           只要把bZj0x解出來就ok了,這里主要分析幾個函數

        2.1  JSON.stringify(i2x)

        斷點調制找到i2x返回內容

網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數

就是上文分析的整個字典參數

csrf_token: ""
cursor: "1610076350235"
offset: "40"
orderType: "1"
pageNo: "2"
pageSize: "20"
rid: "R_SO_4_1807537867"
threadId: "R_SO_4_1807537867"

 2.2 bkk0x函數

 bkk0x(["流淚", "強"]), bkk0x(YS7L.md), bkk0x(["愛心", "女孩", "驚恐", "大笑"]),都用到了同一個函數,這里就看下bkk0x函數內部實現是怎樣的

var bkk0x = function(cJj8b) {
        var m2x = [];
        j2x.bf2x(cJj8b, function(cJi8a) {
            m2x.push(YS7L.emj[cJi8a])
        });
        return m2x.join("")
    }

等同于python寫法

def get_bq_n1x(keys):
    m0x = []
    for key in keys:
        m0x.append(emj[key])
    return ''.join(m0x)

    YS7L.emj是一個固定的字典

YS7L.emj = {
        "色": "00e0b",
        "流感": "509f6",
        "這邊": "259df",
        "弱": "8642d",
        "嘴唇": "bc356",
        "親": "62901",
        "開心": "477df",
        "呲牙": "22677",
        "憨笑": "ec152",
        "貓": "b5ff6",
        "皺眉": "8ace6",
        "幽靈": "15bb7",
        "蛋糕": "b7251",
        "發怒": "52b3a",
        "大哭": "b17a8",
        "兔子": "76aea",
        "星星": "8a5aa",
        "鐘情": "76d2e",
        "牽手": "41762",
        "公雞": "9ec4e",
        "愛意": "e341f",
        "禁止": "56135",
        "狗": "fccf6",
        "親親": "95280",
        "叉": "104e0",
        "禮物": "312ec",
        "暈": "bda92",
        "呆": "557c9",
        "生病": "38701",
        "鉆石": "14af6",
        "拜": "c9d05",
        "怒": "c4f7f",
        "示愛": "0c368",
        "汗": "5b7a4",
        "小雞": "6bee2",
        "痛苦": "55932",
        "撇嘴": "575cc",
        "惶恐": "e10b4",
        "口罩": "24d81",
        "吐舌": "3cfe4",
        "心碎": "875d3",
        "生氣": "e8204",
        "可愛": "7b97d",
        "鬼臉": "def52",
        "跳舞": "741d5",
        "男孩": "46b8e",
        "奸笑": "289dc",
        "豬": "6935b",
        "圈": "3ece0",
        "便便": "462db",
        "外星": "0a22b",
        "圣誕": "8e7",
        "流淚": "01000",
        "強": "1",
        "愛心": "0CoJU",
        "女孩": "m6Qyw",
        "驚恐": "8W8ju",
        "大笑": "d"
    }

   YS7L.md是一個固定的數據

YS7L.md = ["色", "流感", "這邊", "弱", "嘴唇", "親", "開心", "呲牙", "憨笑", "貓", "皺眉", "幽靈", "蛋糕", "發怒", "大哭", "兔子", "星星", "鐘情", "牽手", "公雞", "愛意", "禁止", "狗", "親親", "叉", "禮物", "暈", "呆", "生病", "鉆石", "拜", "怒", "示愛", "汗", "小雞", "痛苦", "撇嘴", "惶恐", "口罩", "吐舌", "心碎", "生氣", "可愛", "鬼臉", "跳舞", "男孩", "奸笑", "豬", "圈", "便便", "外星", "圣誕"]

所以整個window.asrsea的參數都是可以得到的了,下面看下 window.asrsea()查看這個函數執行了什么操作

2.3 window.asrsea()

function a(a) {
        var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
        for (d = 0; a > d; d += 1)
            e = Math.random() * b.length,
            e = Math.floor(e),
            c += b.charAt(e);
        return c
    }
    function b(a, b) {
        var c = CryptoJS.enc.Utf8.parse(b)
          , d = CryptoJS.enc.Utf8.parse("0102030405060708")
          , e = CryptoJS.enc.Utf8.parse(a)
          , f = CryptoJS.AES.encrypt(e, c, {
            iv: d,
            mode: CryptoJS.mode.CBC
        });
        return f.toString()
    }
    function c(a, b, c) {
        var d, e;
        return setMaxDigits(131),
        d = new RSAKeyPair(b,"",c),
        e = encryptedString(d, a)
    }
    function d(d, e, f, g) {
        var h = {}
          , i = a(16);
        return h.encText = b(d, g),
        h.encText = b(h.encText, i),
        h.encSecKey = c(i, e, f),
        h
    }
    function e(a, b, d, e) {
        var f = {};
        return f.encText = c(a + e, b, d),
        f
    }
    window.asrsea = d

可以看到window.asrsea = d,所以我們要執行的就是d這個函數,主要執行3個操作

  1. a(16),生成16位隨機數

  2. 進行兩次AES加密得到h.encText

  3. 通過位移等一系列運算生成h.encSecKey

三、Python實現相同的加密算法

"""
網易云請求參數反編譯工具
    :主要斷點觀察js,改為python實現
"""

emj = {
    "色": "00e0b",
    "流感": "509f6",
    "這邊": "259df",
    "弱": "8642d",
    "嘴唇": "bc356",
    "親": "62901",
    "開心": "477df",
    "呲牙": "22677",
    "憨笑": "ec152",
    "貓": "b5ff6",
    "皺眉": "8ace6",
    "幽靈": "15bb7",
    "蛋糕": "b7251",
    "發怒": "52b3a",
    "大哭": "b17a8",
    "兔子": "76aea",
    "星星": "8a5aa",
    "鐘情": "76d2e",
    "牽手": "41762",
    "公雞": "9ec4e",
    "愛意": "e341f",
    "禁止": "56135",
    "狗": "fccf6",
    "親親": "95280",
    "叉": "104e0",
    "禮物": "312ec",
    "暈": "bda92",
    "呆": "557c9",
    "生病": "38701",
    "鉆石": "14af6",
    "拜": "c9d05",
    "怒": "c4f7f",
    "示愛": "0c368",
    "汗": "5b7a4",
    "小雞": "6bee2",
    "痛苦": "55932",
    "撇嘴": "575cc",
    "惶恐": "e10b4",
    "口罩": "24d81",
    "吐舌": "3cfe4",
    "心碎": "875d3",
    "生氣": "e8204",
    "可愛": "7b97d",
    "鬼臉": "def52",
    "跳舞": "741d5",
    "男孩": "46b8e",
    "奸笑": "289dc",
    "豬": "6935b",
    "圈": "3ece0",
    "便便": "462db",
    "外星": "0a22b",
    "圣誕": "8e7",
    "流淚": "01000",
    "強": "1",
    "愛心": "0CoJU",
    "女孩": "m6Qyw",
    "驚恐": "8W8ju",
    "大笑": "d"
}

md = ["色", "流感", "這邊", "弱", "嘴唇", "親", "開心", "呲牙", "憨笑", "貓", "皺眉", "幽靈", "蛋糕", "發怒", "大哭", "兔子", "星星", "鐘情", "牽手",
      "公雞", "愛意", "禁止", "狗", "親親", "叉", "禮物", "暈", "呆", "生病", "鉆石", "拜", "怒", "示愛", "汗", "小雞", "痛苦", "撇嘴", "惶恐", "口罩",
      "吐舌", "心碎", "生氣", "可愛", "鬼臉", "跳舞", "男孩", "奸笑", "豬", "圈", "便便", "外星", "圣誕"]


def get_bq_n1x(keys):
    m0x = []
    for key in keys:
        m0x.append(emj[key])
    return ''.join(m0x)


def __get_random_str():
    """
    Returns:16位的隨機字符串

    """
    str_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    random_str = ""
    for i in range(16):
        index = random.randint(0, len(str_set) - 1)
        random_str += str_set[index]
    return random_str


arg2 = get_bq_n1x(["流淚", "強"])
arg3 = get_bq_n1x(md)
arg4 = get_bq_n1x(["愛心", "女孩", "驚恐", "大笑"])
random_str = __get_random_str()


def __aes_encrypt(text, key):
    """
    獲取到ASW加密后的數據
    Args:
        text: 首先CBC加密方法,text必須位16位數據
        key: 加密的key

    Returns:加密后的字符串

    """
    # 加密或者解密的初始向量(16位)
    iv = "0102030405060708"
    # 不是16的倍數則填充
    pad = 16 - len(text) % 16
    if isinstance(text, str):
        text = text + pad * chr(pad)
    else:
        text = text.deocde("utf-8") + pad * chr(pad)
    aes = AES.new(key=bytes(key, encoding="utf-8"), mode=2, iv=bytes(iv, encoding="utf-8"))
    res = aes.encrypt(bytes(text, encoding="utf-8"))
    res = base64.b64encode(res).decode("utf-8")
    return res


def __get_enc_text(arg1):
    """
    對稱加密后的參數
    Args:
        arg1:加密參數

    Returns:

    """
    enc_text = __aes_encrypt(arg1, arg4)
    enc_text = __aes_encrypt(enc_text, random_str)
    return enc_text


def __get_enc_sec_key():
    """
    對稱加密密鑰

    通過查看js代碼,獲取encSecKey
    """

    #  隨機字符串逆序排列
    text = random_str[::-1]
    rs = int(codecs.encode(text.encode('utf-8'), 'hex_codec'), 16) ** int(arg2, 16) % int(arg3, 16)
    return format(rs, 'x').zfill(256)


def linux_encrypt(text):
    # print(text)
    return text


def get_form_data(text, method=''):
    """
    反編譯生成
    請求的form-data參數
    Args:
        text: 跟蹤js,自己組裝參數
        method: 方法

    Returns:form-data參數

    """
    """
    
    """
    if method == 'linux':
        return linux_encrypt(text)
    text = str(text)

    return {"params": __get_enc_text(text), "encSecKey": __get_enc_sec_key()}

四、模擬請求歌曲評論

 只要加密過程知道了,其實很多接口都可以模擬請求,此文僅供學習。

最終執行效果如下圖:

網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數

以上是“網易云音樂熱評爬蟲中怎么用python實現反編譯加密參數”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

广州市| 嘉兴市| 文昌市| 海口市| 错那县| 增城市| 台北市| 石门县| 托克托县| 太仓市| 北碚区| 民县| 绥滨县| 三明市| 舞钢市| 甘谷县| 宣化县| 定南县| 通江县| 元阳县| 民勤县| 芦山县| 定日县| 麻栗坡县| 龙陵县| 民丰县| 霍城县| 神木县| 达孜县| 钟祥市| 婺源县| 饶河县| 堆龙德庆县| 武平县| 共和县| 赤壁市| 柯坪县| 铜鼓县| 达日县| 和林格尔县| 毕节市|