最近在家无聊,正好在网上看到一份不错的python教程,于是就学起了python。python是动态语言且具有函数式编程的特点,相比C/C++、java这类静态语言,有很多不同并且很有意思的地方。在学习到教程的常用内建模块xml部分时,老师留下一份作业:
练习一下解析Yahoo的XML格式的天气预报,获取当天和最近几天的天气:
http://weather.yahooapis.com/forecastrss?u=c&w=2151330
这不就是类似网络爬虫的意思吗,然后我就google it,发现很多网络爬虫的教程,都非常有意思,其中比较好的一个,也是我参考的一个:点这里。在里面初步学习了几篇教程后,就迫不及待上手试试,参考博主博文一个爬虫的诞生全过程(以山东大学绩点运算为例),自己做了一个农大的爬虫程序,并且计算出了自己的GPA,下面是我的代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import string
import urllib
import urllib2
import cookielib
import re
import time
class CAU_GPA_Spider:
#申明相关属性
def __init__(self):
self.loginUrl = 'http://urpjw.cau.edu.cn/loginAction.do'
self.resultUrl = 'http://urpjw.cau.edu.cn/gradeLnAllAction.do?type=ln&oper=sxinfo&lnsxdm=001'
self.cookieJar = cookielib.CookieJar()
self.postdata = urllib.urlencode({
'zjh':'1211250521',
'mm':'xxxxxxxx'
}) #密码我在这里就不写出来了,O(∩_∩)O哈哈~
self.GPA = None
self.subjects = [] # 储存科目
self.weights = [] # 储存学分
self.points = [] # 储存分数
self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookieJar))
def cau_init(self):
#初始化链接并获取cookie
myRequest = urllib2.Request(url = self.loginUrl, data = self.postdata) # 自定义请求
result = self.opener.open(myRequest) # 访问登录页面,获取必要cookie
result = self.opener.open(self.resultUrl) # 访问登录成绩页面,获取必要数据
self.deal_data(result.read())
# self.print_data(self.subjects)
# self.print_data(self.weights)
# self.print_data(self.points)
self.calculate_date()
def deal_data(self,myPage):
myItems = re.findall('.*?\s+(.*?)\s+ .*?.*?(\d\.\d|\d).*? .*?.*?(\d\d\.\d) .*? .*? ',myPage,re.S)
for item in myItems:
self.subjects.append(item[0])
self.weights.append(item[1])
self.points.append(item[2])
def print_data(self,items):
for item in items:
print item
def get_level(self, point):
point = string.atof(point)
if point >= 90 and point <= 100:
return 4.0
elif point >=85 and point <= 89:
return 3.7
elif point >=82 and point <= 84:
return 3.3
elif point >=78 and point <= 81:
return 3.0
elif point >=75 and point <= 77:
return 2.7
elif point >=72 and point <= 74:
return 2.3
elif point >=68 and point <= 71:
return 2.0
elif point >=64 and point <= 67:
return 1.5
elif point >=60 and point <= 63:
return 1.0
else:
return 0
def calculate_date(self):
points = 0.0
weights = 0.0
for i in range(len(self.points)):
pattern = re.compile('\d\d\.\d')
match = pattern.match(self.points[i])
if match:
points += self.get_level(self.points[i]) * string.atof(self.weights[i])
weights += string.atof(self.weights[i])
if weights != 0:
self.GPA = points/weights
start = time.time()
mySpider = CAU_GPA_Spider()
mySpider.cau_init()
end = time.time()
print 'your GPA:',mySpider.GPA
print 'run time:', end-start, 's'
其中网络爬虫程序中的数据抽取部分,用到了正则表达式,对参考资料中的
myItems = re.findall('.*?(.*?).*?(.*?).*? ',myPage,re.S) #获取到学分
根据从农大教务处网页爬下来的网页数据,对正则表达式进行修改,最开始是改为
myItems = re.findall('.*?.*?(\d\.\d|\d).*?.*?.*?(\d\d\.\d) .*?.*? ',myPage,re.S) #获取到学分
后来在运行时,光标一直闪烁,没有输出,我以为程序死循环了,后来一直查程序那里错了,结果在几分钟之后突然出数据了,统计一下程序运行时间:210秒+,这么慢的效率怎么能行。把网页数据保存为本地文件,然后单独写了一个.py文件,用正则表达式抽取数据,发现程序慢的原因是在网页数据的后半部分,也就是接近页脚那个地方,和正则表达式匹配度很高,估计程序就是卡在正则表达式在页脚那部分的计算了,唯一的办法只有修改正则表达式,根据网页源文件的内容进行分析,最后的正则表达式是:
myItems = re.findall('.*?\s+(.*?)\s+ .*?.*?(\d\.\d|\d).*? .*?.*?(\d\d\.\d) .*? .*? ',myPage,re.S) #获取到学分
这样修改之后,程序运行时间是run time: 0.768000125885s
正则表达式稍微知道一点,但是具体实现细节不太清楚,经过这次的爬虫程序,发现正则表达式的内容对数据抽取效率有很大影响,同样能抽取出数据的正则表达式,引起的效率可能是几千倍的差距。关键还是要好好分析要抽取出数据的源文件,找出要抽取部分和其他部分的区别,写出的正则表达式要尽量排除源文件中除要抽取数据之外的其它干扰部分。
另外,我的爬虫程序运行环境是python2.7.x,编辑器sublime,pycharm也是一个不错的编辑器,前几天刚下载但是还没有用习惯。sublime是用的比较多的一个编辑器,界面很漂亮。
参考资料
[1] Python教程 - 廖雪峰的官方网站(http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000)
[2] [Python]网络爬虫(十):一个爬虫的诞生全过程(以山东大学绩点运算为例) - 汪海的实验室 - 博客频道 - CSDN.NET (http://blog.csdn.net/pleasecallmewhy/article/details/9305229)
[3] [Python]网络爬虫(七):Python中的正则表达式教程 - 汪海的实验室 - 博客频道 - CSDN.NET
(http://blog.csdn.net/pleasecallmewhy/article/details/8929576)