1.2 爬虫修炼之道——编写一个爬取单页面的网络爬虫
欢迎大家关注我的专题:爬虫修炼之道
上篇 爬虫修炼之道——网站基本知识 主要讲解了一些和网站相关的知识,对于我们之后理解爬虫有很多好处。这一篇就要编写第一个爬虫了。我们使用的python版本为2.7,此外涉及到的python模块包括:
下载单个网页
想要爬取网页数据,首先需要将其下载下来,我们都知道,每个网页其实都是由一个个html文件组成,我们要做的就是将该文件从服务器下载到本地。这儿我们使用urllib2模块来实现。
urllib2模块的基本用法可参考这篇文章:http://www.pythontab.com/html/2014/pythonhexinbiancheng_1128/928.html
import urllib2
def download(url):
"""
url: 要下载的url页面
"""
print 'Downloading: url %s' % url
try:
html = urllib2.urlopen(url).read()
except urllib2.HTTPError, e:
print 'URL: %s,HTTP Error %s: %s' % (url, e.code, e.msg)
html = None
except urllib2.URLError, e:
print 'URL: %s, urlopen Error %s' % (url, e.reason)
html = None
return html
上面的代码可以实现指定url页面的下载,如果出错(例如,提供了一个错误的URL),则会将错误打印到屏幕上。
失败重试下载
下载出错时,服务器会返回特定的 HTTP状态码,如果状态码为4xx,表示请求存在问题,说明我们应该检查自己的请求;如果状态码为5xx,表示服务器存在问题,有可能只是暂时的,这时,我们需要尝试重新下载,但是必须限定一个下载次数。
def download(url, num_retries=2):
"""
url: 要下载的url页面
num_retries: 碰到5xx状态码时尝试重新下载的次数
"""
print 'Downloading: url %s' % url
try:
html = urllib2.urlopen(url).read()
except urllib2.HTTPError, e:
print 'URL: %s,HTTP Error %s: %s' % (url, e.code, e.msg)
html = None
if num_retries > 0 and 500 <= e.code < 600:
return download(url, num_retries - 1)
except urllib2.URLError, e:
print 'URL: %s, urlopen Error %s' % (url, e.reason)
html = None
return html
例如下载 “http://httpstat.us/500” 网址。
重试下载页面设置下载超时
有时候我们可以规定一个页面多长时间内没有下载完成则放弃,即下载超时。想要实现该功能,可以通过urllib2.urlopen方法的timeout参数来指定超时时间,我们指定它默认为3s。即
urllib2.urlopen(request, timeout=3)
设置用户代理
有些网址会针对爬虫做一些限制,比如,必须设置用户代理,即User-Agent。我们可以使用urllib2.Request类来设置用户代理。
我们先用上面的download方法来下载糗事百科首页(http://www.qiushibaike.com/),运行后,我们会出错,如下图所示:
直接抓取糗百出粗现在我们要设置用户代理(User-Agent),首先需要根据url和headers生成一个urllib2.Request类的实例,其中User-Agent就是在headers中封装的。更新后的 <a id="1-2-download" href="#1-2-download">download</a> 如下:
def download(url, user_agent='crawl', num_retries=2, timeout=3):
"""
下载一个URL页面
:param url: 要下载的url页面
:param user_agent: 用户代理
:param num_retries: 碰到5xx状态码时尝试重新下载的次数
:param timeout: 超时时间,单位为s
:return:
"""
print 'Downloading: url %s' % url
headers = {'User-Agent': user_agent}
request = urllib2.Request(url, headers=headers)
try:
html = urllib2.urlopen(request, timeout=timeout).read()
except urllib2.HTTPError, e:
print 'URL: %s,HTTP Error %s: %s' % (url, e.code, e.msg)
html = None
if num_retries > 0 and 500 <= e.code < 600:
return download(url, num_retries = num_retries - 1)
except urllib2.URLError, e:
print 'URL: %s, urlopen Error %s' % (url, e.reason)
html = None
return html
现在通过download方法来下载糗百官网,结果如下:
设置用户代理后抓取糗百官网用户代理可以自己定义之外,也可以使用浏览器自带的用户代理,比如在chrome浏览器地址栏中输入:chrome://version/ ,可以看到相应的版本信息,我的显示如下:
chrome版本信息我们也可以将它作为我们的用户代理,这样做的话,就是模拟浏览器来访问了。
完整代码参见:https://github.com/Oner-wv/spider_note/blob/master/chapter01/1.2.py
下篇我们将讲解如何编写爬取多个页面的爬虫:爬虫修炼之道——编写一个爬取多页面的网络爬虫
欢迎大家关注我的专题:爬虫修炼之道