python模拟登陆百度

本文详细解析了使用Python模拟百度二维码扫码登录的过程,包括清除cookies、分析登录请求、获取关键信息以及实现登录代码。重点在于理解登录过程中涉及的请求、响应头和重要参数,如BAIDUID、token、二维码图片请求、扫码验证和获取登陆授权cookie。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文原地址
目录

说明
环境准备
登陆过程分析
登陆过程完整代码
有效性测试

说明

本文做的是百度二维码扫码登陆,至于为什么要做扫码登陆,主要是因为:1,用账号密码登陆时,在测试过程中,如果清除cookie,会弹出验证码,这个倒是无所谓,要命的是在登陆过程中有可能出发百度的账号保护机制,就算输入验证码,百度还会强制要求手机短信进行二次验证,这个触发机制目前还不明确。

准备环境

准备python3环境以及安装requests类库,chorme浏览器。关于requests类库的基本用法可参考链接:爬虫利器requests


登陆过程分析

需要知道的是:百度是以cookie来对用户的身份进行校验的,当登陆成功以后,可以免验证访问百度相关的所有站点,包括百度贴吧,百度云盘等。模拟登陆成功的标志就是我们拿到用于验证身份的cookie。所以,我们的主要目的就是寻找哪些请求设置了cookie
第一步:打开chorme浏览器,清除百度相关的所有cookie,如当时已经登陆的话,删除cookie后将处于未登陆状态。如下图所示,删除图中所有的cookie

第二步:再次访问百度首页,并清除现有cookie,保证点击登陆按钮之前是没有任何cookie产生的。之后摁F12键,进入浏览器开发者模式,点击登陆按钮,选择二维码登陆,查看请求记录。如下图所示:


可以发现:除去css/img等资源后,主要的链接有:

序号 链接
1 uni_login_wrapper.js...
2 _blank.html
3 ?getapi&tpl=mn...
4 getqrcode?lp=pc...
5 viewlog?ak=1e3f2...
6 ?loginhistory&token=a7...
7 unicast?channel_id=d15...

查看uni_login_wrapper...这个链接的具体信息,可以看到,它的响应头中设置了BAIDUID这个cookie,并且可以发现,后面的所有链接的请求中都带有BAIDUID这个cookie


查看_balnk.html可以发现,它的响应头中没有设置任何cookie


查看?getapi这个链接,我们可以发现,它的响应头中设置了HOSUPPORT=1这个cookie,并且返回了一个json数组,里面有一个token,它的请求参数与响应分别如下图:


这个请求的主要作用就是为了获得token,它是后续?loginhistory?token=...请求的参数。


查看getqrcode?lp=pc..这个链接,可以发现,它的响应头中没有设置cookie,但是,它的返回信息中附带了一个链接,这个链接正是二维码图片的请求地址,如下图所示。访问其中的imgurl即可得到二维码。其中还有一个值sign,这个值是后续unicast?channel_id=34...这个请求中的channel_id


查看viewlog?ak=...这个请求可以看到,它的响应头中设置了pplogid这个cookie,测试发现,这个cookie并不是关键性的,可有可无,如下图:


查看?loginhistory?token=...这个请求可以发现,它设置了PASSID、UBI、HISTORY这三个cookie


查看unicast?channel_id=...这个请求,可以发现,只要我们一直没有扫描二维码,客户端会不断发送这个请求,这个请求正是用来检测我们是否扫描了二维码。,如下图所示


第三步:用百度APP扫描二维码,继续分析后续请求,扫描之后,会出现三个关键请求,如下图所示:

从上一步已经知道unicast?channel_id=...这个请求是为了判断我们是否已经扫描了二维码,可以判定,如果扫描成功,它必定会返回一个用于认证的重要信息。两次请求的反回值分别如下:


从这几张图可以看出,这个返回的v与登陆请求qrbdusslogin?v=..&bduss=...中的参数bduss值相同,与之对应。
继续分析最后的登陆请求,即qrbdusslogin?v=..budss=...,观察它的响应头可以发现其中有几个cookie值:STOKENPTOKENBDUSS,这正是授权登陆的关键所在,如下图所示:

至此,获得上述几个值后,登陆成功。


登陆过程代码

首先定义两个工具函数,一个用来获取毫秒级的时间戳,一个用来将类似于下图的返回信息转换为json,方便信息提取
[外链图片转存失败(img-IiKBvGHH-1562065335192)(/public/static/extimg/article/2019/1561993367666qrurl.png)]

# 获取毫秒级时间戳
def get_cur_timestamp():
    return int(round((time.time()) * 1000))
# 将callback转换为json
def parsecallback_tojson(callbackstr):
    return json.loads(re.search(r'\(.*\)', callbackstr).group().replace("(", "").replace(")", ""))

网站一般还对请求头有所限制,所以还需定义请求头,将其保存在config.py文件中。

# -*- coding: utf-8 -*-
headers = {
   
   
    'passport_headers':{
   
   
        'Host': 'passport.baidu.com',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
        'Refer': 'https://www.baidu.com/?tn=62095104_7_oem_dg'

    },
    'tieba_headers':{
   
   
        'Host': 'tieba.baidu.com',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
        'Refer': 'https://www.baidu.com/?tn=62095104_7_oem_dg',
        'Origin': 'https://tieba.baidu.com'
    }
}

** 获取BAIDUID: ** 根据上面的分析,首先获取BAIDUID,并定义一个login_cookies封装请求cookie。请求所需要的参数都可以通过浏览器的开发者摸式看到,这里不再细说。

 # 封装登陆用的cookie
 login_cookies = {
   
   }
 headers = config.headers['passport_headers']
 init_url='https://passport.baidu.com/passApi/js/uni_login_wrapper.jscdnversion=1561973784431&_=1561973762531'
 init_r = requests.get(init_url, headers=headers, verify=False)
 # 获取BAIDUID
 init_cookies = init_r.cookies
 login_cookies['BAIDUID'] = init_cookies['BAIDUID']
 

** 获取token: ** 利用正则表达式直接从返回结果中提取,其中tpl、apiver、class、loginversion、logintype这几个参数都是固定的,tt是当前的时间戳,callback是接收返回信息的参数,格式是固定的,可以写死。

# 获取token
token_url = 'https://passport.baidu.com/v2/api/?getapi'
t_params = {
   
   
	'tpl': 'mn',
	'apiver': 'v3',
	'tt': get_cur_timestamp(),
	'class': 'login',
	'gid': gid,
	'loginversion': 'v4',
	'logintype': 'dialogLogin',
	'traceid': None,
	'callback': 'bd__cbs__5k
Python中编写百度App登录模块的测试通常涉及模拟网络请求、检查API响应和验证用户登录状态。这里是一个基本的测试框架示例,假设我们使用了requests库来进行HTTP请求,并假设存在一个名为`baidu_login.py`的实际登录函数: ```python import unittest from unittest.mock import patch, MagicMock import requests # 首先,我们需要假设有一个模拟的登录函数 def baidu_login(username, password): # 实际登录逻辑在这里 # 这里只是一个占位符,假设它会发送POST请求到百度登录API response = requests.post('https://api.baidu.com/login', data={'username': username, 'password': password}) return response.json() class TestBaiduLogin(unittest.TestCase): @patch('requests.post') # 使用unittest.mock替换实际的网络请求 def test_valid_credentials(self, mock_post): # 创建一个成功的登录响应 mock_response = { 'status': 'success', 'token': 'your_token_here' } mock_post.return_value = MagicMock(json=lambda: mock_response) result = baidu_login('test_username', 'test_password') self.assertEqual(result['status'], 'success') # 检查登录状态是否成功 self.assertIsNotNone(result['token']) # 检查是否有返回的token @patch('requests.post') # 对于无效的登录尝试,返回错误响应 def test_invalid_credentials(self, mock_post): mock_post.return_value = MagicMock(status_code=401, json=lambda: {'message': 'Invalid credentials'}) with self.assertRaises(Exception) as context: baidu_login('invalid_username', 'invalid_password') self.assertIn('Invalid credentials', str(context.exception)) # 检查是否抛出了预期的异常 if __name__ == '__main__': unittest.main() ``` 在这个例子中,`test_valid_credentials`测试的是正常登录情况,而`test_invalid_credentials`则模拟了用户名或密码错误的情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值