textnow 爬虫登录的问题

2020-07-24 19:45:02 +08:00
 kervia

爬虫初学者。想使用爬虫登录 textnow,然后服务器定时发消息,防止号码被回收。 目前通过浏览器抓包得到了登录的 post 请求,见下图
请求头除了 cookie 外,其他大部分一致。但是使用相同的请求后,登录不成功,返回下面的结果 请大佬帮忙看看,应该如何做才能登录成功,非常感谢 部分代码如下:

1712 次点击
所在节点    问与答
10 条回复
crella
2020-07-24 23:09:31 +08:00
请求头的"json"字符只是表示这个请求体是 json 形式,而不应该在 data 字典里有个 json 键?在 data 字典里去掉"json"试试
kervia
2020-07-24 23:36:55 +08:00
@crella 之间试过,去掉 json 键的话,还是会返回同样的结果,登录失败
gefranks
2020-07-24 23:40:19 +08:00
如果就上面一段代码的话,csrf 是怎么处理的?
kervia
2020-07-24 23:49:36 +08:00
@gefranks 可能问题就出现在 csrf-token 上面吧,我是通过 requests.session()会话进行请求的,首先用 get 请求访问了登录页面,响应结果会在 cookie 中加上 xsrf-token,但是没有 csrf-token,接着我就用 post 请求登录,就会登录失败。关于 csrf-token 和 xsrf-token 我并未接触过,暂时也不知道如何处理。希望能有大神帮助我解决这个问题,分析一下 textnow 的反爬虫机制,给一个 csrf-token 的模板或者教程(非常感谢)
kervia
2020-07-24 23:53:00 +08:00
我也尝试过分析 js 代码来查看网页本身怎么发起请求的,但是始终找不到相关代码的位置
kervia
2020-07-25 00:12:54 +08:00
@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 表单承载这个数据
renmu123
2020-07-25 09:53:13 +08:00
返回说你的验证码头错误,我觉得问题出在 x-tn-captcha-v3 这个头上,可能是通过 Google 验证码那个接口返回的
kervia
2020-07-25 10:17:57 +08:00
@renmu123 应该是的,目前来看问题可能有两个,一个是 csrf-token 的问题,这个目前并不知道是如何生成的。另一个是 x-tn-captcha-v3,应该就是 https://imgur.com/Cv8JbHT 这个请求的结果,但是它的 post 请求 request payload 提交了很多内容,包含未知字符,无法复制下来,而且目前我还不清楚如何使用 requests.post 通过什么参数来提交这个 request payload.如下图
https://imgur.com/Z98pHHn
gefranks
2020-07-25 11:20:51 +08:00
你用 fiddler,观察下从访问网站到登录完成的完整流程.csrf 我看是从 /login 这个 endpoint 的一个 xsrf 里面生成的
kervia
2020-07-25 11:34:32 +08:00
@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
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/692892

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX