今天要做的是第十二题:
任务:抓取这5页的数字,计算加和并提交结果
F12 network查看请求,切换页码观察规律,主要变化为两个参数page和m
查看m的请求情况,initiator 中的request跳转到资源,在这里打个断点刷新下浏览器 查看到,m为btoa函数(base64位编码)加密结果
从js的btoa 、atob中抽取btoa函数部分,复制到浏览器的console中测试,如下图所示,并对照前面获得的m,对比两者确实一致
var base64hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// btoa method
function btoa (s) {
if (/([^\u0000-\u00ff])/.test(s)) {
throw new Error('INVALID_CHARACTER_ERR');
}
var i = 0,
prev,
ascii,
mod,
result = [];
while (i < s.length) {
ascii = s.charCodeAt(i);
mod = i % 3;
switch(mod) {
// 第一个6位只需要让8位二进制右移两位
case 0:
result.push(base64hash.charAt(ascii >> 2));
break;
//第二个6位 = 第一个8位的后两位 + 第二个8位的前4位
case 1:
result.push(base64hash.charAt((prev & 3) << 4 | (ascii >> 4)));
break;
//第三个6位 = 第二个8位的后4位 + 第三个8位的前2位
//第4个6位 = 第三个8位的后6位
case 2:
result.push(base64hash.charAt((prev & 0x0f) << 2 | (ascii >> 6)));
result.push(base64hash.charAt(ascii & 0x3f));
break;
}
prev = ascii;
i ++;
}
// 循环结束后看mod, 为0 证明需补3个6位,第一个为最后一个8位的最后两位后面补4个0。另外两个6位对应的是异常的“=”;
// mod为1,证明还需补两个6位,一个是最后一个8位的后4位补两个0,另一个对应异常的“=”
if(mod == 0) {
result.push(base64hash.charAt((prev & 3) << 4));
result.push('==');
} else if (mod == 1) {
result.push(base64hash.charAt((prev & 0x0f) << 2));
result.push('=');
}
return result.join('');
}
import requests
import execjs # pip install PyExecJS -安装引用包
def get_m(page):
"""使用复制过来的btoa函数 定义加密函数,获取m值"""
with open("btoa.js", 'r', encoding='utf-8') as f:
js = f.read()
s = "yuanrenxue" + str(page)
m = execjs.compile(js).call('btoa', s)
return m
# # 测试
# print(get_m(1))
def get_json(page):
url = "https://match.yuanrenxue.com/api/match/12?"
params = {
'page': page,
'm': get_m(page)
}
# 点击第4 第5页 会跳出提示,填写自己的即可,注意cookie 不传请求到的数据是一样的,不是你页面上显示的数据
# 记得打印对比下
headers = {
'user-agent': "yuanrenxue.project",
'cookie': 'sessionid=使用你自己的seeionid'
}
response = requests.get(url, params=params, headers=headers)
return response.json()
# # 数据请求测试
# print(get_json(1))
def sum_data():
data = []
"""循环页码,取到所有数据,并计算求和"""
for page in range(1, 6):
json_data = get_json(page)
print(json_data)
for d in json_data.get("data"):
data.append(d['value'])
return sum(data)
if __name__ == '__main__':
print("所有数字之和为:", sum_data())