爬虫初学者。想使用爬虫登录 textnow,然后服务器定时发消息,防止号码被回收。
目前通过浏览器抓包得到了登录的 post 请求,见下图
请求头除了 cookie 外,其他大部分一致。但是使用相同的请求后,登录不成功,返回下面的结果
请大佬帮忙看看,应该如何做才能登录成功,非常感谢
部分代码如下:
1
crella 2020-07-24 23:09:31 +08:00 via Android
请求头的"json"字符只是表示这个请求体是 json 形式,而不应该在 data 字典里有个 json 键?在 data 字典里去掉"json"试试
|
3
gefranks 2020-07-24 23:40:19 +08:00
如果就上面一段代码的话,csrf 是怎么处理的?
|
4
kervia OP @gefranks 可能问题就出现在 csrf-token 上面吧,我是通过 requests.session()会话进行请求的,首先用 get 请求访问了登录页面,响应结果会在 cookie 中加上 xsrf-token,但是没有 csrf-token,接着我就用 post 请求登录,就会登录失败。关于 csrf-token 和 xsrf-token 我并未接触过,暂时也不知道如何处理。希望能有大神帮助我解决这个问题,分析一下 textnow 的反爬虫机制,给一个 csrf-token 的模板或者教程(非常感谢)
|
5
kervia OP 我也尝试过分析 js 代码来查看网页本身怎么发起请求的,但是始终找不到相关代码的位置
|
6
kervia OP @gefranks 我刚刚又分析了一下,查看了登录时在网页中发送 post 请求登录之前的请求,发现都没有在请求头中包含 csrf-token 。在点击登录按钮时,第一个发起的请求是 https://www.google.com/recaptcha/api2/reload?k=6Ld5K0IUAAAAABGVv54NtC-G_0ygR8vF1rTrwLj2,第二个发起的请求才是登录 post 请求,网上查询的结果这是 Google recaptcha v2,我在模拟登录时并未发起第一个请求。第一个请求结果如下图![]( https://i.loli.net/2020/07/25/lIV6va9Wg71iXo2.png)
该请求的 Request payload 见下面图,很多字符。 ![]( https://i.loli.net/2020/07/25/emsEud5byB2r9HN.png) 其中包含了许多未知字符,无法完整复制,并且我不清楚如何提交 post 表单承载这个数据 |
7
renmu123 2020-07-25 09:53:13 +08:00 via Android
返回说你的验证码头错误,我觉得问题出在 x-tn-captcha-v3 这个头上,可能是通过 Google 验证码那个接口返回的
|
8
kervia OP @renmu123 应该是的,目前来看问题可能有两个,一个是 csrf-token 的问题,这个目前并不知道是如何生成的。另一个是 x-tn-captcha-v3,应该就是 https://imgur.com/Cv8JbHT 这个请求的结果,但是它的 post 请求 request payload 提交了很多内容,包含未知字符,无法复制下来,而且目前我还不清楚如何使用 requests.post 通过什么参数来提交这个 request payload.如下图
https://imgur.com/Z98pHHn |
9
gefranks 2020-07-25 11:20:51 +08:00
你用 fiddler,观察下从访问网站到登录完成的完整流程.csrf 我看是从 /login 这个 endpoint 的一个 xsrf 里面生成的
|
10
kervia OP @gefranks 好像是诶。
(1) https://textnow.com/login 响应头,见下图 (2) 之后我搜索 csrf-token 关键字,在 js 代码中找到了两个函数 第一个 js 文件( chunk.js ) ``` function t() { var t = e.call(this) || this; return i.a.defaults.headers.common["X-CSRF-TOKEN"] = a.get("XSRF-TOKEN"), t } ``` 第二个 js 文件 ``` function $e(a) { var b = {} , c = N.Cc(); if (c) { if (!c) throw Error("Session cookie value cannot be empty."); c = new yb(new zb,za(c)); a = za(a); c.reset(); c.update(a); a = c.digest(); var d; c = pa(a); v("array" == c || "object" == c && "number" == typeof a.length, "encodeByteArray takes an array as a parameter"); void 0 === d && (d = 0); if (!wb) { wb = {}; c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""); for (var e = ["+/=", "+/", "-_=", "-_.", "-_"], g = 0; 5 > g; g++) { var f = c.concat(e[g].split("")); vb[g] = f; for (var h = 0; h < f.length; h++) { var k = f[h] , l = wb[k]; void 0 === l ? wb[k] = h : v(l === h) } } } d = vb[d]; c = []; for (e = 0; e < a.length; e += 3) { l = a[e]; var p = (g = e + 1 < a.length) ? a[e + 1] : 0; k = (f = e + 2 < a.length) ? a[e + 2] : 0; h = l >> 2; l = (l & 3) << 4 | p >> 4; p = (p & 15) << 2 | k >> 6; k &= 63; f || (k = 64, g || (p = 64)); c.push(d[h], d[l], d[p] || "", d[k] || "") } b["X-Csrf-Token"] = c.join("") // 看这里 } return b } ``` |