python|python 爬虫实战--登陆学校教务系统获取成绩信息
1. 前言 之前写的爬虫都是不需要使用cookie的, 这次我们瞄上了学校的教务系统, 每次登陆都那么几个步骤好费劲啊, 写个爬虫直接获取成绩多好啊~~
2. 项目分析 首先, 我们的目标页面是: http://yjs.ustc.edu.cn/
文章图片
查看网页源码
文章图片
我们发现我们框选出来的地址就是我们验证码的地址:
http://yjs.ustc.edu.cn/checkcode.asp
利用chrome 自带的抓包功能, 我们模拟登陆
先输入账号, 密码, 以及验证码,点击登陆
文章图片
我们发现, 302 是临时重定向, 也就是说登陆成功之后, 转向我们最终页面, 但是我们实际的账号, 密码, 验证码信息都是发向这个地址的
http://yjs.ustc.edu.cn/default.asp
然后, 我们找到我们成绩查询的页面
文章图片
http://yjs.ustc.edu.cn/score/m_score.asp
文章图片
上图是成绩页面的源码, 很容易可以分析得到正则表达式为
string = r'.*? .*?.*?(.*?) (.*?) (.*?) .*?.*?.*?.*?'
至此, 几个关键的连接地址都被我们找到了
3. 验证码处理思路 【python|python 爬虫实战--登陆学校教务系统获取成绩信息】对于验证码的处理, 主要有3种思路,
1. 把学校网站上的验证码全部down下来, 做成一个数据库, 直接查询即可
2. 使用ocr识别
3. 人工识别
我们这里为了简单起见, 采用人工识别的方法, 先将网页中的验证码down下来, 然后手工识别他
4. 其他 这个项目还有几个点需要注意:
1. python 伪装成浏览器进行登录, 设置 headers
2. cookie 连接
5. 运行效果图
文章图片
6. code
# -*- coding:utf-8 -*-
'''
Created on 2016-5-2
获取教务系统 信息
@author: ThinkPad User
'''import sys
reload(sys)
sys.setdefaultencoding('utf8') import urllib
import urllib2
import re
import cookielib
import sys
import os
import stringclass YJSSpider:
# 模拟登陆研究生教务系统
def __init__(self):
self.baseURL = ""
self.enable = True
self.charaterset = "gb2312"
string = "Mozilla/5.0 (Windows NT 6.1;
Win64;
x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2438.3 Safari/537.36"
self.headers = {'User-Agent' : string}
self.cookie = cookielib.CookieJar()
self.hander = urllib2.HTTPCookieProcessor(self.cookie)
self.opener = urllib2.build_opener(self.hander)# 验证码处理
def getCheckCode(self):
# 验证码连接
checkcode_url = "http://yjs.ustc.edu.cn/checkcode.asp"
request = urllib2.Request(checkcode_url, headers=self.headers)
picture = self.opener.open(request).read()
# 将验证码写入本地
local = open("checkcode.jpg", "wb")
local.write(picture)
local.close()
# 调用系统默认的图片查看程序查看图片
os.system("checkcode.jpg")
# 手工识别验证码
txt_check = raw_input(str("请输入验证码").encode(self.charaterset))
return txt_check# 模拟登陆
def login(self, userid, userpwd):
# 获取验证码
txt_check = self.getCheckCode()
postData = https://www.it610.com/article/{"userid":userid, "userpwd":userpwd, "txt_check":txt_check}
data = https://www.it610.com/article/urllib.urlencode(postData)request_url ="http://yjs.ustc.edu.cn/default.asp"
request_new = urllib2.Request(request_url, headers=self.headers)
response = self.opener.open(request_new, data)# 抓取网页
def getHtml(self, url):
try:
request_score = urllib2.Request(url, headers=self.headers)
response_score = self.opener.open(request_score)
return response_score.read().decode("gb2312", 'ignore').encode("utf8")
except urllib2.URLError, e:
if hasattr(e, "reason"):
string = "连接bbs 失败, 原因" +str(e.reason)
print string.encode(self.charaterset)
return None# 获取成绩信息
def getScore(self):
# get score
score_url = "http://yjs.ustc.edu.cn/score/m_score.asp"
content = self.getHtml(score_url)
if not content:
print "获取成绩失败"
returnstring = r'.*? .*?.*?(.*?) (.*?) (.*?) .*?.*?.*?.*?'
pattern = re.compile(string, re.S)
res = re.findall(pattern, content)
class_name = []
class_grade = []
class_credit = []
for item in res:
class_name.append(item[0])
class_grade.append(item[1])
class_credit.append(item[2])
#record = unicode("课程名称:%40s\t成绩:%5s\t学分:%5s" % (item[0].strip(), item[1].strip(), item[2].strip()), "utf8")
#print item[0].encode("utf8"), item[1], item[2]
#print record
return [class_name, class_grade, class_credit]# 科大的gpa 转化公式, 不全, 我们只写了自己成绩中对应的部分
def convert2GPA(self, grade):
if grade == "通过":
return None
if grade == "A-":
return 3.7try:
grade_int = int(grade)
if grade_int >= 95:
return 4.3
if grade_int >= 90:
return 4.0
if grade_int >= 85:
return 3.7
if grade_int >= 82:
return 3.4
if grade_int >= 78:
return 3.1
return None
except:
return None# 成绩显示
def display(self):
result = self.getScore()
name = result[0]
grade = result[1]
credit = result[2]
sum = 0
count = 0
for i in range(len(name)):
record = unicode("课程名称:%40s\t成绩:%5s\t学分:%5s" % (name[i], grade[i], credit[i]), "utf8")
print record.encode(self.charaterset)
gpa = self.convert2GPA(grade[i])
if not gpa:
continue
sum += gpa * string.atof(credit[i])
count += string.atof(credit[i])
avg = sum / count
print str("avg gpa : %f" % avg).encode(self.charaterset)if "__main__" == __name__:
userid = "SA14009048"
# 这里改成自己的账号和密码信息
userpwd = "xxxxxx"
yjs = YJSSpider()
yjs.login(userid, userpwd)
yjs.display()
os.system("pause")
推荐阅读
- python学习之|python学习之 实现QQ自动发送消息
- 逻辑回归的理解与python示例
- python自定义封装带颜色的logging模块
- 【Leetcode/Python】001-Two|【Leetcode/Python】001-Two Sum
- Python基础|Python基础 - 练习1
- Python爬虫|Python爬虫 --- 1.4 正则表达式(re库)
- Python(pathlib模块)
- python青少年编程比赛_第十一届蓝桥杯大赛青少年创意编程组比赛细则
- Python数据分析(一)(Matplotlib使用)
- 爬虫数据处理HTML转义字符