获取某头条签名_signature参数

在写一个头条聚合网站 https://tttt.today ,想爬取今日头条的热点新闻,发现有前端加密的参数

下图是头条热点新闻

下图是头条热点新闻的http请求,可以看到其中只带了一个_signature参数。

如何获取该参数,下面讲解思路和相关操作步骤。

1.全局搜 _signature 找到出现位置

可以看到_signature=n,而n是一个u函数获取的,需要进入u函数查看,在var n=u(p.getUri(e),e);处打断点。

2.在u函数处打断点,并在页面再次触发热点新闻的请求(点击 换一换)

然后鼠标悬停到u函数,可以找到u函数的源文件,点击进入

3.找到函数u,并在返回结果处 打断点

找到u函数,并在return处打断点,

4.这里有各种三元表达式,不容易一眼看出到底干了什么。这里我们进入console去尝试输入各个表达式的各个部分

括号由外到内,一个个尝试。 chrome调试时,点击一个括号可以看到其配对的括号是哪一个,我们选择最前面的括号, 找到 括号内语句

(null === (a = null === (n = window.byted_acrawler) || void 0 === n ? void 0 : n.sign) || void 0 === a ? void 0 : a.call(n, o))

将其输入console回车 ,也可以将其他括号中的部分分别输入回车,测试:

我们可以看到,

(null === (a = null === (n = window.byted_acrawler) || void 0 === n ? void 0 : n.sign) || void 0 === a ? void 0 : a.call(n, o))

这句回车执行后 已经生成了加密字符串,说明已经执行了相关函数。

5.经对比测试,a即为n.sign,是一个函数,来自acrawler.js

找到方法的js源

方法1:文件鼠标悬停到window.byted_acrawler上,点开prototype

方法2:在console中输入a回车,点击返回的方法,也可以跳转到对应的js文件。

6.acrawler.js本地执行

通过查看acrawler.js内容,发现应为jsvmp保护的代码。只能将整个js抓到本地来执行

因为node和浏览器的环境不一样, 需要补环境 (搜 js补环境)

6.1 先将 acrawler.js 复制到一个test.js中。

var glb;
(glb = "undefined" == typeof window ? global : window)._$jsvmprt = function(b, e, f) {
    function a() {
        if ("undefined" == typeof Reflect || !Reflect.construct)
            return !1;
        if (Reflect.construct.sham)
            return !1;
        if ("function" == typeof Proxy)
            return !0;
        try {
            return Date.prototype.toString.call(Reflect.construct(Date, [], (function() {}
            ))),
            !0
        } catch (b) {
            return !1
        }
    }

    ///……省略……
    ///……省略……
    ///……省略……

     0, "undefined" != typeof history ? history : void 0, "undefined" != typeof Image ? Image : void 0, "undefined" != typeof console ? console : void 0, "undefined" != typeof PluginArray ? PluginArray : void 0, "undefined" != typeof indexedDB ? indexedDB : void 0, "undefined" != typeof DOMException ? DOMException : void 0, "undefined" != typeof parseInt ? parseInt : void 0, "undefined" != typeof String ? String : void 0, "undefined" != typeof Array ? Array : void 0, "undefined" != typeof Error ? Error : void 0, "undefined" != typeof JSON ? JSON : void 0, "undefined" != typeof Promise ? Promise : void 0, "undefined" != typeof WebSocket ? WebSocket : void 0, "undefined" != typeof eval ? eval : void 0, "undefined" != typeof setTimeout ? setTimeout : void 0, "undefined" != typeof encodeURIComponent ? encodeURIComponent : void 0, "undefined" != typeof encodeURI ? encodeURI : void 0, "undefined" != typeof Request ? Request : void 0, "undefined" != typeof Headers ? Headers : void 0, "undefined" != typeof decodeURIComponent ? decodeURIComponent : void 0, "undefined" != typeof RegExp ? RegExp : void 0]);
 
    function get_signature(){
        return window.byted_acrawler.sign({url: 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'})
    }
    try{

        let signature = get_signature()
        console.log("signature:")
        console.log(signature)
    }catch(e){
        console.log(e)
    }
    

6.2 安装v_jstools插件

下载https://github.com/cilame/v_jstools 然后解压,在chrome chrome://extensions/ 中, 加载本地v_jstools插件

配置v_jstools,如下图

刷新网站,点击v_jstools中的按钮->生成临时环境

提示:已将代码存放到剪贴板中。

然后将已复制的代码,粘贴到 6.1中代码块前面, 整块代码


var v_saf;!function(){var n=Function.toString,t=[],i=[],o=[].indexOf.bind(t),e=[].push.bind(t),r=[].push.bind(i);function u(n,t){return-1==o(n)&&(e(n),r(`function ${t||n.name||""}() { [native code] }`)),n}Object.defineProperty(Function.prototype,"toString",{enumerable:!1,configurable:!0,writable:!0,value:function(){return"function"==typeof this&&i[o(this)]||n.call(this)}}),u(Function.prototype.toString,"toString"),v_saf=u}();


function _inherits(t, e) {
  t.prototype = Object.create(e.prototype, {
    constructor: { value: t, writable: !0, configurable: !0 }
  }), e && Object.setPrototypeOf(t, e) }
Object.defineProperty(Object.prototype, Symbol.toStringTag, {
  get() { return Object.getPrototypeOf(this).constructor.name }
});
var v_new_toggle = true


//……省略……

var v_to_time = +new v_Date
// var v_to_time = +new v_Date('Sat Sep 03 2022 11:11:58 GMT+0800') // 自定义起始时间
v_new_toggle = undefined;
//以上是 补环境的内容
//以下是 acrawler.js 原内容

var glb;
(glb = "undefined" == typeof window ? global : window)._$jsvmprt = function(b, e, f) {
    function a() {
//……省略……

6.3 在test.js最后 再写一个调用sign函数的方法


function get_signature(){
    return window.byted_acrawler.sign({url: 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'})
}
try{

    let s = get_signature()
    console.log("here is signature:")
    console.log(s)
}catch(e){
    console.log(e)
}

在命令行执行,

node test.js

我们便可以得到_signature

here is signature:
_02B4Z6wo00f01K8F4eQAAIDBBFTbeEzvBHSvJW1AAE8-dabAXl2YU--dHBGeGOWdkIq2MCKZAIffl5LvcS-54wjwUsnyJPni.Z73PiFW4i.kwj.q-O8.qYFmk2kcZD2455.0oZlc9YPR064yee

在postman中输入_signature的值,调用相关接口,可以成功获取返回,说明_signature是正确的。

7.python 中使用 execjs 调用js 获取signature参数,执行http request 获取热点新闻

import execjs

def get_signature():  # 解密signature参数
    with open('test.js', encoding='utf-8')as f:
        jscode = f.read()
    signature = execjs.compile(jscode).call('get_signature')
    return signature
s=get_signature()
print(s)