爬虫经典练手项目——HFUT GPA计算器

来源:互联网 发布:淘宝网天猫购裱画材料 编辑:程序博客网 时间:2024/05/24 04:46

前言

之前搭建完Python的环境之后就一直没有时间真正静下来写一个完整的爬虫应用程序,这几天实习的日子开始填坑,Python爬虫最经典的也比较有意义的就是GPA计算器了,它模拟了登录捕获教务系统中成绩的过程,并且程序逻辑较为简单,实现起来较快。为了较好的体验和测试效果,我用PyQt写了小的界面。

目标

实现一个GPA计算器,输入用户名和密码,计算该学生的GPA并返回。

实现步骤

  1. 明确登录的过程,获取HTTP报文查看具体的字段。
  2. 接收用户的输入,输入用户名和密码进行模拟登录。
  3. 使用正则表达式匹配相应的字段进行过滤。
  4. 根据伟大的学校章程规定进行GPA计算并且返回。
  5. 完善彩蛋2333
    本次实现采用Python的内置函数库进行实现。

核心设计

首先需要实现模拟登录,使用Chrome Developer Tools监视我们登录的情况,发现两点:第一点是实际上我们的用户名和密码是POST进行传输的(GET方式的参数会放在URL中,这样是灰常危险的),其次是我们POST参数的地址是pass.asp而不是我们看到的页面地址,这个页面是一个密码验证页面,它的BODY是空的,你看不到任何的内容。
实际的POST地址

然后我们需要进行模拟登录,为了保存登录信息,我们需要使用Cookie,这个过程的套路相对比较固定,为了尽量安全,我们构造Headers,整体的流程代码如下所示:

    cookie=cookielib.MozillaCookieJar(self.filename)    handler=urllib2.HTTPCookieProcessor(cookie)    opener=urllib2.build_opener(handler)    values={'UserStyle':'student',            'user':self.username,               'password':self.password}    data=urllib.urlencode(values)   #对于post数据进行编码    opener.open(self.login_url,data) #模拟登录    cookie.save(self.filename, ignore_discard=True, ignore_expires=True)    response=opener.open(self.grade_url)    html=response.read().decode("gb2312")  #统一强制转换为Unicode

然后进入成绩页面进行分析,分析过程类似,页面情况如下图所示:
成绩页面

网站使用的是frame,我们分析其中的内容,可以构造正则表达式进行内容的匹配,关于正则表达式可以参考这篇文章,目前常用的匹配是.*?,这个可以匹配任意多个字符,不贪婪方式进行匹配,值得注意的是匹配过程中我们最好将边界明确化,这样可以增加匹配的准确度。构造匹配串的代码如下所示:

    #构建匹配字符串    name_str='<tr.*?bgcolor=.*?>.*?<td>(.*?)</td>.*?<td.*?align.*?>(.*?)</td>.*?<td>(.*?)</td>'    grade_str='.*?<td.*?align.*?>.*?</td>.*?<td.*?align.*?>(.*?)</td>'    score_str='.*?<td.*?align.*?>.*?</td>.*?<td>(.*?)</td>'    special_pattern=re.compile('<.*?>')    #进行匹配    pattern_str=name_str+grade_str+score_str    pattern=re.compile(pattern_str,re.S|re.I)    items=re.findall(pattern,html)    if items:        for item in items:        newitem=re.sub(special_pattern,'',item[3]) #特殊成绩的格式过滤        isenglish=item[2].find(u'英语')        self.gradeList.append([item[0],item[1],item[2],newitem,item[4],isenglish])         #print item[0].strip(),' ',item[1].strip(),'   ',item[2].strip(),'   ',item[3].strip(),' ',item[4].strip() #for debug                return True            else:                return None

如上代码所示,匹配完成之后我们需要提取所需要的各种信息,我们将每个信息的字段进行存储,这里比较合适的就是List存储一门课的信息(包括课程代码、课程的时间、课程名、成绩以及学分)。然后我们根据学校的具体规定进行计算,具体代码在后面的开源链接中给出。

界面设计

既然打算搭建界面,就需要界面库进行支持,这里我使用的界面库是PyQt,语言自带的界面貌似都是非常惊险的,Python的界面也是非常不可描述的(233)。\
我自己写的界面都可以称为SHIT1.0(233)。
SHIT1.0

彩蛋

用户名和密码这么好的东西……如果能获取并且默默的发邮件的话……
彩蛋

TODO

  1. 界面可以进行完善,菜单栏的功能补全,尝试写一个控制语言的配置文件,尝试写帮助文档CHW。
  2. Py打包成EXE。
  3. 增加可扩展性,了解教务API。
  4. 熟悉SMTP。

后记

一般写这种练手项目的总结,注重实现的整体顺序和逻辑,还有一些实现的难点,具体的技术细节会在技术细节流水账中记录。

0 0