Python 模拟登录微博

模拟登录, 阅读本文大概需要五分钟, 理解本文至少需要五分钟, 实践本文大概需要两小时。

初学爬虫, 模拟登录是一个不得不面对的门, 在这个门槛之前基本上都是将无脑将网页内容爬取下来, 再对内容进行分析即可。但是需要爬取的网站涉及到了模拟登录的功能, 那么爬虫的重点其实更在于分析整个登录的过程, 编码反倒是次要的。

近期, 我终于向渣浪伸出了我邪恶的手, 分析了下微博的登录流程, 废话少说, 接下来开始正题。

简单来说, 分析的过程只不过是在浏览器上进行一次登录操作, 通过抓包工具查看在整个登录的过程中, 客户端与服务端到底进行了哪些交互, 发送了几次请求, 请求获取了什么数据又传递了什么数据给服务端。如果上述这些风骚的操作你都会, 那么恭喜你, 毕业了请出门右拐需找高级课程。如果上述这些步骤你不会, 或者说有些步骤还不是了解的很清晰明白, 那么希望这篇文章能够帮助到你。

再逼逼两句, 模拟登陆的方式有很多种, 一种像这篇文章介绍的通过分析客户端与服务端的交互, 让代码代替客户端发送接收数据。但是这种方式有个弊端, 就是不会很直观, 毕竟是分析服务端与客户端之间的数据交互, 所以能看到的也只是数据的变化。除了这种方式以外, 还有一种方式是模拟人的行为进行登录, 这种方式完全不需要在乎后端, 只需要按照步骤在前端进行操作即可。这种方式的优点是操作非常直观, 结果也能够很明显的看到。第二种方式, 我在

selenium 模拟浏览器登录微博

这篇文章中已经介绍过了, 对后面这种方式更感兴趣的朋友可以去阅读一下。

下面就是真正的正题, 准备好了吗? 黑喂狗

01 抓包

如果你用的浏览器是「Chrome」, 那么就会比较方便的能看到整个流程, 如果是其他浏览器的话可能需要抓包工具的帮助了。以「chrome」浏览器为例, 打开微博首页, 按「F12」打开开发者模式, 选择「Network」栏, 你会看到这样一个界面。

先别急着登录, 在帐号输入框中, 我们先输入我们的帐号。然后你会在下面的框子中看见一条请求。

02 模拟登录

这是一条预登录请求, 打开它, 我们可以看到请求头和请求响应。

可以看到这其实是一条 Get 请求, 一看这个 Get 请求 URL 地址就头大, 但是别慌, 这是有规律的。

https://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=NTkxMjA5MTI1JTQwcXEuY29t&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.19)&_=1532432079160

在这个 URL 地址上, 「su=」后面的参数其实就是我们的账户了, 其他的都是固定的(不信的话,可以使用不同的账户重复上述步骤), 最后的一长串数字是时间戳, 不带上也可以。也就是说, 只要我们知道我们登录时使用的帐号, 是如何被编码转化成 URL 地址里面的这串字符, 就可以动态生成 prelogin 的请求地址了(当然写死也可以, 毕竟登录的帐号是不变的)。

拿到请求地址后, 我们把焦点放在这条请求的返回值上, 虽然目前不知道有什么用, 但是先记一下。

sinaSSOController.preloginCallBack()

exectime:85

is_openlock:0

nonce:"W97J6V"

pcid:"gz-adfac0f44fb0a31f2e01e250586fc315bee4"

retcode:0

servertime:1532436116

showpin:0

经过简单的尝试你会发现, 账户使用的是 base64 编码, 通过 base64 解码就可以还原出我们的原始帐号了。这里要注意, 如果你的帐号是邮箱的话, 会发现原本「@」的位置变成了「%40」, 这是因为在将参数拼接到 URL 上时, 还需用了 URL 编码。所以在使用 base64 编码后, 我们还需要 URL 编码在加密一次, 然后就可以看到最开始 prelogin 的 URL 地址上看到的字符串了。

然后我们点击登录按钮,然后你就会看到大量的请求, 多到奔溃的那种。一个小小的登录操作, 居然要发送那么多条请求, 是不是很神奇?

其实并不是。

我们只需要挑重点看就可以了, 仔细观察这些请求, 你会发现一条叫

的特别显眼, 明摆着告诉你这就是登录请求了。我们会发现这条请求, 极其麻烦。找到 From Data 这一栏, 这里面就是我们发送这条请求的时候, post 给服务器的数据, 包括但不限于帐号密码。这里就不贴图了太长了, 就是一些键值对。同样, 通过多次登录法, 我们可以对比出。

su、servertime、nonce、rsakv、sp

这五个值是变化的, 其他的都可以写死。那么问题就简单一些了。其中 servertime、nonce、rsakv 这几个值是不是很眼熟?这几个值和我们上一个 prelogin 请求的返回里面的值一模一样。所以现在就剩下 su、sp 两个参数了, 一个是账户一个是密码。

账户在前面我们已经介绍了如何加密, 接下来就是密码了。看到密码这么一长串你就可以意识到, 密码不会像帐号加密这么简单。要看密码是如何加密的其实还是需要关注下加密代码, 这个代码就藏在我们登录请求的下面的那个 ssologin.js 的文件里。在这个文件里搜索 password, 你会发现这么一段代码

if ((me.loginType & rsa) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.RSAKey) {

request.servertime = me.servertime;

request.nonce = me.nonce;

request.pwencode = "rsa2";

request.rsakv = me.rsakv;

var RSAKey = new sinaSSOEncoder.RSAKey();

RSAKey.setPublic(me.rsaPubkey, "10001");

password = RSAKey.encrypt([me.servertime, me.nonce].join("\t") + "\n" + password)

可以看到, 加密方式是使用 RSA 加密的。 pubkey 的两个值是 16 进制的, 需要先转化为 10 进制再设置 pubkey, 然后加密后的 password 就是根据

servertime + '\t' + nonce + '\n' + password

这个格式, 再经过 rsa 加密完成的。搞定了这一步, 我们就可以发起 post 的登录请求了。发出请求后, 发现返回的并不是登录页面代码, 而是这么一串东西

新浪通行证

正在登录 ...

try);}

catch(e){

var msg = e.message;

var img = new Image();

var type = 1;

img.src = 'https://login.sina.com.cn/sso/debuglog?msg=' + msg +'&type=' + type;

}try);}

catch(e){

var msg = e.message;

var img = new Image();

var type = 2;

img.src = 'https://login.sina.com.cn/sso/debuglog?msg=' + msg +'&type=' + type;

}

另一串重定向代码, 依旧提取出重定向地址, 再次发送请求, 然后你会惊喜的发现, 这次终于不是重定向代码了, 然而也不是登录页面代码。

在这次回的代码里, 有一个地址看起来很眼熟, 就是键 userdomain 的值, 这个值看起来像是我们微博 URL 的地址的一部分。将它和 "https://weibo.com/" 拼接起来, 再发起请求, 终于我们看到了登录页面。

写在最后的逼逼, 这个登录其实在一年前就决定要学了, 然而近期才弄懂, 这中间除了工作忙之外, 最主要的原因, 起始还是懒。

最后的最后,代码我已经传到 GitHub 了,感兴趣的同学可以去看看。

https://github.com/zengln/script/blob/master/TBHuman/WBLogin.py

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180725G0966200?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券