模拟登录
import requests
from lxml import etree
import pandas as pd
构造请求头、表单数据。
url = "http://121.248.63.139/nstudent/login.aspx"
headers = {
'Cookie': "xxx", #这里我删除了,实际需要添加
'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"
}
data = {
'txt_user': "xxx",
'txt_password': "xxx"
}
建立会话。
requests库的session对象能够帮我们跨请求保持某些参数,这样我们才能进行后面的查成绩等等操作。
# 创建一个session对象
s = requests.Session()
# 用session对象发出get请求
response = s.post(url,headers = headers,data = data)
response.text
然后输入:
response.text
看到这个下面这个界面,说明模拟登录成功!
欢迎使用东大研究生管理平台
成绩查询
成绩页面获取
采用session变量去访问成绩页面。
url_grade = "http://121.248.63.139/nstudent/grgl/xskccjcx.aspx"
response_grade = s.get(url_grade,headers = headers)
content = response_grade.text
页面解析
这里出了个问题,下面是问题描述以及解决方案。
问题描述
我在用XPath匹配元素的时候,发现老是出错,后来发现是<tbody>
标签上有文章。
问题分析
我使用Chrome的元素审查对网页进行分析来得到XPath路径,但是Chrome会对网页源码进行加工,在<table>
标签中,如果源码中没有写<tbody>
标签,在元素审查和查看网页源代码中还是会将<tbody>
强行添加上。
当然,若源代码中没有<tbody>
,而我们信任Chrome而把它添进XPath的话,是不会匹配出想要的结果的。
我们可以通过
print(response)
对源代码进行检查,确定有没有<tbody>
标签后,再得出XPath。
selector = etree.HTML(content)
table = selector.xpath('//table[@class="box" and @bordercolor="#5c6bac"]/tr') #这里很奇怪,明明中间还有一个tbody,但是加了tbody定位不到
下面查询学位课程成绩:
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})
df_degree = pd.DataFrame(degreeList)
df_degree
成绩 | 规格化成绩 | 课程 | 课程学分 | 选修学期 | |
---|---|---|---|---|---|
0 | 91 | 83 | 工程矩阵理论 | 3.0 | 1 |
1 | 82 | 81 | 学位英语 | 4.0 | 2 |
2 | 85 | 81 | 学位英语 | 0 | 1 |
3 | 85 | 81 | 中国特色社会主义理论与实践研究 | 2.0 | 1 |
4 | 90 | 78 | VLSI设计技术 | 3.0 | 2 |
5 | 91 | 87 | 射频集成电路设计基础 | 3.0 | 1 |
6 | 77 | 89 | CMOS模拟集成电路分析与设计 | 3.0 | 1 |
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})
df_optional = pd.DataFrame(optionalList)
df_optional
成绩 | 规格化成绩 | 课程 | 课程学分 | 选修学期 | |
---|---|---|---|---|---|
0 | 82 | 81 | 自然辩证法概论 | 1.0 | 1 |
1 | 87 | 81 | 微波非线性网络 | 2.0 | 2 |
2 | 95 | 85 | 微波电路系统与应用 | 2.0 | 2 |
3 | 93 | 79 | 光纤通信用集成电路设计 | 3.0 | 2 |
规格化平均成绩计算
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
average_degree
83.16666666666667