【Python】模拟登陆房天下的总结

【Python】requests模拟登陆房天下的总结

最近想爬取些与房价有关的数据,看了几个网站,感觉房天下包含的内容比较多,于是,先对房天下入手。为了保证后面数据爬取,想先模拟登陆获取cookies,维护一个cookies池来用,后续的爬取直接带cookies请求。

一,常规操作

一般的模拟登录,都是模拟网站登录请求的发送。打开房天下的登录页面,输入账号密码,再F12用来观察请求的发送,点击登录。
在这里插入图片描述
在这里插入图片描述
这里可以看到有个【login.api】,可以看到Request URL 为https://passport.fang.com/login.api,Method为POST。基本可以确定这就登录相关的请求,这里使用POST方法,那么POST什么?
在这里插入图片描述
在【login.api】的最底部有个【Form Data】,这就表单提交的内容:

uid:输入的账号,就是手机号,或者邮箱号
pwd:加密后的密码
Service:soufun-passport-web
AutoLogin:1

这几个参数中Service,AutoLogin都是固定的,uid就输入的账号,就pwd会在变。所以先要明白密码是如何进行加密的?

二,风骚操作

密码的加密最常用的应该就RSA加密,观察请求的顺序,在【login.api】之前没有任何与加密相关的请求发送,所以加密过程应该是在本地用js脚本加密。
在查看与【login.api】的js脚本时在这里插入图片描述
有个【loginClickFn】,访问链接内容,看到一段与登录相关的代码:
在这里插入图片描述
所以,登录是通过ajax的post进行登录的,data里面就是【Form Data】的参数,
可以看到【pwd】是如何得到的。

pwd: encryptedString(key_to_encode, that.password.val()),

搜索这个脚本中没有找到与encryptedString,key_to_encode相关的东西。于是,返回登录的主页面中再搜索下,毕竟这个页面是登录的唯一入口,应该会包含相关信息。
在这里插入图片描述
在登录的页面中找到与RSA有关的js脚本,访问该链接,发现这是个RSA加密解密的脚本,贴出部分代码:两个关键的方法,其中一个加密函数是我们需要的。

function encryptedString(n, t) {
    var e, o, s, h, c, i, f, u, v, l, y;
    if (n.chunkSize > n.digitSize - 11) return "Error";
    for (var a = [], p = t.length, r = 0; r < p;) a[r] = t.charCodeAt(r),
    r++;
    for (e = a.length, o = "", r = 0; r < e; r += n.chunkSize) {
        for (c = new BigInt, s = 0, f = r + n.chunkSize > e ? e % n.chunkSize: n.chunkSize, u = [], i = 0; i < f; i++) u[i] = a[r + f - 1 - i];
        for (u[f] = 0, v = Math.max(8, n.digitSize - 3 - f), i = 0; i < v; i++) u[f + 1 + i] = Math.floor(Math.random() * 254) + 1;
        for (u[n.digitSize - 2] = 2, u[n.digitSize - 1] = 0, h = 0; h < n.digitSize; ++s) c.digits[s] = u[h++],
        c.digits[s] += u[h++] << 8;
        l = n.barrett.powMod(c, n.e);
        y = n.radix == 16 ? biToHex(l) : biToString(l, n.radix);
        o += y + " "
    }
    return o.substring(0, o.length - 1)
}
function decryptedString(n, t) {
    for (var e = t.split(" "), i = "", r, u, o, f = 0; f < e.length; ++f) for (o = n.radix == 16 ? biFromHex(e[f]) : biFromString(e[f], n.radix), u = n.barrett.powMod(o, n.d), r = 0; r <= biHighIndex(u); ++r) i += String.fromCharCode(u.digits[r] & 255, u.digits[r] >> 8);
    return i.charCodeAt(i.length - 1) == 0 && (i = i.substring(0, i.length - 1)),
    i
}

接着继续寻找key_to_encode,也是在同个页面,
在这里插入图片描述
有个与key_to_encode相关的function :RSAKeyPair,往这个function传入参数后,就可以得到用于加密的key了,而RSAKeyPair正好也在刚才找到的js脚本中。

function RSAKeyPair(n, t, i) {
    this.e = biFromHex(n);
    this.d = biFromHex(t);
    this.m = biFromHex(i);
    this.digitSize = 2 * biHighIndex(this.m) + 2;
    this.chunkSize = this.digitSize - 11;
    this.radix = 16;
    this.barrett = new BarrettMu(this.m)
}

综上,可以得到pwd加密的过程是执行一系列相关的js得到,先执行RSAKeyPair得到key_to_encode,再和密码一起传入encryptedString中完成加密。 所以在发送请求之前需要执行这一些的js。在这里不得不感叹下,python的库是真的强大。其中有个专门调用执行js的库,它可以加载整个js文件,然后调用文件中function。这个库就是PyExecJS
1,首先piip这个库,用的是douban地址

pip install  PyExecJS  -i  https://pypi.douban.com/simple 

2,修改下js文件,将前面的RSAjs脚本,复制内容保存为js格式文件,然后在文件最后添加以下代码:

var key_to_encode = new RSAKeyPair("010001", "", "978C0A92D2173439707498F0944AA476B1B62595877DD6FA87F6E2AC6DCB3D0BF0B82857439C99B5091192BC134889DFF60C562EC54EFBA4FF2F9D55ADBCCEA4A2FBA80CB398ED501280A007C83AF30C3D1A142D6133C63012B90AB26AC60C898FB66EDC3192C3EC4FF66925A64003B72496099F4F09A9FB72A2CF9E4D770C41");
function getpwd(t) {
   return escape(encryptedString(key_to_encode,t))
}

由于文件太长,没把所有代码贴出来,需要的可以留言。
3,调用代码编写

    def get_pwd(self):
      #路径为js文件路径
        f = open("E:\\PycharmProjects\\CookiesPool\\fang_password.js", 'r',encoding='UTF-8')
        line = f.readline()
        htmlstr = ''
        while line:
            htmlstr = htmlstr + line
            line = f.readline()
        jsstr = htmlstr
        ctx = execjs.compile(jsstr)   #加载js文件
        return ctx.call('getpwd', self.password)    #调用函数,返回加密后的结果

这样一波风骚操作,就获取到需要的pwd,后面就可以构建请求了。

三,迷之操作

下面开始构建请求,直接上代码:

import requests
import random
import execjs
from config import USER_AGENT_LIST


class FangLogin(object):
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.session = requests.session()  # 登录用session
        self.session.headers = {
            'User-Agent': random.choice(USER_AGENT_LIST)
        }
   #获取密码加密后的结果
    def get_pwd(self):
        f = open("E:\\PycharmProjects\\CookiesPool\\fang_password.js", 'r',encoding='UTF-8')
        line = f.readline()
        htmlstr = ''
        while line:
            htmlstr = htmlstr + line
            line = f.readline()
        jsstr = htmlstr
        ctx = execjs.compile(jsstr)
        return ctx.call('getpwd', self.password)
  #构建登录请求
    def login(self):
       #登录url
        url = 'https://passport.fang.com/login.api'
       #表单
        data = {
            'uid': self.username,
            'pwd': self.get_pwd(),
            'Service': 'soufun-passport-web',
            'AutoLogin': 1}
        headers = {
            'User-Agent': random.choice(USER_AGENT_LIST)       #随机抽取USER_AGENT
        }
        #发送请求
        response = self.session.post(url=url, data=data, headers=headers)
        #获取cookies
        cookies = requests.utils.dict_from_cookiejar(response.cookies)
        return cookies

if __name__ == '__main__':
    fang = FangLogin('账号','密码')
    print(fang.get_pwd())
    cookies = fang.login()
    # print(cookies)
    #个人主页,用于测试cookies是否可用,判断是否成功登录
    test_url = 'https://my.fang.com/'  
    headers = {
        'User-Agent': random.choice(USER_AGENT_LIST)
    }
    #带cookies请求,禁止重定向跳转
    response = requests.get(url=test_url, headers=headers,cookies=cookies, allow_redirects=False)
    #根据返回的页面判断是否成功访问个人主页
    print(response.text)

运行结果:
在这里插入图片描述
返回的页面是一个重定向跳转!!!说明没有登录成功,cookies没生效,你要访问个人主页,要先登录。后面一直在找问题,请求的代码也没有问题,一直找不到原因,后面想起之前说的ajax,post,于是,查了查ajax,post的原理,没有完全看懂,但是都有提到XmlHttpRequest,在Ajax应用程序中,XmlHttpRequest对象负责将用户信息以异步通信地发送到服务器端,并接收服务器返回的响应信息和数据。
好像在哪里看到过XmlHttpRequest,没错,就是在Request Header
在这里插入图片描述
于是,不敢偷懒,把headers中补全,

  headers = {
            'User-Agent': random.choice(USER_AGENT_LIST),           #随机抽取USER_AGENT
            'X-Requested-With': 'XMLHttpRequest',
            'Host': 'passport.fang.com',
            'Origin': 'https://passport.fang.com',
            'Referer': 'https://passport.fang.com/?backurl=http%3a%2f%2fmy.fang.com%2f'
        }

再次请求,返回了个人主页的内容,说明cookies有效,登录成功。
在这里插入图片描述
但是,这波迷之操作背后的原理,还是不太明白。

四,总结

1,通过本次的练手,多了一种破解密码加密,模拟登录的思路,日后遇到其他的方式也可以博客记录下,形成自己的体系。
2,爬虫之所以难,之所以牛逼,估计就在与你知识面需要很广,基本的HTTP,ajax,js,html等等。

最后,如果有其他的更简单的方法,或者有什么错误,可以分享交流!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值