【Python爬虫】爬取成绩计算绩点
昨天太忙了,就没写这篇博客,今天补上。
1.地址分析
在登陆页面打开开发者工具栏(要启用持续日志),随便输入点登陆,可以看到采用的是POST的方式提交的参数,有两个隐藏参数,并且用户名密码没有加密。记下提交地址http://jwgl.ntu.edu.cn/cjcx/Default.aspx
和两个隐藏参数的值
"__VIEWSTATE":"/wEPDwUJODExMDE5NzY5ZGRgtUdRucUbXsT8g55XmVsTwV6PMw==",
"__VIEWSTATEGENERATOR":"6C0FF253",
还有一个地址是获取验证码的记下地址:http://jwgl.ntu.edu.cn/cjcx/checkImage.aspx
我用自己的账号登进去,点击全部成绩,可以看到又有一个POST请求,两个参数简单猜一下应该是起始课程号和结束课程号。记下POST的地址:http://jwgl.ntu.edu.cn/cjcx/Data/ScoreAllData.aspx
2.验证码问题
请求一次验证码就会得到一个SessionId,请求Default.aspx却没有
所以自己定义一个带cookie的opener,先用它请求验证码,并把验证码保存到本地,然后人工识别输入后,在向Default.aspx发送请求。
cj=cookielib.CookieJar()
headler=urllib2.HTTPCookieProcessor(cj)
opener=urllib2.build_opener(headler)
yzm=opener.open(url1)
yzmgif=open("yzm.gif","w")
yzmgif.write(yzm.read())
yzmgif.close()
print u"验证码已保存在本文件目录下(yzm.gif),请查看并输入!"
yzmstr=raw_input()
3.数据分析观察请求全部成绩响应的数据,开以看出没门课程是以键值对的形式返回来的,
那么用一下正则表达式来匹配
restr='"kcmc":"(.*?)","jsxm":"(.*?)","xq":"(.*?)","xs":"(.*?)","xf":"(.*?)","zpcj":"(.*?)","pscj":"(.*?)","qmcj":"(.*?)","kcsx":"(.*?)","cjid":"(.*?)","ksfsm":"(.*?)","pxcj":"(.*?)"}'
pattern=re.compile(restr)
items=re.findall(pattern,scorestr)
4.绩点计算方法(不一定对)
1考核成绩与绩点关系: 五级记分 绩点 百分记分 绩点 优秀 4.5 90~100 4.0~5.0 良好 3.5 80~89 3.0~3.9 中等 2.5 70~79 2.0~2.9 及格 1.5 60~69 1.0~1.9 不及格 0 <60 0 2.学分绩点、平均学分绩点的计算。 课程学分绩点=课程学分×考核成绩绩点 平均学分绩点=Σ所修课程学分绩点/Σ所修课程学分
5.运行结果
6.完整代码(刚学Python,代码风格神乱并且完全没有做容错处理,大神勿笑)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib2
import urllib
import cookielib
import re
def getjd(item):
if item[5]=="优":
return 4.5*float(item[4])
if item[5]=="良":
return 3.5*float(item[4])
if item[5]=="中":
return 2.5*float(item[4])
if item[5]=="及格":
return 1.5*float(item[4])
if item[5]=="不及格":
return 0.0
if int(item[5])>=90 and int(item[5])<=100:
return ((float(item[5])-90)/10+4.0)*float(item[4])
if int(item[5])>=80 and int(item[5])<=89:
return ((float(item[5])-80)/10+3.0)*float(item[4])
if int(item[5])>=70 and int(item[5])<=79:
return ((float(item[5])-70)/10+2.0)*float(item[4])
if int(item[5])>=60 and int(item[5])<=69:
return ((float(item[5])-60)/10+1.0)*float(item[4])
if int(item[5])<=59:
return 0.0
cj=cookielib.CookieJar()
headler=urllib2.HTTPCookieProcessor(cj)
opener=urllib2.build_opener(headler)
url="http://jwgl.ntu.edu.cn/cjcx/Default.aspx" #登录页面
url1="http://jwgl.ntu.edu.cn/cjcx/checkImage.aspx" #验证码页面
scoreurl="http://jwgl.ntu.edu.cn/cjcx/Data/ScoreAllData.aspx"#获取分数
#输入数据
print u"××××××××××××××××××××南通大学教务系统登陆××××××××××××××××××××"
print u"输入学号!"
xh=raw_input()
print u"输入身份证号!"
sfzh=raw_input()
print u"密码!"
kl=raw_input()
yzm=opener.open(url1)
yzmgif=open("yzm.gif","w") #保存验证码
yzmgif.write(yzm.read())
yzmgif.close()
print u"验证码已保存在本文件目录下(yzm.gif),请查看并输入!"
yzmstr=raw_input()
#数据保存
jilu=open(xh+".txt","w")
jilu.write("学号:"+xh+"\n身份证号:"+sfzh+"\n密码:"+kl)
jilu.close()
values={"__VIEWSTATE":"/wEPDwUJODExMDE5NzY5ZGRgtUdRucUbXsT8g55XmVsTwV6PMw==",
"__VIEWSTATEGENERATOR":"6C0FF253",
"xh":xh,
"sfzh":sfzh,
"kl":kl,
"yzm":yzmstr}
scoreValues={"start":"0",
"pageSize":"80"}
request=urllib2.Request(url,urllib.urlencode(values))
scoreRequest=urllib2.Request(scoreurl,urllib.urlencode(scoreValues))
f=opener.open(request) #请求登陆页面
score=opener.open(scoreRequest) #登陆成功的话就可以得到全部成绩
scorestr=score.read()
#正则表达式
restr='"kcmc":"(.*?)","jsxm":"(.*?)","xq":"(.*?)","xs":"(.*?)","xf":"(.*?)","zpcj":"(.*?)","pscj":"(.*?)","qmcj":"(.*?)","kcsx":"(.*?)","cjid":"(.*?)","ksfsm":"(.*?)","pxcj":"(.*?)"}'
pattern=re.compile(restr)
items=re.findall(pattern,scorestr) #匹配元素
jd=0.0 #总绩点
xf=0.0 #总学分
for item in items:
print item[0],item[1],item[2],item[3],item[4],item[5],item[6],item[7],item[8],item[9],item[10],item[11]
if repr(getjd(item))!="None":
jd=jd+float(repr(getjd(item)))
xf=xf+float(item[4])
print u"该课程学分绩点为:"+repr(getjd(item))
print u"所修课程学分绩点为:"+repr(jd)
print u"所修课程学分为 :"+repr(xf)
print u"平均学分绩点为 :"+repr(jd/xf)
print cj #SessionId