疫情自动打卡

发布于 2023-01-09  848 次阅读


主要涉及到一个查询参数的逆向.疫情填报打卡,之前用selenium写过,不过比较笨重.

现在直接使用requests.

爬虫的精髓应该是js逆向,反爬技术.
使用python的简单之处就是利用方法简单的库,cookie自动保存,留给我们的就是去逆向,多线程处理等等.

开始

首先进入官网

西北工业大学

打开检查,一般流程是发送一个GET请求,有了cookie.如果你发现响应没有set-cookie,而请求直接就有了cookie,这一般是浏览器缓存了,可以清除一下cookie.

image-20220102171907498

这就是响应,可以看到有了set-cookie,这很重要,直接提交表单的话没有cookie,很可能失败(要说为什么不是一定,这与你调的第三方包有关).

image-20220102171754941

然后输入账号密码,查看又发了什么请求,通常会发一个POST.

打开筛选器 method:POST查看

image-20220102172509367

当看到POST请求时有必要查看PAYLOAD,也就是携带的数据.

image-20220102172603819

构造请求时直接把这个表单发过去就行了.

再看看响应头又有set-cookie说明这个很有用,因为给了你cookie.

image-20220102172706501

这样登录之后就有了基本的cookie

进入疫情填报

然后进入疫情填报界面疫情每日填报

正常一波操作:打开审查,刷新,查看重要的请求(一般是jsp或者js啥的)

看到了熟悉的set-cookie

image-20220102173029972

说明这个url是需要get的,同时查看响应发现有很多个人信息,包括姓名.

注意一下:因为我们登陆时只输入了学号和密码,如果后面需要姓名,可以通过这种方法获取响应提取出姓名.

这里就可以利用正则提取出姓名.

name_info = s.get(get_name_url, headers=headers).text
name = re.search(r'姓名:(.*)<', name_info).group(1)

同时我们又可以发现还有POST请求

image-20220102173401933

查看payload,有一个

actionType: getRoles

看不出有什么特别的作用,可以不用post.

最后

然后点击每日填报,又进入新的页面,查看有没有什么请求

筛选jsp,我们到这里就可以知道这个网站的架构了,利用jsp(不过这是常见的方法)

可以发现一个请求jrsb.jsp,貌似没什么特别作用.

image-20220102173804950

不过可以看看响应的预览,后面可能会用于提取一些数据啥的.

勾选已检测,提交表单.

可以查看新的请求

image-20220102174221779

这就是提交表单的POST.

查看Payload,重点是sign和timeStamp.表单数据正常贴过去就行.

主要是sign和timeStamp数据如何获取.

image-20220102174413097

接下来说说这个重点

重点

直接全局搜索sign或者其他关键词,这里的要点是不能把之前的清空了,也就是查询字符串参数与之前的响应有关.

image-20220102174720756

结果惊奇的发现这个字段在jrsb.jsp的响应里,url就是这个字段,推测是后台java生成后发过来的.

image-20220102175014649

提取出来就行了.

query_info = s.get(get_query_url, headers=headers).text
info = re.search(r'sign=(.*?)&timeStamp=(\d*)', query_info)

后面post需要params的参数,也就是post需要data表单数据,也需要params的字符串查询参数.

post_url = 'http://yqtb.nwpu.edu.cn/wx/ry/ry_util.jsp?' + info.group()
    params = {
        'sign': sign,
        'timeStamp': timestamp
    }
    data = {
        'hsjc': '1',
        'xasymt': '1',
        'actionType': 'addRbxx',
        'userLoginId': sno,
        'szcsbm': '1',
        'bdzt': '1',
        'szcsmc': '在学校',
        'sfyzz': '0',
        'sfqz': '0',
        'tbly': 'sso',
        'qtqksm': '',
        'ycqksm': '',
        'userType': '2',
        'userName': name,
    }
    # 这里要加一下请求源 必要
    headers.update({
        'Referer': 'http://yqtb.nwpu.edu.cn/wx/ry/jrsb.jsp',
        'Origin': 'http://yqtb.nwpu.edu.cn',
    })
    r = s.post(post_url, headers=headers, data=data, params=params)

最后要加一下请求的referer

 Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的

如果不加测试发现过不了,应该是服务器有检测.

这样整个代码基本就完成了.

源代码

import json
import requests
import re


def login(sno, pwd):
    s = requests.Session()
    # CAS系统登录报文
    login_url = 'https://uis.nwpu.edu.cn/cas/login'
    be_student_url = 'http://yqtb.nwpu.edu.cn/wx/xg/yz-mobile/qj_util.jsp'
    get_name_url = 'http://yqtb.nwpu.edu.cn/wx/xg/yz-mobile/index.jsp'
    get_query_url = 'http://yqtb.nwpu.edu.cn/wx/ry/jrsb.jsp'
    headers = {
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62',
    }
    data = {
        'username': sno,
        'password': pwd,
        'currentMenu': '1',
        'execution': 'e1s1',
        '_eventId': 'submit',
        'geolocation': '',
        'submit': '稍等片刻……'
    }

    # 获取CAS系统SESSION
    # 这一步是必须的 要获取cookie
    s.get(login_url, headers=headers)
    # 登录
    s.post(login_url, headers=headers, data=data)
    # 这一步貌似并不是必要的 通过post提交一个数据
    s.post(be_student_url, headers=headers, data={'actionType': 'getRoles'})
    # 这一步是获得姓名信息
    name_info = s.get(get_name_url, headers=headers).text
    name = re.search(r'姓名:(.*)<', name_info).group(1)
    # 获得查询参数 这是之前没有的
    query_info = s.get(get_query_url, headers=headers).text
    info = re.search(r'sign=(.*?)&timeStamp=(\d*)', query_info)
    # 查询参数
    sign = info.group(1)
    timestamp = info.group(2)
    # post请求提交 注意,url后面的参数可以忽略
    post_url = 'http://yqtb.nwpu.edu.cn/wx/ry/ry_util.jsp?' + info.group()
    params = {
        'sign': sign,
        'timeStamp': timestamp
    }
    data = {
        'hsjc': '1',
        'xasymt': '1',
        'actionType': 'addRbxx',
        'userLoginId': sno,
        'szcsbm': '1',
        'bdzt': '1',
        'szcsmc': '在学校',
        'sfyzz': '0',
        'sfqz': '0',
        'tbly': 'sso',
        'qtqksm': '',
        'ycqksm': '',
        'userType': '2',
        'userName': name,
    }
    # 这里要加一下请求源 必要
    headers.update({
        'Referer': 'http://yqtb.nwpu.edu.cn/wx/ry/jrsb.jsp',
        'Origin': 'http://yqtb.nwpu.edu.cn',
    })
    r = s.post(post_url, headers=headers, data=data, params=params)
    r = json.loads(r.text)
    if r['state'] == "1":
        print('成功')


if __name__ == '__main__':
    sno = input('输入你的学号')
    pwd = input('输入你的密码')
    login(sno,pwd)

学习资料

JS逆向破解_哔哩哔哩_bilibili

这是偶然看到的,感觉挺不错,无聊时可以看看

届ける言葉を今は育ててる
最后更新于 2023-01-24