srx-2000 / spider_collection

python爬虫,目前库存:网易云音乐歌曲爬取,B站视频爬取,知乎问答爬取,壁纸爬取,xvideos视频爬取,有声书爬取,微博爬虫,安居客信息爬取+数据可视化,哔哩哔哩视频封面提取器,ip代理池封装,知乎百万级用户爬虫+数据分析,github用户爬虫
MIT License
1.22k stars 221 forks source link

知乎参数咋加密的呀 #18

Open youzeliang opened 2 years ago

youzeliang commented 2 years ago

知乎参数咋加密的呀

srx-2000 commented 2 years ago

目前来说有以下三个参数:x-zst-81,x-zse-93,x-zse-96,其中81参数主要是在用户使用浏览器或selenium模拟滑动时才会出现的,而如果直接请求接口则不需要输入这个参数。93这个参数是相对固定的,应该是一个类似于版本信息的东西,所以主要就是x-zse-96这个参数,这个参数通过全局搜索,在js里找到了这样一段代码【github的代码块不好用,就直接粘在这里了,见谅】:

try { var g = z() , y = function(e, t, n) { var r = n.zse93 , i = n.dc0 , o = n.xZst81 , c = U(e) , u = M(t) , s = [r, c, i, B(u) && u, o].filter(Boolean).join("+"); return { source: s, signature: a()(l()(s)) } }(t, u.body, { zse93: b, dc0: g, xZst81: v }) , E = y.signature; O = y.source, v && h.set("x-zst-81", v), h.set("x-zse-93", b), h.set("x-zse-96", "2.0_" + E)

其中可看出96这个参数主要是来自于signature: a()(l()(s))这个变量,而这个变量所使用的函数一共有两个,第一个是l()(s),这个函数本身是一个md5加密,而参数s经输出后发现是x-zse-93+api_url+cookie["d_c0"]三者相加,然后就是最重要的a()函数了,这个函数我通过chrome的js单步调试,找到了一个函数转发器:

o.n = function(e) { var t = e && e.__esModule ? function() { return e.default } : function() { return e } ; return o.d(t, "a", t), t }

然后通过传入的参数e,找到了该转发器在转发a()函数时调用的e函数所对应的真实函数: https://github.com/srx-2000/spider_collection/blob/2a58ec2cfeee8a582809c51c2ddb385ffb5a41d6/zhihuAnswerSpider/spider/g_encrypt.js#L445-L447 然后通过上述函数中的__g的声明位置找到了加密函数所对应的完整的大function,并将该function作为js代码作为js文件复制进自己代码中,并使用jsdom这个库【主要作用就是创建一下虚拟的dom文件和窗口配合函数调用】配合execjs这个库【真正调用js代码的python库】成功运行。此时我只需要在python代码中将x-zse-93,api_url,cookie["d_c0"]三者进行拼串,同时调用md5加密得到基础的加密信息,然后将这个加密信息放到js文件中的b函数中即可完成最终加密。

值得一提的是,其中cookie["d_c0"]这个属性,其实很奇妙,用户不用登陆的时候如果通过question直接检索到相应的问答也可以直接浏览,此时查看cookie就会发现d_c0这个属性依然存在,所以本质上来说,知乎是不用登陆即可爬取的,这也就意味着不用建立相应的cookie池【因为并没有标识单个用户的用户特征用在了这次加密中】。

最后就是,此次js逆向是我第一次做相对复杂的js逆向,所以在网络上参考了很多前辈们的工作,这里尤其感谢csdn的一位大佬,参考文章链接

youzeliang commented 2 years ago

如果我想使用Python呢。明白了这3个参数。但是要咋传递到后端去?比如 参数 k-v(md5加密后的) 还是放header里面?

srx-2000 commented 2 years ago

如果我想使用Python呢。明白了这3个参数。但是要咋传递到后端去?比如 参数 k-v(md5加密后的) 还是放header里面?

这个你可以参考一下我知乎问答爬虫或者知乎用户爬虫的做法,就是直接将获取到的参数以key-value的形式封装进header中,然后带着这个header进行请求就行了

srx-2000 commented 2 years ago

这里再添加一些说明,就是上述的参数加密方式同时可以使用在对知乎文章,专栏等有header加密的请求中,所以如有需要大家参考本库中的两个知乎爬虫自己写就行了,基本改改接口就全能用了,该issue也会一直pin在这里,大家如果有什么有关知乎爬虫不懂得地方可以在这里讨论,希望楼主不要介意。

233lawliet commented 2 years ago

大佬,我运行的时候报了一个错误,没跑起来,能帮忙看一下吗。。。

` File "/Users/lutong/Documents/pythonProjects/spider_collection/zhihuAnswerSpider/spider/zhihu_answer.py", line 43, in get_headers encryptstr = "2.0%s" % ctx1.call('b', fmd5) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_abstract_runtime_context.py", line 37, in call return self._call(name, *args) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 92, in _call return self._eval("{identifier}.apply(this, {args})".format(identifier=identifier, args=args)) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 78, in eval return self.exec(code) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_abstract_runtimecontext.py", line 18, in exec return self.exec(source) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 88, in exec return self._extract_result(output) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 167, in _extract_result

raise ProgramError(value) execjs._exceptions.ProgramError: Error: No valid exports main found for '/Users/lutong/Documents/pythonProjects/spider_collection/zhihuAnswerSpider/node_modules/ws' `

问题代码:

image
srx-2000 commented 2 years ago

大佬,我运行的时候报了一个错误,没跑起来,能帮忙看一下吗。。。

` File "/Users/lutong/Documents/pythonProjects/spider_collection/zhihuAnswerSpider/spider/zhihu_answer.py", line 43, in get_headers encryptstr = "2.0%s" % ctx1.call('b', fmd5) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_abstract_runtime_context.py", line 37, in call return self._call(name, *args) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 92, in _call return self._eval("{identifier}.apply(this, {args})".format(identifier=identifier, args=args)) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 78, in eval return self.exec(code) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_abstract_runtimecontext.py", line 18, in exec return self.exec(source) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 88, in exec return self._extract_result(output) File "/Users/lutong/opt/anaconda3/envs/python3.7/lib/python3.7/site-packages/execjs/_external_runtime.py", line 167, in _extract_result

raise ProgramError(value) execjs._exceptions.ProgramError: Error: No valid exports main found for '/Users/lutong/Documents/pythonProjects/spider_collection/zhihuAnswerSpider/node_modules/ws' `

问题代码: image

感觉可能是python的版本或nodejs的版本问题导致的吧? 我这里给出以下我的环境信息: python:3.7.3 nodejs:16.14.2 execjs:1.5.1

2648226350 commented 2 years ago

NotADirectoryError: [WinError 267] 目录名称无效。为什么会报这个错呀 感觉像是ctx1.call('b', fmd5)出的错

longczx commented 2 years ago

如果想要爬取搜索页面,x-zst-81这个参数应该是必须的,要不然就会有 image 的提示。大佬有什么好的解决办法不

renyd123 commented 1 year ago

又换加密方式了,大佬又没啥好的解决办法

srx-2000 commented 1 year ago

又换加密方式了,大佬又没啥好的解决办法

嗯....最近一直在忙考研的事情,等我考完我整体翻新一下这个库,估计这个库里好多爬虫都不能用了

srx-2000 commented 1 year ago

如果想要爬取搜索页面,x-zst-81这个参数应该是必须的,要不然就会有 image 的提示。大佬有什么好的解决办法不

em...抱歉,最近在忙刚看见。你解决了嘛,如果没解决可能需要等到明年1月我忙完,我会尽可能的看下是否能绕过去或者给他解出来....

longczx commented 1 year ago

如果想要爬取搜索页面,x-zst-81这个参数应该是必须的,要不然就会有 图片 的提示。大佬有什么好的解决办法不

em...抱歉,最近在忙刚看见。你解决了嘛,如果没解决可能需要等到明年1月我忙完,我会尽可能的看下是否能绕过去或者给他解出来....

感谢回信,您先忙 我先尝试自己搞一下