我就读于自动化专业,现为一名大三学生。本学期学习了“智能控制终端技术”课程,教学内容包括网络与通信基础、基于C++的Qt界面开发、Linux入门等。
在上个学期末,也就是大三上考完试后,我觉得查考试成绩十分地繁琐,每天打开教务查成绩也很浪费时间、分散精力。于是编写了一个Python爬虫程序帮我去教务系统中爬取成绩,打印成绩单并计算GPA。在本学期的Linux入门课程学习中,了解到Linux系统除了在自己电脑上装虚拟机,或双系统,还可以通过购买租赁阿里云服务器的方式使用。
于是,我通过飞天加速计划·高校学生在家实践活动获得了两周的免费阿里云ECS(弹性计算服务)使用机会。我花了一个晚上的时间熟悉了云服务器的基本操作,并扩充了之前的教务系统查成绩爬虫代码,并将Python程序运行于阿里云ECS上。在官方教程指导下,从服务器租赁到程序部署,非常简单而迅速。
当出成绩之后,程序会给我发邮件,截图如下:
下面来介绍一下我的教务系统查成绩Python程序
整个程序的实现步骤分为以下几部分:
1.教务系统爬虫
2.发邮件
3.整合1和2到一个py脚本中
4.部署到阿里云Linux服务器
除了py脚本,还需要在同一个路径下创建一个名为1.txt的文本文档,用于存放上一次查询时,出了几门课的成绩,比如:上一次查询出了3门课的成绩,那么1.txt文档的内容就是3
1.教务系统爬虫
我们学校的教务系统是正方软件股份有限公司开发的,实现的思路是:
- 在Chrome浏览器里打开教务系统并登陆,找到查成绩的页面
- 打开浏览器检查功能(F12),找到FXH文件,刷新网页,一般来说,成绩信息会存在一个json格式的文件中
- 用python的requests库进行带参数的请求,带上headers、data,cookie会在请求头里
- 从json文件中提取成绩相关的元素,存入变量
import requests
headers = {} # 需要填充一下,是字典的形式,可以在浏览器中用检查找到请求头等信息
data = {} # 和headers一样要自己填充
url = 'https://jwxt.cjlu.edu.cn/cjcx/cjcx_cxXsgrcj.html?'
res = requests.post(url, headers = headers, data = data)
json = res.json()
text = text + "\r\n{} {} {} {}".format('课程名称'.center(10, chr(12288)), '学分'.center(4, chr(12288)), '成绩'.center(4, chr(12288)), '绩点'.center(4, chr(12288)))
sum_credit_gp = 0.0
sum_credit = 0.0
for each in json['items']:
subject = each['kcmc'] # 课程名称
credit = each['xf'] # 学分
grade = each['bfzcj'] # 成绩
gradepoint = each['jd'] # 绩点
credit_gp = float(credit) * float(gradepoint) # 学分绩点 = 学分*绩点
sum_credit = sum_credit + float(credit)
sum_credit_gp = sum_credit_gp + credit_gp # 计算GPA
text = text + "\r\n{} {} {} {}".format(subject.center(10, chr(12288)), credit.center(4, chr(12288)), grade.center(4, chr(12288)), gradepoint.center(4, chr(12288)))
print(text)
#with open("/home/yrl/request_grade/1.txt", 'r') as f: # 部署到linux系统中,使用绝对路径
with open("1.txt", 'r') as f: # 1.txt存储上一次num的数值
num = f.read() # 出了几门课的成绩,num就是几
if num == str(len(json['items'])):
print("没有变化")
# 不发送邮件
if num!=str(len(json['items'])):
#with open("/home/yrl/request_grade/1.txt", 'w') as f:
with open("1.txt", 'w') as f:
print("发生变化,出了新的成绩")
# 发送邮件
self.send_mail()
# 并修改txt文件
f.write(str(len(json['items'])))
2.发邮件
发邮件程序中需注意
- from_addr是发信人的邮箱
- to_addr是收信人的邮箱,发信人和收信人邮箱可以是同一个
- password是POP3授权码,我用的是qq邮箱,应该是一个16位的字符串
import smtplib #调用smtplib模块 用于发信动作
from email.mime.text import MIMEText #调用MIMEText方法 构建邮件内容
from email.header import Header #从email包引入Header()方法 构建邮件头
from_addr = "xxxxx@qq.com"
password = "xxxxx" #POP 授权码
to_addr = "xxxxx@qq.com"
smtp_server = 'smtp.qq.com' #发信服务器
title = '请输入邮件标题'
text = '请输入正文内容'
msg = MIMEText(text,'plain','utf-8') #正文内容 参1为正文内容 参2为格式(plain为纯文本) 参3为编码
msg['From'] = Header(from_addr) #构建邮件头
msg['To'] = Header(to_addr) #构建邮件头
msg['Subject'] = Header(title) #构建邮件头
server = smtplib.SMTP_SSL(smtp_server) #开启发信服务,这里使用的是加密传输
server.connect(smtp_server,465)
server.login(from_addr, password) #登录
server.sendmail(from_addr, to_addr, msg.as_string()) #发送 参1发件人 参2收件人 参3"内容"
server.quit() #关闭服务器
print('邮件已发送')
3.整合1和2到一个py脚本中
import requests
import smtplib #调用smtplib模块 用于发信动作
from email.mime.text import MIMEText #调用MIMEText方法 构建邮件内容
from email.header import Header #从email包引入Header()方法 构建邮件头
class RequestGrade:
text = ""
def send_mail(self):
from_addr = "xxxxx@qq.com"
password = "xxxxx" #POP 授权码
to_addr = "xxxxx@qq.com"
smtp_server = 'smtp.qq.com' #发信服务器
title = '出了新的成绩'
msg = MIMEText(self.text,'plain','utf-8') #正文内容 参1为正文内容 参2为格式(plain为纯文本) 参3为编码
msg['From'] = Header(from_addr) #构建邮件头
msg['To'] = Header(to_addr) #构建邮件头
msg['Subject'] = Header(title) #构建邮件头
server = smtplib.SMTP_SSL(smtp_server) #开启发信服务,这里使用的是加密传输
server.connect(smtp_server,465)
server.login(from_addr, password) #登录
server.sendmail(from_addr, to_addr, msg.as_string()) #发送 参1发件人 参2收件人 参3"内容"
server.quit() #关闭服务器
print('邮件已发送')
def get_grade(self):
headers = {}
data = {}
url = 'https://jwxt.cjlu.edu.cn/cjcx/cjcx_cxXsgrcj.html?'
res = requests.post(url, headers = headers, data = data)
json = res.json()
print("\n{} {} {} {}".format('课程名称'.center(10, chr(12288)), '学分'.center(4, chr(12288)), '成绩'.center(4, chr(12288)), '绩点'.center(4, chr(12288))))
self.text = self.text + "\r\n{} {} {} {}".format('课程名称'.center(10, chr(12288)), '学分'.center(4, chr(12288)), '成绩'.center(4, chr(12288)), '绩点'.center(4, chr(12288)))
sum_credit_gp = 0.0
sum_credit = 0.0
for each in json['items']:
subject = each['kcmc']
credit = each['xf']
grade = each['bfzcj']
gradepoint = each['jd']
credit_gp = float(credit) * float(gradepoint)
sum_credit = sum_credit + float(credit)
sum_credit_gp = sum_credit_gp + credit_gp
print("{} {} {} {}".format(subject.center(10, chr(12288)), credit.center(4, chr(12288)), grade.center(4, chr(12288)), gradepoint.center(4, chr(12288))))
self.text = self.text + "\r\n{} {} {} {}".format(subject.center(10, chr(12288)), credit.center(4, chr(12288)), grade.center(4, chr(12288)), gradepoint.center(4, chr(12288)))
print('\n\t\tGPA:{:.5f}'.format(sum_credit_gp / sum_credit))
self.text = self.text + ('\r\n\t\tGPA:{:.5f}'.format(sum_credit_gp / sum_credit))
with open("/home/yrl/request_grade/1.txt", 'r') as f:
#with open("1.txt", 'r') as f:
num = f.read() # 出了几门课的成绩
if num == str(len(json['items'])):
print("没有变化")
# 不发送邮件
if num!=str(len(json['items'])):
with open("/home/yrl/request_grade/1.txt", 'w') as f:
#with open("1.txt", 'w') as f:
print("发生变化,出了新的成绩")
# 发送邮件
self.send_mail()
# 并修改txt文件
f.write(str(len(json['items'])))
if __name__ == "__main__":
r = RequestGrade()
r.get_grade()
4.部署到阿里云Linux服务器
我没有选Ubuntu或CentOS,因为他们自带的是Python版本是Python 2,而Alibaba Cloud Linux自带了Python 3。如果使用的是Python 2,可以下载安装Python 3,或重装系统,阿里云服务器重装系统很简便。
注意:需要提前装好pip包管理工具,并安装requests、smtplib等库
pip3 install requests
接下来就可以把我们的程序部署到服务器里啦
创建一个目录 名为request_grade
mkdir request_grade
在该路径下创建1.txt和main.py文件,使用vi编辑器填入数字和脚本
touch main.py
vi main.py
在终端定时运行这个程序
编辑定时任务
crontab -e
每分钟都运行一次
* * * * * python /home/yrl/request_grade/main.py
以上就是教务系统爬虫Python程序的源代码了。我的Python和Linux基础都较为一般,代码也有些许不足或让人不易理解,请多体谅。
感谢阿里云-高校学生在家实践活动给我提供了这个机会,给我实操使用Linux服务器的机会。
我在这个过程中也遇到了一些问题,可以给新手一些tips:
1.服务器的端口可以不要选择默认的22,不然睡一觉醒来,远程登录一下服务器就会发现有几百条甚至上千条访问失败的记录,这应该是其他人对服务器在进行扫描、攻击
2.续第一个问题,为提高安全性,建议把密码设置地更复杂一些
3.阿里云也提供了iPadOS和iOS的软件,可以直接使用SSH远程连接,非常方便;也可以使用其他SSH远程连接
希望未来能进一步深入学习,分享一些更优质的原创作品