Python 爬取学校课程表和成绩
2017-08-12 21:43
330 查看
本文仅用于学习交流爬虫技术,不用于商业,转载请说明出处!
最近在自学 Python 网络爬虫,想实际练练手,于是选择了学校的教务管理系统,获取课表、成绩、排名和绩点。
我用的 Python 版本是 3.6,全部使用标准库,用到的库如下:
获取的是 HTML,可以用正则表达式或者 BeautifulSoup 来解析。
![](https://img-blog.csdn.net/20170812224458471?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2JzcnY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
切换到“参数”标签,可以看到 POST 的参数:
![](https://img-blog.csdn.net/20170812224623486?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2JzcnY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
显然,表单数据中,
有了请求头和参数,我们就可以用 Python 发送一个 POST 请求,得到教务系统首页的 HTML 源码。但是因为浏览成绩、课表是要保持登录状态,因此需要处理 cookie,可以用
接下来,进入“成绩查询”页面。右击链接,选择“查看元素”,可以看到成绩查询页面的 URL:
![](https://img-blog.csdn.net/20170812225730564?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2JzcnY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
于是,通过这个 URL 进入成绩查询首页,并获取 HTML 源码:
点击左侧功能模块中的“成绩查询”,显示成绩表,可以看到发送了一个 GET 请求:
![](https://img-blog.csdn.net/20170812230748997?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2JzcnY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
请求的参数有两个,一个是
得到了这两个参数的值之后,就可以发送 GET 请求了,获得的恰好是成绩页面的 HTML:
![](https://img-blog.csdn.net/20170812232617251?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2JzcnY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
注:省略
武汉理工大学教务系统默认显示最近的 20 条记录,但是这个值可以修改,通过 Firefox 可以发现,发送一个 POST 请求即可。参数如下:
获取排名和绩点也很简单,通过 Firefox 网络监视器可以看到请求的地址和参数。
最近在自学 Python 网络爬虫,想实际练练手,于是选择了学校的教务管理系统,获取课表、成绩、排名和绩点。
我用的 Python 版本是 3.6,全部使用标准库,用到的库如下:
urllib.request
urllib.parse
http.cookiejar
time
re
urllib.request和
urllib.parse用来发送网络请求,
http.cookiejar用来保存 cookie,
time用来生成 Unix 时间戳,
re通过正则表达式从网页中获取网络请求需要的一个参数。
代码
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import urllib.request import urllib.parse import http.cookiejar import time import re url = "http://sso.jwc.whut.edu.cn/Certification//login.do" user = input("Username: ") password = input("Password: ") # 表单参数 params = { 'systemId': '', 'xmlmsg': '', 'userName': user, 'password': password, 'type': 'xs', 'imageField.x': '60', 'imageField.y': '19' } # 处理 Cookie cookie = http.cookiejar.CookieJar() opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie)) opener.addheaders = [ ('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'), ('Host', 'sso.jwc.whut.edu.cn'), ('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'), ('Referer', 'http://sso.jwc.whut.edu.cn/Certification/toLogin.do'), ('Connection', 'keep=alive') ] data = urllib.parse.urlencode(params).encode() # 打开教务处首页 response_index = opener.open(url, data) # 打开成绩首页 response_score_index = 4000 opener.open("http://202.114.90.180/Score/") text_score_index = response_score_index.read().decode() # 正则表达式从成绩首页的 HTML 中获取 snkey 字段 # (这个字段很重要,如果省略掉会提示非法查询) snkey = re.findall(r'snkey=([0-9a-z]{8}-(?:[0-9a-z]{4}-){3}[0-9a-z]{12})', text_score_index, re.I)[0] # 打开历史成绩页面 response_score_history = opener.open("http://202.114.90.180/Score/lscjList.do?snkey={snkey}&_={ts}" .format(snkey=snkey, ts=int(round(time.time() * 1000)))) # 显示 200 条记录 params_score = { 'pageNum': '1', # 当前页码 'numPerPage': '200', # 每页显示记录条数 'xh': user, # 学号 'xn': '', # 学年 'xnxq': '', # 学年学期 'nj': '', 'xydm': '', 'zydm': '', 'bjmc': '', 'kcmc': '', 'kcdm': '', 'xslb': '', 'kcxz': '', 'jsxm': '', 'snkey': snkey } show_200 = opener.open("http://202.114.90.180/Score/lscjList.do", urllib.parse.urlencode(params_score).encode()) show_200_html = show_200.read().decode() print(show_200_html) # 学分、绩点、排名 credit_and_gpa = opener.open("http://202.114.90.180/Score/xftjList.do?_={ts}" .format(ts=int(round(time.time() * 1000)))) print(credit_and_gpa.read().decode())
获取的是 HTML,可以用正则表达式或者 BeautifulSoup 来解析。
分析思路
使用 Firefox 浏览器进入教务系统首页,按Ctrl + Shift + Q打开网络监视器(也可以按
F12然后选择“网络”),输入用户名和密码登录,可以捕获到登录的 POST 请求:
切换到“参数”标签,可以看到 POST 的参数:
显然,表单数据中,
userName为用户名,而
password为密码。
有了请求头和参数,我们就可以用 Python 发送一个 POST 请求,得到教务系统首页的 HTML 源码。但是因为浏览成绩、课表是要保持登录状态,因此需要处理 cookie,可以用
http.cookiejar模块。
cookie = http.cookiejar.CookieJar() opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie))
接下来,进入“成绩查询”页面。右击链接,选择“查看元素”,可以看到成绩查询页面的 URL:
于是,通过这个 URL 进入成绩查询首页,并获取 HTML 源码:
response_score_index = opener.open("http://202.114.90.180/Score/") text_score_index = response_score_index.read().decode()
点击左侧功能模块中的“成绩查询”,显示成绩表,可以看到发送了一个 GET 请求:
请求的参数有两个,一个是
snkey,8-4-4-4-12 格式的 GUID;还有一个是
_,13 位 Unix 时间戳。
snkey字段在成绩查询首页的 HTML 中可以提取,使用正则表达式即可:
snkey = re.findall(r'snkey=([0-9a-z]{8}-(?:[0-9a-z]{4}-){3}[0-9a-z]{12})', text_score_index, re.I)[0]
_字段可以使用 Python 的
time模块获取当前时间戳。由于
time.time()默认获取的是个浮点数,要想取得 13 位时间戳,需要做如下计算:
ts = int(round(time.time() * 1000))
得到了这两个参数的值之后,就可以发送 GET 请求了,获得的恰好是成绩页面的 HTML:
注:省略
_参数仍然可以获取数据,但是省略
snkey参数会提示“非法查询”。
武汉理工大学教务系统默认显示最近的 20 条记录,但是这个值可以修改,通过 Firefox 可以发现,发送一个 POST 请求即可。参数如下:
params_score = { 'pageNum': '1', # 当前页码 'numPerPage': '200', # 每页显示记录条数 'xh': user, # 学号 'xn': '', # 学年 'xnxq': '', # 学年学期 'nj': '', 'xydm': '', 'zydm': '', 'bjmc': '', 'kcmc': '', 'kcdm': '', 'xslb': '', 'kcxz': '', 'jsxm': '', 'snkey': snkey # 这个 snkey 就是之前从 HTML 中抓取的 snkey }
获取排名和绩点也很简单,通过 Firefox 网络监视器可以看到请求的地址和参数。
相关文章推荐
- python3+BeautifulSoup+tkinter 爬虫 获取学校成绩
- Python项目模拟登录学校正方教务系统抓取课程表。
- Python3 学校成绩更新实时通知
- python3模拟登录我们学校的官网爬去本学期的成绩
- python 爬虫实战--登陆学校教务系统获取成绩信息
- python小爬虫—获取学校教务处成绩
- (python3)1038.统计同成绩学生(20分)
- SQL语句多表查询(学生表/课程表/教师表/成绩表 ){转载}
- python 爬虫登陆学校教务系统
- 新手详细教程:python3基于SVM识别学校登录页面验证码
- Python 自动分类学生成绩
- (python3)1080. MOOC期终成绩 (19分)——2017-12考题
- 学生表 课程表 成绩表 教师表 50个常用sql语句
- sql语句多表查询(学生表/课程表/教师表/成绩表 )
- 学生表 课程表 成绩表 教师表 50个常用sql语句
- 1004. 成绩排名 python
- Problem #3288 成绩计算(python实现)
- 用Python做有趣的事儿——模拟登陆学校教务系统
- 学生表 课程表 成绩表 教师表 50个常用sql语句
- Python爬取成绩