利用Python自动化完成每期的青年大学习,将python脚本托管到GitHub action并设置定时任务之后即可完全解放双手。
准备工作
要想自动化地完成这一操作,首先我们得分析当我们在微信上点开青年大学习的时候,后台到底干了什么,这样我们才能知道如何去自动化地完成这一系列动作。我们怎么才能知道呢,抓包看一下嘛,遇事不决,先抓包。
抓包软件,实际上就是接管你的系统代理,所有数据包都经过这个软件之后,再到原本要去的地方,大概就这个意思。

所以我们先要准备抓包工具
安装抓包软件
我用的是Charles,挺好用的软件,官网下载就好,安装一路点过就好了。
安装证书
软件安装完成后还要安装CA证书,点install一路下一步安装就好

安装手机证书
由于青年大学习必须得用微信完成,大学习的网址用电脑浏览器打开会提示必须用微信打开,单纯的改浏览器UA根本没用,因为青年大学习还要用微信登陆,所以我们抓包的时候用手机操作,然后用Charles查看发送的数据包即可。
但是现在Charles仅仅接管了电脑的系统代理,不拍,刚刚的选项还有一个,给手机安装证书,点击之后手机与电脑连接统一局域网,然后手机代理设置为手动,代理主机设置为电脑即可。

按照要求进行操作,代理主机地址就是192.168.5.6,端口8888,每个人都不一样,地址其实就是电脑的内网ip。

然后按照要求手机访问chls.pro/ssl去下载证书文件,这时候电脑上会有提示,是否允许连接,选择allow即可,下载好证书之后在手机设置,隐私安全之类的里面安装证书即可。
现在Charles就可以对手机进行抓包了。
开始抓包
电脑端保持监听,手机正常操作打开青年大学习,一系列操作之后可以在电脑上看到,手机访问了这个网址:

点击开始学习后,在api下的student多了commit,这就是学习是向后台提交的数据。

编写代码测试
直接POST
可以看到,访问类型是POST,直接用python进行测试。

import requests url = "http://dxx.scyol.com/api/student/commit" r = requests.post(url) r.encoding = 'utf-8' print(r.text)
|
运行结果如下,说明还是需要设置UA、token之类的东西。

观察之前正常操作时发送的commit:

添加UA和token
就用这个UA和token,重新编写代码测试:
import requests url = "http://dxx.scyol.com/api/student/commit" agent = { "User-Agent": "Mozilla/5.0 (Linux; Android 10;)XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 'Content-Type': 'application/json', "token": "XXXXXXXXXXXXXXX", } r = requests.post(url, headers=agent) r.encoding = 'utf-8' print(r.text)
|
再次运行,还是有问题,说明还是缺少东西。

想到青年大学习开始前还要填写一些信息,但是这些操作并没有涉及到填写信息,再次分析抓包数据,在/api/stages/currentInfo中发现个人信息数据。

添加json数据
直接构造data,按照格式填入自己的数据:
import requests url = "http://dxx.scyol.com/api/student/commit" agent = { "User-Agent": "Mozilla/5.0 (Linux; Android 10;)XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 'Content-Type': 'application/json', "token": "XXXXXXXXXXXXXXX", } data = { 'name': 'xxx', 'tel': 'xxxxxxxxxxxxx', 'org': 'xxxxxxxxx', 'lastOrg': 'xxxxxxxxxx', 'orgName': 'xxxxxxxxxxxxx', 'allOrgName': 'xxxxxxxxxxxxxxxx' } r = requests.post(url, headers=agent, data=json.dumps(data)) r.encoding = 'utf-8' print(r.text)
|
再次运行测试,发现返回结果正常,搞定!

利用github action自动化运行
现在虽说可以直接运行完成学习,但是手动运行跟手机上直接操作好像没有什么区别,所以 再次用万能的action:
编写workflow:
将编写好的代码保存后上传到github仓库,由于代码中有许多隐私信息,所以创建私有仓库,也可以在公有仓库中用env,但是麻烦,不用!
在仓库根目录下创建.github
文件夹,在里面创建workflow
文件夹,再在里面放入.yml
文件就可以啦
name: action
on: push: branches: [ main ] pull_request: branches: [ main ] schedule: - cron: '00 05 * * *' workflow_dispatch: Scheduled: inputs: description: 'Scheduled Time' required: false
jobs: qndxx:
runs-on: ubuntu-latest
steps: - uses: actions/checkout@v2 - name: Set up Python 3.9 uses: actions/setup-python@v2 with: python-version: 3.9 - name: Install dependencies run: | python -m pip install --upgrade pip pip install requests - name: 'action' run: | python main.py
|
这个文件会在每天中午一点自动运行,定时设置可以自己修改,一般一周运行两次就好了。
添加邮件提醒
每次运行之后结果对不对呢,这点我们没法第一时间知道,我不允许这样的情况出现,所以再次修改Python代码,添加发送邮件功能:
一般来说自己给自己发,寄件邮箱和收件邮箱用同一个就好了。
def Send_Email(str): msg = MIMEText(f'运行返回结果:{str}') msg["Subject"] = "青年大学习自动化反馈" msg["From"] = 'action bot' msg["To"] = 'xxx' from_addr = 'xxxxxxxxxx@qq.com' password = 'xxxxxxxxxxxxxxxx' smtp_server = 'smtp.qq.com' to_addr = 'xxx@xxx.xxx' try: server = smtplib.SMTP_SSL(smtp_server, 465, timeout=2) server.login(from_addr, password) server.sendmail(from_addr, to_addr, msg.as_string()) server.quit() print('success') except Exception as e: if e == None: print('Faild:%s' % e) pass
|
完整代码
import requests import json import smtplib from email.mime.text import MIMEText
def Send_Email(str): msg = MIMEText(f'运行返回结果:{str}') msg["Subject"] = "青年大学习自动化反馈" msg["From"] = 'action bot' msg["To"] = 'xxx' from_addr = 'xxxxxxxxxx@qq.com' password = 'xxxxxxxxxxxxxxxx' smtp_server = 'smtp.qq.com' to_addr = 'xxx@xxx.xxx' try: server = smtplib.SMTP_SSL(smtp_server, 465, timeout=2) server.login(from_addr, password) server.sendmail(from_addr, to_addr, msg.as_string()) server.quit() print('success') except Exception as e: if e == None: print('Faild:%s' % e) pass def main(): url = "http://dxx.scyol.com/api/student/commit" agent = { "User-Agent": "Mozilla/5.0 (Linux; Android 10;)XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 'Content-Type': 'application/json', "token": "XXXXXXXXXXXXXXX", } data = { 'name': 'xxx', 'tel': 'xxxxxxxxxxxxx', 'org': 'xxxxxxxxx', 'lastOrg': 'xxxxxxxxxx', 'orgName': 'xxxxxxxxxxxxx', 'allOrgName': 'xxxxxxxxxxxxxxxx' } r = requests.post(url, headers=agent, data=json.dumps(data)) r.encoding = 'utf-8' Send_Email(r.text) if __name__=='__main__': main()
|
运行效果
