N0rth3ty's Blog.

教务系统成绩自动化推送脚本

字数统计: 1.2k阅读时长: 5 min
2018/01/24 Share

考完试第一篇博客,好好做人。
最近在倒腾爬虫,又正好教务系统出成绩时间不统一,每次查很久。
顺手写了个自动化推送脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import requests
import re
from email.mime.text import MIMEText
import smtplib

index = 'http://idas.uestc.edu.cn/authserver/login?service=http%3A%2F%2Fportal.uestc.edu.cn%2F'
goal = 'http://eams.uestc.edu.cn/eams/teach/grade/course/person!search.action?semesterId=163&projectType='
goal1 = 'http://eams.uestc.edu.cn/eams/teach/grade/course/person!historyCourseGrade.action?projectType=MAJOR'
systerm = 'http://eams.uestc.edu.cn/eams/home!submenus.action?menu.id='
temp = 'http://eams.uestc.edu.cn/eams/home.action'
headers = {
"host": "idas.uestc.edu.cn",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0",
"Referer": "http://idas.uestc.edu.cn/authserver/login?service=http%3A%2F%2Fportal.uestc.edu.cn%2F"
}
def login():
s = requests.session()
s.cookies.clear()
r = s.get(index,headers = headers)
#print(r.text)
lt = re.findall('name="lt" value="(.*)"/>', r.text)[0]
#获取csrf_token
data = {
"username": 'username',
"password": 'password',
"lt": lt,
"dllt": "userNamePasswordLogin",
"execution": "e1s1",
"_eventId": "submit",
}
r = s.post(index,headers = headers,data = data)
r = s.get(systerm,headers = headers)
if '重复登陆'in r.text:
s.get(temp,headers = headers)
return s

def search_term():
new = login()
r = new.get(goal,headers = headers)
#print(r.text)
newtext = r.text.replace('\t','')
newtext = newtext.replace('\r\n','')
#方便匹配替换所有换行
score = re.findall('<td style="">(\d+|[\u4e00-\u9fa5]+)\s', newtext)
#匹配分数或者是否通过
subject = re.findall('<td>[A-Z]\d{7}.\d{2}</td><td>(.*?)</td>',newtext)
new = zip(subject,score)
#返回的是一个可以迭代的对象,不是列表本身,强制类型转换便于打印
new = list(new)
return new

def search_sum():
#写的时候顺手写个全部成绩查询,说不准以后会用啊,其实就正则不一样
new = login()
r = new.get(goal1, headers=headers)
# print(r.text)
newtext = r.text.replace('\t', '')
newtext = newtext.replace('\r\n', '')
#方便匹配替换所有换行
score = re.findall('(\d+|[\u4e00-\u9fa5]+)</td></tr>', newtext)
#匹配分数或者是否通过
subject = re.findall('<td>[A-Z]\d{7}.\d{2}</td><td>(.*?)</td>', newtext)
new = zip(subject, score)
for i, j in new:
print(i)
print(j)
return 0

def send():
_user = "user"#发件人
_pwd = "pwd"#授权码
_to = "to"#收件人

new = search_term()
new = str(new)
new = new.replace('[', ' ')
new = new.replace(']', '')
new = new.replace('(', '')
new = new.replace(')', '\n')
new = new.replace(',', '')
new = new.replace('\'', '')
# 处理下格式,强迫症
msg = MIMEText(new)
msg["Subject"] = "退学通知"
msg["From"] = "教务系统"
#msg["To"] = _to

s = smtplib.SMTP_SSL("smtp.qq.com", 465)
s.login(_user, _pwd)
s.sendmail(_user, _to, msg.as_string())
s.quit()

if __name__ == '__main__':
l = len(search_term())
l = 1
while True:
n = len(search_term())
if n != l:
l = n
send()

一些问题

  • csrf_token
    模拟登陆时要提交的lt参数,就是一个csrf_token,并且是放置到了session中的。所以要创建了一个session对象先获取这个token。
    Token一般用在两个地方:
    1)防止表单重复提交、 2)anti csrf攻击(跨站点请求伪造)。
    两者在原理上都是通过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。
    然后,如果应用于”anti csrf攻击”,则服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。
    不过,如果应用于”防止表单重复提交”,服务器端第一次验证相同过后,会将session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。
    上面的session应用相对安全,但也叫繁琐,同时当多页面多请求时,必须采用多Token同时生成的方法,这样占用更多资源,执行效率会降低。因此,也可用cookie存储验证信息的方法来代替session Token。比如,应对”重复提交”时,当第一次提交后便把已经提交的信息写到cookie中,当第二次提交时,由于cookie已经有提交记录,因此第二次提交会失败。
    不过,cookie存储有个致命弱点,如果cookie被劫持(xss攻击很容易得到用户cookie),那么又一次gameover。黑客将直接实现csrf攻击。
  • \r\n问题
    replece的时候遇到了一个问题,如果replece(‘\n’)会出现文本丢失,而\r\n则不会,查询后发现有如下说法
    简单说最开始回车是光标置于首位,换行是垂直下移一行。
    由于历史原因,windows环境下的换行符是\r\n
    linux和html等开源或公开标准中的换行符是\n
CATALOG
  1. 1. 一些问题