入门级js逆向解析——猿人学爬虫攻防大赛题目12

2021-12-30 20:22:52 浏览数 (2)

题目

今天要做的是第十二题:

任务:抓取这5页的数字,计算加和并提交结果

网页解析

F12 network查看请求,切换页码观察规律,主要变化为两个参数page和m

查看m的请求情况,initiator 中的request跳转到资源,在这里打个断点刷新下浏览器 查看到,m为btoa函数(base64位编码)加密结果

从js的btoa 、atob中抽取btoa函数部分,复制到浏览器的console中测试,如下图所示,并对照前面获得的m,对比两者确实一致

代码语言:javascript复制
 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('');
   }

代码实例

代码语言:javascript复制
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())

0 人点赞