这是我JS逆向的习作之一:使用requests库爬取我的博客阅读量
关键点1:Cookies需要有UserName和UserToken,其中UserToken从浏览器中先获取。
关键点2:加密过程需要先产生32位UUID,然后拼接链接:“请求方法 响应类型 x-ca-key UUID 访问链接”,但后来发现随便撸一个UUID都行。
关键点3:如果链接带有参数,那就必须拆散参数然后按字母顺序重新排列组合
关键点4:请求headers必须带有'accept': 'application/json, text/plain, */*',否则请求失败。
import requests
import hmac
from random import randint
from re import search
from base64 import b64encode
from hashlib import sha256
def get_csdn(url):
# 用随机数生成32位的UUID
# uid = ''.join(f'{randint(0,16):x}' for _ in range(32))
# uuid = f'{uid[:8]}-{uid[8:12]}-{uid[12:16]}-{uid[16:20]}-{uid[20:]}'
# 原来随便撸一个UUID也行
uuid = '9527-3547-709394'
url_path = search('(.*)://(.*?)/(.*)', url)[3]
# 如果链接带有参数,那就必须拆散参数然后排序重组
if '?' in url_path:
param = '&'.join(sorted(search('\?(.*)', url_path)[1].split('&')))
url_path = url_path[:url_path.find('?')]+'?'+param
# 拼接字符串,其中x-ca-key在JS里可找到
text = f'GET\napplication/json, text/plain, */*\n\n\n\nx-ca-key:203803574\nx-ca-nonce:{uuid}\n/{url_path}'
# HMAC256加密的key,该key的值在JS里可找到
key = '9znpamsyl2c7cdrr9sas0le9vbc3r6ba'
# HMAC256加密后的值
signature = str(b64encode(hmac.new(key.encode('utf-8'), text.encode('utf-8'), digestmod=sha256).digest()), 'utf-8')
# 请求头必须加下面的元素
se.headers.update({'X-Ca-Key': "203803574",
'X-Ca-Nonce': uuid,
'X-Ca-Signature': signature,
'X-Ca-Signature-Headers': "x-ca-key,x-ca-nonce",
# UserName、UserToken可在浏览器开发者工具里复制粘贴到这里
'cookie': 'UserName=你的用户名; UserToken=你的UserToken;',
'accept': 'application/json, text/plain, */*',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
})
res = se.get(url)
assert res.status_code == 200, f'{res.status_code} error'
return res.json()
if __name__ == '__main__':
se = requests.Session()
# 第一步:先获取总阅读量
url1 = "https://bizapi.csdn.net/blog-console-api/v1/data/blog_statistics"
data1 = get_csdn(url1)
if data1['msg'] == 'success':
for k in data1['data']:
if k['name'] == '阅读量':
print(f"{k['name']}: {k['num']}")
break
# 第二步:获取最近7天阅读量
url2 = 'https://bizapi.csdn.net/blog/phoenix/console/v1/data/all-article'
data2 = get_csdn(url2)
week_total = 0
if data2['message'] == 'success':
for k in data2['data']['list']:
print(f"{k['pdate']}: {k['viewCount']}")
week_total += int(k['viewCount'])
print(f'最近7天总阅读量:{week_total}')
运行结果截图: