PEM
PysicalExperimentMotor(PEM)——物理实验小马达
今天教大家怎么用物理实验制作小马达……Emmm,不好意思,走错场了。
1. 前言
1.1 简介
- PysicalExperimentMotor(PEM)是一款针对CUMT大学物理实验选课的一款软件。
1.2 起源
- 大学物理实验作为全校理工科学生的必修课,每到实验选课时间服务器就会卡到让人自闭,各实验的开课时间有限且名额很少,因此要选到自己空闲时间的实验不是一件容易的事,而想要选到自己空闲时间且操作简单的实验更是难上加难。
- 笔者在大一曾连续三个周没选到实验,所以决定做一个这样的软件方便选课。
- 起初的Version 1:
- 当时还不叫小马达,造出来大概也就自己用用,也没有想到会开发到2代。
- 现在的Version 2:
- 2代较1代相比,采用Python编写,兼容性、操作性和稳定性都有了很大提升。当然,开发的路上困难重重,刚造出来的时候稳定性也不是很好,因为平时调试和实际选课环境是不同的,bug都是后来实践中一点点消除的。
- 笔者目前已经大二了,终于摆脱了大物实验( ̄▽ ̄)。
2. 开发过程
2.1 开发工具
- Pycharm——一款优秀的Python IDE
- Fiddler——抓包工具
- Google Chrome——谷歌浏览器
2.2 开发环境
- 操作系统:Win 10
- 编程语言:Python 2.7(笔者最开始学Python学的是Python2,现在Python 2.7已经停更了)
2.3 核心技术
- 利用python模拟登录选课网站,之后爬取选课信息,本地选择后,向服务器提交请求。
- 关键操作是模拟登录网站,只要能登录成功,就可以获取选课信息及相关数据。
2.4 具体实现
2.4.1 模拟登录
- 方法1:利用selenium库
import selenium
其实用selenium省时省力,但是会导致软件可移植性较差。然而,最初当笔者尝试用requests库模拟登录时,却一直无法登录成功,最后无奈在原始版本中选取了selenium进行登录。这里不再阐述selenium登录方法。
- 方法2:利用requests库
import requests
通过Fiddler抓取网页登录时向服务器提交的数据,转换成代码实现就可以了。
抓包发现提交的data参数中密码没有经过加密,这省了不少事,验证码的获取可以将验证码图片缓存到本地通过人工输入的方式传入,但是VIEWSTATE、EVENTVALIDATION这俩是啥啊?
查阅资料发现,由于选课的登录网址是aspx,这类网址登录时会携带隐藏的VIEWSTATE、EVENTVALIDATION数据,具体值可以在登录页源码中获取。
# 获取隐藏POST数据
def get_hidden(self):
soup = BeautifulSoup(self.html, "html.parser")
self.VIEWSTATE = soup.find(id="__VIEWSTATE")["value"]
self.EVENTVALIDATION = soup.find(id="__EVENTVALIDATION")["value"]
(笔者在这次写作截图发现了新的提交参数VIEWSTATEGENERATOR,而这在当时是没有的,不过这个参数对登录没有产生影响,我们暂且就不管它。)
关于验证码的获取:
# 获取验证码
def get_captcha(self):
captcha_url = "http://ecpt.cumt.edu.cn/model/TwoGradePage/VerifyCode.aspx?"
try:
captcha = self.session.get(captcha_url, headers=self.headers).content
except Exception as e:
print(u"连接失败,正在重连...")
self.get_captcha()
with open("captcha.jpeg", "wb") as f:
f.write(captcha)
os.startfile("captcha.jpeg")
print(u"请输入验证码:"),
self.captcha = raw_input()
self.get_hidden()
于是完整的data请求参数如下:
data = {
"ScriptManager1": "login$UpPanel1|login$Btn_Login",
"__EVENTTARGET": "",
"__EVENTARGUMENT": "",
"__VIEWSTATE": self.VIEWSTATE,
"__EVENTVALIDATION": self.EVENTVALIDATION,
"login$txtName": self.num,
"login$txtPwd": self.password,
"login$txt_Code": self.captcha,
"login$Btn_Login": "%E7%99%BB%C2%A0%E5%BD%95"
}
获取到这些就可以登录成功了?
还要注意要在HTTP报头headers里加入“Content-Type”: “application/x-www-form-urlencoded”防止post时对data进行url转码,笔者当时就是忽略了这个导致登录失败的,之后才注意到,因此在最开始的版本里是用selenium登录的。
# 完整的HTTP报头
self.headers = {
"Host": "ecpt.cumt.edu.cn",
"Connection": "keep-alive",
# "Content-Length": "86",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Origin": "http://ecpt.cumt.edu.cn",
"X-Requested-With": "XMLHttpRequest",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36",
# "Content-Type": "application/json",
# "Referer": "http://ecpt.cumt.edu.cn/index.aspx",
# "Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Content-Type": "application/x-www-form-urlencoded" # 防止post时对data进行url转码
}
至此,模拟登录就完成了。
2.4.2 实验信息获取
- 简单来说就是向实验列表的URL发送get请求,之后将返回信息中的实验信息爬取出来,输出到屏幕上。
这是爬虫的基本操作,不在赘述。
2.4.3 发送选课请求
- 不同的实验对应不同的URL。
- 同样通过抓包获取选择实验时向服务器发送了哪些请求,逐一分析。
- post提交的实验时间需要通过用户选择指定。
- 发送请求后,根据服务器返回的响应判断是否选课成功。
至此,PEM最主要的功能“实验选课”已介绍完毕。
2.4.4 其余功能
- 实验余量查询——可以获取各实验的选择情况
- 课表查询——可以查询到自己已选的实验信息(审批通过的实验才会显示)
- 查看公告栏通知——查看官网公告栏的通知
- 报个Bug/提个建议——向作者发送Bug或建议信息
- 退出程序——关闭软件
2.5 打包程序
- 可通过pyinstaller将py文件打包成可执行文件exe在Windows系统下运行。
2.6 开源代码
- 完整代码已上传到GitHub:https://github.com/RunRainN/PysicalExperimentMotor。
3. 实际操作
3.1 流程演示
https://www.bilibili.com/video/BV1H7411c7uJ
3.2 实战演示
https://www.bilibili.com/video/BV1H7411c7uJ?p=2
Tip:程序运行中若卡住,请检查窗口是否进入了选择模式,如果是,则只需按下回车,变成正常状态
,程序即可继续运行。若正常状态下卡住,则应是网络原因,需要重新运行程序。
4. 注意事项
- 为了软件的持续使用,请勿传播宣传。
- 本软件的最终解释权归作者所有。
2条评论
AffiliateLabz
Great content! Super high-quality! Keep it up! 🙂
Chenyifan
小倪哥太强啦,不知道我们能用这软件吗