导读:本文主要分为两部分:一部分是网络爬虫您详细了解网络爬虫;另一部分是HTTP请求的Python实现,帮助大家理解Python中实现HTTP各种方式的请求,以便有编写HTTP网络程序的能力。
作者:范传辉
如需转载,请联系华章科技
01 网络爬虫概述接下来,从网络爬虫的概念、用途、价值和结构三个方面,让大家对网络爬虫有一个基本的了解。
1. 网络爬虫及其应用
随着网络的快速发展,万维网络已经成为大量信息的载体。如何有效地提取和利用这些信息已经成为一个巨大的挑战。网络爬虫(又称网页蜘蛛、网络机器人)是一种按照一定规则自动捕获万维网络信息的程序或脚本。下图3-1显示网络爬虫在互联网中的作用:
▲图3-1 网络爬虫
根据系统结构和实现技术,网络爬虫大致可分为以下类型:通用网络爬虫、聚焦网络爬虫、增量网络爬虫、深层网络爬虫。实际的网络爬虫系统通常是几种爬虫技术的结合。
搜索引擎(Search Engine),例如,传统的通用搜索引擎baidu、Yahoo和Google等,是一种大型复杂的网络爬虫,属于通用网络爬虫的范畴。但是通用搜索引擎有一定的局限性:
不同领域和背景的用户往往有不同的搜索目的和需求。通用搜索引擎返回的结果包括大量用户不关心的网页。一般搜索引擎的目标是尽可能大的网络覆盖率,有限的搜索引擎服务器资源与无限的网络数据资源之间的矛盾将进一步加深。随着万维网络数据形式的丰富和网络技术的不断发展,出现了大量不同的数据,如图片、数据库、音频和视频多媒体。通用搜索引擎往往无法找到和获取这些信息内容密集、结构一定的数据。大多数通用搜索引擎提供基于关键字的搜索,很难支持基于语义信息的查询。为了解决上述问题,聚焦爬虫应运而生。
聚焦爬虫是一个自动下载网页的程序。根据既定的抓取目标,有选择地访问万维在线网页和相关链接,获取所需信息。与普通爬虫不同,聚焦爬虫并不追求大覆盖,而是将目标定为捕获与特定主题内容相关的网页,为主题用户查询准备数据资源。
聚焦爬虫之后,我们来谈谈增量网络爬虫。增量网络爬虫是指下载载的网页进行增量更新,只爬行新产生或改变网页的爬虫。它可以在一定程度上确保爬行的页面是尽可能多的新页面。
与定期爬行和刷新页面的网络爬虫相比,增量爬虫只会在需要时爬行新生成或更新的页面,不会重新下载无变化的页面,可以有效减少数据下载,及时更新爬行页面,减少时间和空间成本,但增加爬行算法的复杂性和难度。
例如,为了获取市场网络的招聘信息,没有必要重复以前爬过的数据,只需要获取更新的招聘数据,此时使用增量爬虫。
最后说说深网爬虫。Web页面可分为表面网页和深层网页。表面网页是指传统搜索引擎可以索引的页面,主要由超链接可以到达的静态网页组成Web页面。深度网络是那些只有用户提交一些关键词才能获得的,大部分内容不能通过静态链接获得,隐藏在搜索表单后面。Web页面。
例如,只有用户登录或注册才能访问的页面。可以想象,爬贴吧或论坛中的数据必须在用户登录并有权限的情况下才能获得完整的数据。
2. 网络爬虫结构
以下是网络爬虫的基本工作流程,如图3-4所示。
▲图3-4 网络爬虫结构
网络爬虫的基本工作流程如下:
首先,选择一些精心挑选的种子URL。将这些URL放入待抓取URL队列。从待抓取URL在队列中读取要抓取的队列URL,解析DNS,并获得主机IP,并将URL下载相应的网页并存储在已下载的网页库中。另外,这些URL放进已抓取URL队列。分析已抓取URL队列中的URL,从已下载的网页数据中分析其他数据URL,并且已经取的URL比较去重,最后重复URL放入待抓取URL从而进入下一个循环。02 HTTP请求的Python实现通过以上网络爬虫结构,我们可以看到读取URL、下载网页是每个爬虫的必要和关键功能,需要和解HTTP请求打交道。接下来讲解Python中实现HTTP请求的三种方式:urllib2/urllib、httplib/urllib以及Requests。
1. urllib2/urllib实现
urllib2和urllib是Python要实现两个内置模块HTTP实现功能的方法是urllib2为主,urllib为辅。
1.1 首先实现完整的请求和响应模型
urllib提供基本函数urlopen,通过指定URL发出获取数据的请求。最简单的形式是:
import urllib2response=urllib2.urlopen('http://www.zhihu.com')html=response.read()print html
其实可以面对http://www.zhihu.com请求响应分为两步,一步是要求,一步是响应,形式如下:
import urllib2# 请求request=urllib2.Request('http://www.zhihu.com')# 响应response = urllib2.urlopen(request)html=response.read()print html
以上两种形式都是GET请求,接下来演示一下POST事实上,请求是相似的,只是增加了请求数据,此时使用urllib。示例如下:
import urllibimport urllib2url = 'http://www.xxxxxx.com/login'postdata ={'username' : 'qiye', 'password' : 'qiye_pass'}# info 需要编码为urllib2可以理解的格式在这里使用urllibdata = urllib.urlencode(postdata)req = urllib2.Request(url, data)response = urllib2.urlopen(req)html = response.read()
但有时会发生这种情况:即使是:POST请求的数据是正确的,但服务器拒绝您的访问。为什么?为什么?问题在于请求中的头部信息。服务器将检查请求头以判断它是否来自浏览器访问,这也是反爬虫的常用手段。
1.2 请求头headers处理
重写上述例子,添加请求头信息,并在请求头中设置User-Agent域和Referer域信息。
import urllibimport urllib2url = 'http://www.xxxxxx.com/login'user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'referer='http://www.xxxxxx.com/'postdata ={'username' : 'qiye', 'password' : 'qiye_pass'}# 将user_agent,referer写入头信息headers={'User-Agent':user_agent,'Referer':referer}data = urllib.urlencode(postdata)req = urllib2.Request(url, data,headers)response = urllib2.urlopen(req)html = response.read()
也可以这样写,用add_header添加请求头信息,修改如下:
import urllibimport urllib2url = 'http://www.xxxxxx.com/login'user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'referer='http://www.xxxxxx.com/'postdata ={'username' : 'qiye', 'password' : 'qiye_pass'}data = urllib.urlencode(postdata)req = urllib2.Request(url)# 将user_agent,referer写入头信息req.add_header('User-Agent',user_agent)req.add_header('Referer',referer)req.add_data(data)response = urllib2.urlopen(req)html = response.read()
对有些header要特别注意,为此服务器header例如:
User-Agent:或者一些服务器Proxy浏览器发出的请求是否会通过这个值来判断。Content-Type:在使用REST接口时,服务器会检查该值以确定HTTP Body如何分析内容?Content-Type:在使用REST接口时,服务器会检查该值以确定HTTP Body如何分析内容?使用服务器提供的内容RESTful或SOAP服务时,Content-Type错误的设置会导致服务器拒绝服务。常见值有:application/xml(在XML RPC,如RESTful/SOAP调用时使用),application/json(在JSON RPC调用时使用),application/x-www-form-urlencoded(提交浏览器Web使用表单)。Referer:有时服务器会检查防盗链。
1.3 Cookie处理urllib2对Cookie处理也是自动的,使用CookieJar函数进行Cookie的管理。假如需要得到一个Cookie项的值,可以这样做:
import urllib2import cookielibcookie = cookielib.CookieJar()opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))response = opener.open('http://www.zhihu.com')for item in cookie: print item.name ':' item.value
但有时会遇到这种情况,我们不想让urllib2自动处理,我们想自己添加Cookie设置请求头中的内容可以Cookie域来做:
import urllib2opener = urllib2.build_opener()opener.addheaders.append( ( 'Cookie', 'email=' \\"xxxxxxx@163.com\\" ) )req = urllib2.Request( \\"http://www.zhihu.com/\\" )response = opener.open(req)print response.headersretdata = response.read()
1.4 Timeout设置超时在Pytho n2