东南大学研究生系统模拟登录

这是一个简单的Python爬虫模拟登录实战小脚本,主要在于__VIEWSTATE这个变量的处理。

一、模拟登录

1、导入包

1
2
3
4
import requests
from lxml import etree
import pandas as pd
import base64

2、构造请求头、表单数据。

1
url = "http://121.248.63.139/nstudent/login.aspx"
1
2
3
4
5
6
headers = {
'Host': "121.248.63.139",
'Origin': "http://121.248.63.139",
'Referer': "http://121.248.63.139/nstudent/login.aspx",
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
}
1
2
# 创建一个session对象 
s = requests.Session()

下面是关键,由于ASP.NET网站每次都会发送一个__VIEWSTATE到隐藏域,后面提交表单时会提交上去,所以这里我们需要先获取到这个值,具体方法是先请求一次该url,从response中提取出__VIEWSTATE,然后再在POST的时候提交上去。

1
response = s.get(url,headers = headers)
1
2
3
content = response.text
sel = etree.HTML(content)
viewstate = sel.xpath('//input[@name="__VIEWSTATE"]/@value')[0]

下面简单看下__VIEWSTATE经过base64解码后的值:

1
viewstate_decode = base64.b64decode(viewstate)

下面是构造POST请求提交的数据:

1
2
3
4
5
6
7
data = {
'__VIEWSTATE': viewstate,
'txt_user': "用户名",
'txt_password': "密码",
'ok.x':'44',
'ok.y':'6'
}

3、建立会话。

requests库的session对象能够帮我们跨请求保持某些参数,这样我们才能进行后面的查成绩等等操作。

1
2
# 用session对象发出get请求
response = s.post(url,headers = headers,data = data)
1
response.apparent_encoding

‘utf-8’

1
response.encoding = response.apparent_encoding

然后输入:

1
response.text

看到这个下面这个界面,说明模拟登录成功!

欢迎使用东大研究生管理平台

二、成绩查询

1、成绩页面获取

采用session变量去访问成绩页面。

1
2
url_grade = "http://121.248.63.139/nstudent/grgl/xskccjcx.aspx"
response_grade = s.get(url_grade,headers = headers)
1
content = response_grade.text

2、页面解析问题处理

这里出了个问题,下面是问题描述以及解决方案。

1)、问题描述

我在用XPath匹配元素的时候,发现老是出错,后来发现是<tbody>标签上有文章。

2)、问题分析

我使用Chrome的元素审查对网页进行分析来得到XPath路径,但是Chrome会对网页源码进行加工,在<table>标签中,如果源码中没有写<tbody>标签,在元素审查和查看网页源代码中还是会将<tbody>强行添加上。

当然,若源代码中没有<tbody>,而我们信任Chrome而把它添进XPath的话,是不会匹配出想要的结果的。

我们可以通过

1
print(response)

对源代码进行检查,确定有没有<tbody>标签后,再得出XPath。

1
2
selector = etree.HTML(content)
table = selector.xpath('//table[@class="box" and @bordercolor="#5c6bac"]/tr') #这里很奇怪,明明中间还有一个tbody,但是加了tbody定位不到

3、学位课程成绩查询

下面查询学位课程成绩:

1
2
3
4
5
6
7
8
9
degreeCourses = table[2].xpath('td[1]/table/tr')
degreeList = []
for i in degreeCourses[1:]:
course = i.xpath('td[1]/text()')[0]
credit = i.xpath('td[2]/text()')[0]
term = i.xpath('td[3]/text()')[0]
score = i.xpath('td[4]/text()')[0]
score_standardized = i.xpath('td[5]/text()')[0]
degreeList.append({'课程':course,'课程学分':credit,'选修学期':term,'成绩':score,'规格化成绩':score_standardized})
1
2
df_degree = pd.DataFrame(degreeList)
df_degree
成绩规格化成绩课程课程学分选修学期
09183工程矩阵理论3.01
18281学位英语4.02
28581学位英语01
38581中国特色社会主义理论与实践研究2.01
49078VLSI设计技术3.02
59187射频集成电路设计基础3.01
67789CMOS模拟集成电路分析与设计3.01

4、非学位课程成绩查询

1
2
3
4
5
6
7
8
9
optionalCourses = table[2].xpath('td[2]/table/tr')
optionalList = []
for i in optionalCourses[1:]:
course = i.xpath('td[1]/text()')[0]
credit = i.xpath('td[2]/text()')[0]
term = i.xpath('td[3]/text()')[0]
score = i.xpath('td[4]/text()')[0]
score_standardized = i.xpath('td[5]/text()')[0]
optionalList.append({'课程':course,'课程学分':credit,'选修学期':term,'成绩':score,'规格化成绩':score_standardized})
1
2
df_optional = pd.DataFrame(optionalList)
df_optional
成绩规格化成绩课程课程学分选修学期
08281自然辩证法概论1.01
19584微波毫米波工程设计2.02
28781微波非线性网络2.02
39584微波电路系统与应用2.02
49379光纤通信用集成电路设计3.02

5、规格化平均成绩计算

1
2
3
4
5
6
sums_score = 0
sums_credit = 0
for i in range(len(df_degree['规格化成绩'])):
sums_score += int(df_degree['规格化成绩'][i]) * float(df_degree['课程学分'][i])
sums_credit += float(df_degree['课程学分'][i])
average_degree = sums_score / sums_credit
1
average_degree

83.16666666666667

赞赏一杯咖啡
0%