优雅的从教务系统中查成绩
0x00 写在前面
每次查成绩都需要从学校官网查,这似乎有点累,何不写个代码,自动获取成绩。(以下是实现效果)
0x01 准备工作
工具 [Chrome内核浏览器]或[IE8以上浏览器]、编程工具:python 3(可根据个人喜好来选择编程工具,这里我拿python来做演示,python3与python2有代码上的区别,注意区分。)
- 使用IE、或者chrome浏览器进入教务系统对网页进行抓包。
首先是 登录
登录所需条件:用户名、密码、验证码、登录类型、登录按钮
- 以Chrome内核浏览器为例操作步骤
按下 F12 > Network
红色按钮表示开启拦截日志
选中Preserve log 就是防止页面跳转的时候 拦截的日志信息被清理掉
- 准备工作做好以后 分别输入内容 user pwd code ,点击登录。
页面会提示验证码不正确(当然我没有输入正确的验证码)
- 登录的头信息包含(整体、响应头、请求头、提交表单)具体各个名词是什么意思,可以参考文章HTTP协议详解
首先提取出需要的数据信息。如以下
Request URL: http://119.145.248.32:81/default2.aspx
Request Method: POST
Cookie: ASP.NET_SessionId=tkppurvel0i0szru54px5145
Form_data:
__VIEWSTATE: dDw3OTkxMjIwNTU7Oz7/99NZP1opAgc5jOaeBNNUdogk9Q==
__VIEWSTATEGENERATOR: 92719903
TextBox1: user
TextBox2: pws
TextBox3: code
RadioButtonList1: %D1%A7%C9%FA
Button1:
然后我们要知道Form_data里各个数据代表什么,以及怎么获取
名称 | 获取途径 | 备注 |
---|---|---|
VIEWSTATE | 右键 查看网页源代码 >Ctrl+F >搜索VIEWSTATE | __VIEWSTATE value="dDw3OTkxMjIwNTU7Oz7/99NZP1opAgc5jOaeBNNUdogk9Q== |
__VIEWSTATEGENERATOR | 同上 | __VIEWSTATEGENERATOR value=“92719903” |
TextBox1 | 用户输入的账号信息 | 账号 |
TextBox2 | 用户输入的密码内容 | 密码 |
TextBox3 | 用户输入的验证码内容 | 验证码 |
RadioButtonList1 | URL编码 | 登录的类型:部门、教师、学生、访客,都是固定值。这里是使用了gb2312>url编码 |
Button1 | 无实际值 | 登录按钮 |
URL编码在线加解码 http://tool.chinaz.com/tools/urlencode.aspx
- 具体编码讲解可以参考文章中文编码 1:常见中文编码格式
登录的时候还有一个关键信息就是验证码图片以及Cookie
http://119.145.248.32:81/CheckCode.aspx 验证码数据
接下来是 查询功能 点击学习成绩查询
记录下拦截信息
点击查询已修课程,可以查到所有成绩
这个也是POST
- __VIEWSTATE 这个名词有点眼熟,不过里的内容是一堆乱码内容其实是一个Base64编码,具体是什么内容我们不用关心,最重要是如何获取。
我们在登录的时候也有提交过这个信息,所以也可以从网页源代码中获得。
名称 | 获取途径 | 备注 |
---|---|---|
VIEWSTATE | 右键 查看网页源代码 >Ctrl+F >搜索VIEWSTATE | __VIEWSTATE value="dDwtMTg3MzYzMTY5MDt0PHA8bDx4a… |
__VIEWSTATEGENERATOR | 同上 | __VIEWSTATEGENERATOR value=“DB0F94E3” |
ddlXN | 无实际值 | 账号 |
ddlXQ | 无实际值 | 密码 |
Button6 | URL编码: | 点击的按钮标题:查询已修课程最高成绩 |
整个流程大致就这样,也分析完了,接下来就是如何使用编程工具来实现。
0x02 功能的实现
python3 代码
# !/usr/bin/python
# encoding:utf-8
import lxml
import requests
from bs4 import BeautifulSoup
from http import cookiejar
from urllib.parse import quote
# getlist 获取网页中列表内容
def getlist(soup):
trs = soup.find_all('tr')
str = ""
for link in trs:
for td in link:
if td.string != '\n':
str = str+"|"+td.string
str = str+"\n"
print(str)
# getstate 获取网页源代码值
def getstate(soup):
list_value = []
for link in soup.find_all('input'):
list_value.append(link.get('value'))
VIEWSTATE = list_value[0]
VIEWSTATEGENERATOR = list_value[1]
return VIEWSTATE, VIEWSTATEGENERATOR
session = requests.session()
session.cookies = cookiejar.LWPCookieJar(filename='cookies')
# =====初始化自动管理Cookie
# gethtml 获取网页源代码
def gethtml(url):
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8',
'Connection': 'keep-alive',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36',
}
html = session.get(url, headers=headers)
session.cookies.save()
return html
##################正文############################
url = 'http://119.145.248.32:81/' # 初始化登录界面 目的获取 VIEWSTATE和VIEWSTATEGENERATOR
soup = BeautifulSoup(gethtml(url).text, 'lxml') # 创建 beautifulsoup 对象
VIEWSTATE, VIEWSTATEGENERATOR = getstate(soup)
# =====初始化 VIEWSTATE和VIEWSTATEGENERATOR
PostUrl = 'http://119.145.248.32:81/default2.aspx' # 登录地址
CodeUrl = 'http://119.145.248.32:81/CheckCode.aspx' # 验证码地址
# =====初始化登录post地址、验证码地址
picture = gethtml(CodeUrl).content # 获取验证码数据
local = open('./CodeImg.jpg', 'wb') # 将验证码保存到本地
local.write(picture) # 写出验证码
local.close() # 记得要关闭
# =========将验证码保存到本地
userid = input('请输入账号: ') # 提示输入并保存到userid里
pwd = input('请输入密码: ')
VerifiedCode = input('输入验证码: ')
# =========提示用户输入内容
From_Data = {
'__VIEWSTATE': VIEWSTATE,
'__VIEWSTATEGENERATOR': VIEWSTATEGENERATOR,
'TextBox1': userid,
'TextBox2': pwd,
'TextBox3': VerifiedCode,
'RadioButtonList1': '学生',
'Button1': '',
}
# =========保存表单
r = session.post(PostUrl, data=From_Data) # 使用post类型提交表单给服务器
soup = BeautifulSoup(r.text, 'lxml')
# ======获取网页返回内容
name = soup.span.string # 获取登录成功后的名字
name = name.replace('同学', '') # 替换掉同学两个字
name_urlde = quote(name.encode('gbk')) # 使用名字转为gbk再进行url编码
# =====URL编码姓名
# 判断是否登录成功
if name != '新生学籍信息查询系统':
print("欢迎您:"+name) # 登录成功后 提示信息
url = "http://119.145.248.32:81/xscj_gc.aspx?xh=" + \
userid+"&xm="+name_urlde+"&gnmkdm=N121605" # 设置查询地址
headers = { # 设置 头信息 如果没设置 可能会获取失败
'Referer': "http://119.145.248.32:81/xs_main.aspx?xh="+userid,
}
# 目的是获取 VIEWSTATE, VIEWSTATEGENERATOR
html = session.get(url, headers=headers).text
soup = BeautifulSoup(html, 'lxml') # 创建 beautifulsoup 对象
VIEWSTATE, VIEWSTATEGENERATOR = getstate(soup) # 取出源代码里的VIEWSTATE, VIEWSTATEGENERATOR
#==========设置提交表单
From_Data = {
'__VIEWSTATE': VIEWSTATE,
'__VIEWSTATEGENERATOR': VIEWSTATEGENERATOR,
'ddlXN': '',
'ddlXQ': '',
'Button6': '%B2%E9%D1%AF%D2%D1%D0%DE%BF%CE%B3%CC%D7%EE%B8%DF%B3%C9%BC%A8',
}
r = session.post(url, headers=headers, data=From_Data) #使用post类型进行提交表单
soup = BeautifulSoup(r.text, 'lxml')#取出提交信息后的内容
getlist(soup)# 获取成绩列表并展示出来
else:
print("您输入的账号或者验证码有误。请重新尝试!")
刚安装python的童鞋需要安装以下库,命令如下
pip install lxml
pip install requests
pip install BeautifulSoup
pip install cookiejar
运行结果