基于Python通过Chrome的Cookie登录百度账户

环境

  • 操作系统:windows 10 x64
  • 集成环境:Visual Studio Code
  • Python版本:v3.10.5 64位
    – 解码需要os、sqlite3、win32crypt、base64、cryptography、json
    – 访问网页需要urllib、http

一、说明

这篇博文是一篇解题思路的记述文章,代码也是按照解决问题的思路一路写下去的,所以基本不存在函数、类等可以反复调用的对象,甚至其中还存在一些手动的动作。也即意味着如果你顺利的理解了这个思路,可以通过自己的修改让代码看起来更加的优雅整洁。
ps:为了保证代码环境的纯净,建议在实施本博文之前,先清除百度在Chrome中的所有cookie。

二、原理简述

浏览器是利用cookie实现免密码登录的。如果想实现通过python对百度的登录,需要先在浏览器中进行一次登录,然后获取cookie文件,最后基于获取的文件进行百度其他产品的访问。

三、步骤

1、通过Chrome访问百度,获取Cookie

用户首先需要在Chrome上正式访问一次百度的网页,如百度搜索首页www.baidu.com。如果未登录,需要登录成功一次以产生cookies。
Chrome浏览器(version≥103)的cookie是以SQlite库的形式存储的。在Windows文件资源管理器的地址栏中键入路径%localAppData%\Google\Chrome\User Data\Default\network\,可以很容易的找到这个名为Cookies的SQlite文件。所以它的完整路径是:

%localAppData%\Google\Chrome\User Data\Default\network\Cookies

因为Cookies文件的本质是一个SQlite库文件,所以可以通过Navicat等数据库管理软件直接打开它。此库包含两张表:

  • cookies
  • meta

其中cookies表存储的就是与Cookie相关的数据。需要关注如下几个字段:

creation_utc(创建时间)host_key(域名)name(变量名)encrypted_value(变量值)path(路径)
13302687838867670.baidu.comBAIDUIDv10J�����q��Kp¶�3)Z���&1m�/

其中host_key存储的是网页域名,可以被用于识别cookie的归属对象。
name就是变量名;
encrypted_value就是变量值。它是一个加密字段。其密钥存储在Local State文件中,路径为:

%localAppData%\Google\Chrome\User Data\Local State

Local State本质上是一个Json文件。接下来将尝试通过这个文件来解密变量值。

2、利用Python解密变量

2.1准备工作

将一些常量载入内容

import os
import sqlite3
import win32crypt
import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import json
import time


'''
关于下面这个字典的来历:它出现在这里可能会有些跳跃,有些不合逻辑,因为这个是我根据结果倒推的。
里面的key是域名,value是cookie文件里面需要的参数。他们表示的含义我没研究出来。
可以先忽略这个字典,后面你就知道为啥存在它了。
'''
BAIDU_BOOL = {
    '.baidu.com': ['TRUE', 'FALSE'],
    '.passport.baidu.com': ['TRUE', 'TRUE'],
    'passport.baidu.com': ['FALSE', 'FALSE'],
    'www.baidu.com': ['FALSE', 'FALSE'],
    '.hm.baidu.com': ['TRUE', 'FALSE'],
    '.www.baidu.com': ['TRUE', 'FALSE'],
    '.wenku.baidu.com': ['TRUE', 'TRUE'],
    '.miao.baidu.com': ['TRUE', 'FALSE'],
    'wenku.baidu.com': ['FALSE', 'TRUE'],
    '.pan.baidu.com': ['FALSE', 'FALSE'],
    'pan.baidu.com': ['FALSE', 'FALSE'],
    '.jingyan.baidu.com': ['FALSE', 'FALSE'],
    '.baike.baidu.com': ['FALSE', 'FALSE'],
    'baike.baidu.com': ['FALSE', 'FALSE'],
    '.b2b.baidu.com': ['FALSE', 'FALSE'],
    '.tongji.baidu.com': ['FALSE', 'FALSE'],
    '.bce.baidu.com': ['FALSE', 'FALSE'],
    '.developer.baidu.com': ['FALSE', 'FALSE'],
    '.lewan.baidu.com': ['FALSE', 'FALSE'],
    '.haokan.baidu.com': ['FALSE', 'FALSE'],
    '.tieba.baidu.com': ['FALSE', 'FALSE'],
    '.live.baidu.com': ['FALSE', 'FALSE'],
    '.zhidao.baidu.com': ['FALSE', 'FALSE']
}
# 存储cookie、密钥的文件路径
CHROME_COOKIE_PATH = r'\Google\Chrome\User Data\Default\network\Cookies'
CHROME_LOCALSTATE_PATH = r'\Google\Chrome\User Data\Local State'

# cookie文件头,最后一步手工生成cookie会用得到
COOKIE_HEADER = """# Netscape HTTP Cookie File\n# http://curl.haxx.se/rfc/cookie_spec.html\n# This is a generated file!  Do not edit.\n\n"""

2.2 获取Cookie、LocalState两个文件的完整路径
path = os.environ['LOCALAPPDATA']
dbCookies = path + CHROME_COOKIE_PATH  # cookie文件,本质是一个sqlite数据库
fileLocalState = path + CHROME_LOCALSTATE_PATH  # 存储密钥的文件,本质是一个Json文件

2.3 将Cookies读入valCookies变量
conn = sqlite3.connect(dbCookies)
cur = conn.cursor()
sql = """select creation_utc,host_key,name,encrypted_value,path from cookies where host_key like '%baidu%'"""
cur.execute(sql)
valCookies = cur.fetchall()
cur.close()
conn.close()

2.4 将LocalState存储的密钥读入key变量
with open(fileLocalState, 'r', encoding='utf-8') as f:
    jsonStr = json.load(f)
    encryptedKey = jsonStr['os_crypt']['encrypted_key']
encrypted_key_with_header = base64.b64decode(encryptedKey)
encrypted_key = encrypted_key_with_header[5:]
key = win32crypt.CryptUnprotectData(encrypted_key, None, None, None, 0)[1]

2.5 对2.3中valCookies列表中的[encrypted_value]字段进行解密
# 1、预解密
valCookieOut = []  # 这个用来存储解密后的cookie

# 2、解密并输入明文列表
for valCookieGet in valCookies:
    # 将valCookies的每个元素赋值给变量。这里重点关注valEncrypted,需要解密的就是它
    creation_utc, host_key, name, valEncrypted, path = valCookieGet

    # 根据百度的结果,valEncrypted的构成分为三部分,都是固定长度
    top = valEncrypted[:3]  # ->这个切片没啥用,也可以删掉
    nonce = valEncrypted[3:15]
    cipherbytes = valEncrypted[15:]

    # 百度的解密过程
    aesgcm = AESGCM(key)
    plainbytes = aesgcm.decrypt(nonce, cipherbytes, None)
    value = plainbytes.decode('utf-8')  # ->这个就是解密之后的值

    # 将解密的文件存入列表
    valCookieOut.append(tuple((creation_utc, host_key, name, value, path)))
    

3、基于解密的列表生成cookie

'''
cookie文件正文的结构是[host_key] [TRUE|FALSE] [path] [TRUE|FALSE] [creation_utc] [name] [value]
中间用制表符\t分隔
creation_utc那个实际上是存储有效时间戳的,用creation_utc也没啥影响,为了偷懒这里就用它占位了
文件的存储我是放在平行目录下的log文件夹,文件名加上了时间戳
'''
with open('../log/BaiduCookie'+str(int(time.time())), 'w') as f:
    # 写入头
    f.write(COOKIE_HEADER)

    # 写入体
    for valCookie in valCookieOut:
        # 将valCookie的每个元素赋值给变量。
        creation_utc, host_key, name, value, path = valCookie
        cookieContent = str(host_key) + '\t' + str(BAIDU_BOOL[host_key][0]) + '\t' + str(path) + '\t' + \
            str(BAIDU_BOOL[host_key][1]) + '\t' + str(creation_utc) + \
            '\t' + str(name) + '\t' + str(value) + '\n'
        f.write(cookieContent)
        

4、cookie预览

如果一切顺利,在做完上面所有步骤后,将会获得一个编辑好的cookie文件。它大致的内容如下:

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

.passport.baidu.com	TRUE	/	TRUE	13302687843561289	PTOKEN	6842356784ffb2db1236574567d8ee1d3
.baidu.com	TRUE	/	FALSE	13302687839790384	BIDUPSID	AG43E548AF7F091F824110AC4ABCD9DA5
.passport.baidu.com	TRUE	/	TRUE	13302687843561303	HISTORY	ffb2db1236574567d8ee1d3affd3
...
...

5、访问网页

获取cookie后,下面的事情就简单了。首先载入cookie文件内容,其次携带cookie模拟浏览器登录百度,然后执行你所需要的操作。

5.1 准备工作

包括定义好headers、载入cookie、定义好需要访问的网址

from urllib.parse import *
from urllib.request import *
from http.cookiejar import *
import time

url = 'https://www.baidu.com'

# 这里是采集了我电脑上chrome的header,具体可以换成自己的
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}

# cookie文件偷懒了,直接复制了想要的文件名。这里可以写个方法读取最新时间戳对应的cookie
cookie_jar = MozillaCookieJar('../log/BaiduCookie1658281995')
cookie_jar.load(ignore_discard=True, ignore_expires=True)

5.2 访问工作
cookie_processor = HTTPCookieProcessor(cookie_jar)
opener = build_opener(cookie_processor)

request = Request(url, headers=headers)

response = opener.open(request)
data = response.read().decode('utf8')

# 做你想做的事情
5.3 存储新的cookie

访问新的网页意味着会产生新的cookie,所以要及时存储这些cookie

cookie_jar.save('../log/BaiduCookie'+str(int(time.time())),ignore_discard=True, ignore_expires=True)

以上就是一个从0开始利用python登录百度账户的过程。
要注意cookie作为客户端与服务端通讯的密钥,其具有时效性。如果长时间不模拟登录,cookie就会失效。到时候需要重新将这个过程来过一次。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大尾巴鱼_root

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值