博客文章Xindog Web APP

南京航空航天大学研究生成绩爬虫程序

因为平时查成绩十分繁琐,要点击很多次,上学期也学了一点python,所以想着用个脚本比较快速的查成绩。

2017年5月29日 14:0528935 分钟
南京航空航天大学研究生成绩爬虫程序

因为平时查成绩十分繁琐,要点击很多次,上学期也学了一点python,所以想着用个脚本比较快速的查成绩。话不多说,正式开始。

1.首先打开南京航空航天大学研究生成绩管理的页面,没有验证码还是比较方便爬取的。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-1.jpg

首先按f12键打开开发工具,先看看form表单的结构,我们看到input标签下有一个hidden的隐藏域__VIEWSTATE。在后面的爬取中,我发现这个__VIEWSTATE会在一定时间内会发生变化,这个我们先不管,我们之后再来处理它。我们注意到action="login.aspx"

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-2.jpg

2.我们准备登陆,首先打开开发工具的Network,并勾选preserve log,记录我们登录过程中的页面加载过程中的请求和响应情况。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-3.jpg

3.现在万事具备,我们点击登录。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-4.jpg

我们点击login.aspx这个Name的请求。在当中记录了Request URL和Request Method,以及Form Data中的隐藏域__VIEWSTATE

继续下拉,我们看到Form Data中的_ctl0:txtusername,这就是我们登录时所填写的用户名,以及_ctl0:txtpassword这是我们的密码。除此之外,_ctl0:ImageButton1.x_ctl0:ImageButton1.y这两个也是Form Data所需要向服务器POST的数据。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-5.jpg

4.接下来就是找到查询成绩的页面。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-6.jpg

在学生成绩查询上我们右键”审查元素”,发现是指向一个 http://gsmis.nuaa.edu.cn:81/nuaapyxx/grgl/xskccjcx.aspx 的链接,而且是以Frame的形式打开。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-7.jpg

5.接下来就是使用正则表达式或者Python中一个著名的beautifulSoup的页面解析库,这里我也正是采用了beautifulSoup进行页面的解析。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-8.jpg

6.通过”审查元素”,我们看到课程名和成绩是在属性为nowrap="nowrap"的表格里,但是其他的学位课程等其他无用的标签也包含属性nowrap="nowrap",所以我们要去掉。(要去掉的元素同时还包含属性'bgcolor': '#C8E1FB',所以还是比较容易除去的)。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-9.jpg

7.接下来就是代码了,其实功能也很简单,加上注释不到60行就搞定了。想查成绩的时候,轻轻点击一下运行,成绩文件自动建立就OK了。

	https://ixingo-1251718187.cos.ap-nanjing.myqcloud.com/images/web/blog/nuaa-10.jpg

源代码为:

1# -*- coding: utf-8 -*-
2import urllib
3import urllib2
4import cookielib
5import os
6from bs4 import BeautifulSoup
7import sys;
8reload(sys);
9sys.setdefaultencoding("utf8")
10
11#声明一个CookieJar对象实例来保存cookie
12cookie = cookielib.CookieJar()
13
14#利用urllib2库的HTTPCookieProcessor对象来创建cookie处理器
15handler=urllib2.HTTPCookieProcessor(cookie)
16
17#通过handler来构建opener
18opener = urllib2.build_opener(handler)
19
20# 登录教务系统的URL
21loginUrl = 'http://gsmis.nuaa.edu.cn/nuaapyxx/login.aspx'
22
23# 请求头文件
24headers = {
25    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0',
26}
27req = urllib2.Request(url=loginUrl,  headers=headers)
28
29# 为了获得隐藏域__VIEWSTATE,先打开一次页面获得viewstate,再进行登录
30opener.open(req)
31
32result = opener.open(req)
33content = result.read().decode('utf-8')
34soup = BeautifulSoup(content, "lxml")
35for tabb in soup.find_all(name='input', attrs={'name':'__VIEWSTATE'}):
36    viewstate = tabb.attrs['value']
37postdata = urllib.urlencode({
38    '__VIEWSTATE': viewstate,
39
40    # 此处为用户名/学号
41    '_ctl0:txtusername': '######',
42
43    '_ctl0:ImageButton1.x': '30',
44    '_ctl0:ImageButton1.y': '26',
45
46    # 此处为用户密码
47    '_ctl0:txtpassword': '######'
48})
49req = urllib2.Request(url=loginUrl, data=postdata, headers=headers)
50opener.open(req)
51gradeUrl = 'http://gsmis.nuaa.edu.cn:81/nuaapyxx/grgl/xskccjcx.aspx'
52req = urllib2.Request(url=gradeUrl, headers=headers)
53result = opener.open(req)
54content = result.read().decode('utf-8')
55soup = BeautifulSoup(content, "lxml")
56count = 0
57filename = u"成绩"
58path = filename + ".txt"
59[s.extract() for s in soup(name='tr', attrs={'bgcolor': '#C8E1FB'})]
60for tabb in soup.find_all(name='tr', attrs={'nowrap':'nowrap'}):
61    for tdd in tabb.find_all(name='font', attrs={'size':'2'}):
62        count += 1
63        if (count % 5 == 1):
64            with open(path, "a") as fp:
65                fp.write("课程:“%s”," % tdd.get_text())
66        if (count % 5 == 4):
67            with open(path, "a") as fp:
68                fp.write("成绩:%s;\n" % tdd.get_text())