首页 > > > 10291 用Python忽略全部邀请
昨晚写了一个 Python 程序,可以自动忽略知乎上的全部邀请。欢迎大 V 们试用!
链接:https://github.com/MaigoAkisame/zhihu-ignore-invites
下面是原理介绍。
在“邀请我回答的问题”页面(下文简称“邀请页面”),点击一个邀请后的“忽略”按钮,可以发现这个邀请消失了,但页面并没有刷新。由此推测,点击“忽略”按钮时页面向服务器发送了一个 AJAX 请求。
在 Chrome 中按 F12 键调出开发者工具窗口,并切换至 Network → XHR 标签页。再点击一个邀请后的“忽略”按钮,发现果然出现了一个请求。


利用 Unix 或 Cygwin 中的 curl 工具,可以在命令行发送 POST 请求,如下。当然,这里的 qid 要换成下一个邀请的编号。
结果返回一串乱码,刷新邀请页面,发现邀请并未消失。这是因为刚刚发送的 POST 请求不带 cookies,被服务器拒绝了。
在 Cookies 标签页下可以找到浏览器发送的 POST 请求所带有的 cookies,它们是各种意味不明的字符串。经试验,其中只有 _xsrf 和 z_c0 两项是必需的;_xsrf 的值与表单参数中的相同。把这两个 cookies 添加到用 curl 发送的 POST 请求中去,发现返回一个 json 对象;刷新邀请页面,第一个邀请果然就消失了。

弄懂了忽略一个邀请是怎么操作的,就容易写出批量忽略邀请的脚本了。首先模拟登录,然后反复读取邀请页面(页面上会有最近的 20 个邀请),提取出页面上的问题编号,逐一发送 POST 请求忽略,直到不再有邀请为止。
利用 Python 里的 requests 库,可以发送 GET 或 POST 请求。与 curl 不同,它发送的请求必须带有 headers,不过我发现,必需的 headers 只有 User-Agent 这一项,而且值为空就行。 requests 库里有个 Session 类,其对象可以把 cookies 记忆起来,于是手动提取 _xsrf 和 z_c0 两项 cookies 的工作就可以省去了。
下面是各个步骤的做法,和它们的返回结果:
忽略邀请时所需的 qid、uid、_xsrf 三项数据,都可以在邀请页面中找到。qid 就在邀请本身里面,在附近还可以找到邀请者的信息。uid 在页面中的一处脚本里,是“user_hash”后面的一串十六进制数;_xsrf 在页面底部的一个隐藏输入框里。



有了上面的准备,就可以写脚本了。忽略一个邀请大约用时 0.5 秒,效率还可以。不过,当忽略了几百个邀请后,我发现我的知乎账号因为访问太快被暂时冻结了╮( ̄▽ ̄)╭,不过好在 1 个多小时后就恢复了正常。在现在的版本中,我只能每 5 秒忽略一个邀请,并在忽略 20 个页面(400 个邀请)后休息 1 分钟。
我在探索的过程中,意外地发现知乎可能有未公开的“全部忽略”功能。我是这么发现的:
首先,我试图定位忽略邀请的 POST 请求是在哪里发起的。邀请页面上的“忽略”按钮(其实是个超链接),其 href 值为“javascript:;”,也就是说发起 POST 请求的代码并不在此处。我依次打开邀请页面所加载的各个 JavaScript 文件,并搜索“askpeople”、“pass”等关键字,最终发现发起 POST 请求的代码位于 https://www.zhihu.com/static/revved/-/js/closure/page-misc.13415dac.js 这个脚本中。将脚本美化后,我发现了这样几个函数:

我在写脚本的过程中参考了下面两篇文章,在此向作者致谢。
原文作者:;如有侵权,请联系管理员删除。