python 爬虫(三十七)之登陆

1.1 目标站点网址

https://www.zhihu.com/signin?next=%2F

知乎上所有的数据都是得登录之后才能获取的,所以我们首先得用爬虫模拟知乎的登录操作

1.2 站点分析

1.2.1 登录过程分析

首先我们访问登录页面的时候,服务器会给我们返回一系列的cookie

img

这些cookie我们需要保存下来

接着,咱点击密码登录会发现,如下的一个验证码的请求:

img

这个请求是用来询问服务器,我需不需要填写验证码,'show_captcha’为false,则不需要验证码,'show_captcha’为true,则需要验证码

经过多次测试,会发现,lang这个字段,控制的是验证码格式,en为英文验证码,cn为中文验证码(这个需要你点击哪些中文是倒置的).因为我们选择使用英文验证码

当’show_captcha’为true的时候,浏览器会继续像这个url发送请求,来获取验证码的图片内容

img

虽然是同一个url,只不过这次请求的请求方法变成了PUT,返回的内容为base64处理过的图片内容,这个我们只需要用python中base64这个库去解析就好了

当我输入验证码并提交的时候,浏览器会向这个url发送第三次请求,用来验证我的验证码是否输入正确

img

提交验证码的url依旧是这个url,不过这次请求方法为POST,请求体为{“input_text”:‘验证码内容’}

如果验证通过,'success’这个字段的值就为true

然后紧接着,浏览器就会向服务器提交我的用户名和密码.

img

这个时候,咱就懵逼了,因为请求体的数据全部是前端js加密过的密文

第一,我不知道请求体都需要哪些字段

第二,我就算知道都有哪些字段,不知道加密规则,也无法正常提交

所以,我们下面就需要找到请求体的加密算法

1.2.2 加密算法破解

正常情况下,网站程序员为了便于识别,对于加密算法,一般都会带有关键字"encrypt",所以,我们使用控制台上的搜索功能,来尝试定位到他们的js加密算法

img

这个结果让人心情愉悦,咱一共找到3个文件,共6个匹配.

每个匹配都点进去瞅一眼

最后,我们会找到下面这块代码,咱打个断点,然后重新点击登录,程序会被卡主

img

这个时候我们注意看上边e这个变量

"client_id=c3cef7c66a1843f8b3a9e6a1e3160e20&grant_type=password&timestamp=1566371889615&source=com.zhihu.web&signature=849409fe69f76b28a7ebfa95f0acc784d7c812bf&username=%2B8618896530856&password=dadasdasdas&captcha=nngt&lang=en&utm_source=&ref_source=other_https%3A%2F%2Fwww.zhihu.com%2Fsignin%3Fnext%3D%252F"

很明显了,我们找到了post请求的请求体数据,但是这是url编码的,有些字段看不懂呀,咋办?

python里调url解析库解个码就好了:

from urllib.parse import unquote_plus

msg = '''
client_id=c3cef7c66a1843f8b3a9e6a1e3160e20&grant_type=password&timestamp=1566371889615&source=com.zhihu.web&signature=849409fe69f76b28a7ebfa95f0acc784d7c812bf&username=%2B8618896530856&password=dadasdasdas&captcha=nngt&lang=en&utm_source=&ref_source=other_https%3A%2F%2Fwww.zhihu.com%2Fsignin%3Fnext%3D%252F
'''
print(unquote_plus(msg))

输出结果如下:

client_id=c3cef7c66a1843f8b3a9e6a1e3160e20&grant_type=password&timestamp=1566371889615&source=com.zhihu.web&signature=849409fe69f76b28a7ebfa95f0acc784d7c812bf&username=+8618896530856&password=dadasdasdas&captcha=nngt&lang=en&utm_source=&ref_source=other_https://www.zhihu.com/signin?next=%2F

里面需要包含的字段如下:

client_id      用户id(固定值)
grant_type     验证方式(固定值)
timestamp      时间戳*1000,去尾
source		   (固定值)
signature	   签名(js加密,变动)
username	   用户名
password	   密码
captcha		   验证码
lang		   验证码方式(固定值)
utm_source	   (固定值)
ref_source	   (固定值)other_https://www.zhihu.com/signin?next=%2F

这些字段都很好处理,但是让人老壳疼的地方又来了,这个signature是加密的,我们还得找出它的js加密算法

怎么找,很容易,咱搜索关键字"signature",在一堆匹配中会找到下面的匹配

img

ok,咱找着了,hamc的加密方式,sha-1的加密算法,咱用python的hmac,hashlib这两个包就能搞定

import hmac
from hashlib import sha1

咱接着说请求体的加密,刚刚我们找到了加密的地方,怎么处理呢,只要把它所在的js函数全部复制到python里,在python里调用node.js去执行就可以了,复制结果如下:

function t(e) {
        return (t = "function" == typeof Symbol && "symbol" == typeof Symbol.A ? function(e) {
            return typeof e
        }
        : function(e) {
            return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
        }
        )(e)
    }
    Object.defineProperty(exports, "__esModule", {
        value: !0
    });
    var A = "2.0"
      , __g = {};
    function s() {}
    function i(e) {
        this.t = (2048 & e) >> 11,
        this.s = (1536 & e) >> 9,
        this.i = 511 & e,
        this.h = 511 & e
    }
    function h(e) {
        this.s = (3072 & e) >> 10,
        this.h = 1023 & e
    }
    function a(e) {
        this.a = (3072 & e) >> 10,
        this.c = (768 & e) >> 8,
        this.n = (192 & e) >> 6,
        this.t = 63 & e
    }
    function c(e) {
        this.s = e >> 10 & 3,
        this.i = 1023 & e
    }
    function n() {}
    function e(e) {
        this.a = (3072 & e) >> 10,
        this.c = (768 & e) >> 8,
        this.n = (192 & e) >> 6,
        this.t = 63 & e
    }
    function o(e) {
        this.h = (4095 & e) >> 2,
        this.t = 3 & e
    }
    function r(e) {
        this.s = e >> 10 & 3,
        this.i = e >> 2 & 255,
        this.t = 3 & e
    }
    s.prototype.e = function(e) {
        e.o = !1
    }
    ,
    i.prototype.e = function(e) {
        switch (this.t) {
        case 0:
            e.r[this.s] = this.i;
            break;
        case 1:
            e.r[this.s] = e.k[this.h]
        }
    }
    ,
    h.prototype.e = function(e) {
        e.k[this.h] = e.r[this.s]
    }
    ,
    a.prototype.e = function(e) {
        switch (this.t) {
        case 0:
            e.r[this.a] = e.r[this.c] + e.r[this.n];
            break;
        case 1:
            e.r[this.a] = e.r[this.c] - e.r[this.n];
            break;
        case 2:
            e.r[this.a] = e.r[this.c] * e.r[this.n];
            break;
        case 3:
            e.r[th
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值