在掌握了urllib几个模块的相关用法后,接下来就是进入实战步骤了~
(一)抓取豆瓣网站同城活动
豆瓣北京同城活动该链接指向豆瓣同城活动的列表,向该链接发起request:
# encoding=utf-8import urllibimport urllib2import cookielibimport recj=cookielib.CookieJar()opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))url="/events/future-all?start=0"req=urllib2.Request(url)event=urllib2.urlopen(req)str1=event.read()
我们会发现返回的html代码中,除了我们需要的信息之外,还夹杂了大量的页面布局代码:
如上图所示,我们只需要中间那些关于活动的信息。而为了提取信息,我们就需要正则表达式了~
正则表达式是一种跨平台的字符串处理工具/方法,通过正则表达式,我们可以比较轻松的提取字符串中我们想要的内容~
这里不做详细介绍了,个人推荐余晟老师的正则指引,挺适合新手入门的。下面给出正则表达式的大致语法:
这里我使用捕获分组,将活动四要素(名称,时间,地点,费用)为标准进行分组,得到的表达式如下:
regex=pile(r'summary">([\d\D]*?)</span>[\d\D]*?class="hidden-xs">([\d\D]*?)<time[\d\D]*?<li title="([\d\D]*?)">[\d\D]*?strong>([\d\D]*?)</strong>')
这样就可以将几个部分提取出来了。
总体代码如下:
# -*- coding: utf-8 -*- #--------------------------------------- # program:豆瓣同城爬虫 # author:GisLu# data:-02-08 #---------------------------------------import urllibimport urllib2import cookielibimport recj=cookielib.CookieJar()opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))#正则提取 def search(str1):regex=pile(r'summary">([\d\D]*?)</span>[\d\D]*?class="hidden-xs">([\d\D]*?)<time[\d\D]*?<li title="([\d\D]*?)">[\d\D]*?strong>([\d\D]*?)</strong>')for i in regex.finditer(str1):print "活动名称:",i.group(1)a=i.group(2)b=a.replace('</span>','')print b.replace('\n','')print '活动地点:',i.group(3)c=i.group(4).decode('utf-8')print '费用:',c#获取urlfor i in range(0,5):url="/events/future-all?start="url=url+str(i*10)req=urllib2.Request(url)event=urllib2.urlopen(req)str1=event.read()search(str1)
在这里需要注意一下编码的问题,因为我使用的版本还是python2.X,所以在内部汉字字符串传递的时候需要来回转换,比如在最后打印“费用“这一项的时候,必须使用
i.group(4).decode('utf-8') 将group(4元组中的ASCII码转换为utf8格式才行,否则会发现输出的是乱码。
而在python中,正则模块re提供了两种常用的全局查找方式:findall 和 finditer,其中findall是一次性处理完毕,比较消耗资源;而finditer则是迭代进行搜索,个人比较推荐使用这一方法。
最后得到的结果如下,大功告成~
(二)模拟登陆图书馆系统查询书籍归还情况
既然我们能够通过python向指定网站发出请求获取信息,那么自然也能通过python模拟浏览器进行登陆等操作~
而模拟的关键,就在于我们向指定网站服务器发送的信息需要和浏览器的格式一模一样才行~
这就需要分析出我们想要登陆的那个网站接受信息的方式。通常我们需要对浏览器的信息交换进行抓包~
抓包软件中,目前比较流行的是wireshark,相当强大~不过对于我们新手来说,IE、Foxfire或者chrome自带的工具就足够我们使用了~
这里就以本人学校的图书馆系统为例子~
我们可以通过模拟登陆,最后进入图书管理系统查询我们借阅的图书归还情况。首先要进行抓包分析我们需要发送哪些信息才能成功模拟浏览器进行登陆操作。
我使用的是chrome浏览器,在登陆页面按F12调出chrome自带的开发工具,选择network项就可以输入学号密码选择登陆了。
观察登陆过程中的网络活动,果然发现可疑分子了:
分析这个post指令后,可以确认其就是发送登陆信息(账号、密码等)的关键命令。
还好我们学校比较穷,网站做的一般,这个包完全没有加密~那么剩下的就很简单了~记下headers跟post data就OK了~
其中headers中有很多实用的信息,一些网站可能会根据user-Agent来判断你是否是爬虫程序从而决定是否允许你访问,而Referer则是很多网站常常用来反盗链的,如果服务器接收到的请求中referer与管理员设定的规则不符,那么服务器也会拒绝发送资源。
而post data就是我们在登录过程中浏览器向登陆服务器post的信息了,通常账户、密码之类的数据都包含在里面。这里往往还有一些其他的数据如布局等信息也要发送出去,这些信息通常我们在操作浏览器的时候没有任何存在感,但没了他们服务器是不会响应我们滴。
现在postdata 跟headers的格式我们全部知道了~模拟登陆就很简单了:
import urllib#--------------------------------------- # @program:图书借阅查询 # @author:GisLu# @data:-02-08 #---------------------------------------import urllib2import cookielibimport recj=cookielib.CookieJar()opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))opener.addheaders = [('User-agent','Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)')]urllib2.install_opener(opener)#登陆获取cookiespostdata=urllib.urlencode({'user':'X1234564','pw':'demacialalala','imageField.x':'0','imageField.y':'0'})rep=urllib2.Request(url='http://210.45.210.6/dzjs/login.asp',data=postdata)result=urllib2.urlopen(rep)print result.geturl()
其中urllib.urlencode负责将postdata自动进行格式转换,而opener.addheaders则是在我们的opener处理器中为后续请求添加我们预设的headers。
测试后发现,登陆成功~~
那么剩下的就是找出图书借还查询所在页面的url,再用正则表达式提取出我们需要的信息了~~
整体代码如下:
import urllib#--------------------------------------- # @program:图书借阅查询 # @author:GisLu# @data:-02-08 #---------------------------------------import urllib2import cookielibimport recj=cookielib.CookieJar()opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))opener.addheaders = [('User-agent','Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)')]urllib2.install_opener(opener)#登陆获取cookiespostdata=urllib.urlencode({'user':'X11134564','pw':'demacialalala','imageField.x':'0','imageField.y':'0'})rep=urllib2.Request(url='http://210.45.210.6/dzjs/login.asp',data=postdata)result=urllib2.urlopen(rep)print result.geturl()#获取账目表Postdata=urllib.urlencode({'nCxfs':'1','submit1':'检索'})aa=urllib2.Request(url='http://210.45.210.6/dzjs/jhcx.asp',data=Postdata)bb=urllib2.urlopen(aa)cc=bb.read()zhangmu=re.findall('tdborder4 >(.*?)</td>',cc)for i in zhangmu:i=i.decode('gb2312')i=i.encode('gb2312')print i.strip(' ')
下面是程序运行结果~