为了抓取网页,首先要下载包含有感兴趣数据的网页,该过程一般被称为爬取(crawing)。
本文主要介绍了利用sitemap文件,遍历ID,跟踪网页的方法获取网页内容。
想要爬取网页,我们首先要将其下载下来。下载的脚本如下:
import urllib2
def download(url):
return urllib2.urlopen(url).read()
当传入URL地址时,该函数将会下载并返回其HTML。
不过这个代码片存在一点问题,假如URL地址不存在时,urllib2就会抛出异常。改进的版本为:
import urllib2
def download(url):
try:
html=urllib2.urlopen(url).read()
except urllib2.URLError as e:
print 'Downloading error:',e.reason
html=None
return html
print download('http://www.sse.com.cn')
下载时遇到的错误经常是临时性的,比如服务器过载时返回的503错误,对于此类错误,重新下载即可,下面是添加重新重新下载功能的代码:
import urllib2
def download(url,num_reload=5):
try:
html=urllib2.urlopen(url).read()
except urllib2.URLError as e:
print 'Downloading error:',e.reason
html = None
if num_reload>0 and ( hasattr(e,'code') and 500<=e.code<=600 ):
return download(url,num_reload-1)
return html
download('http://httpstat.us/500')
下面的这步可略过:
默认情况下,urllib2使用Python-urllib2/2.7作为用户代理下载网页内容,其中2.7是python的版本号。
import urllib2
def download(url,user_agent='wswp',num_reload=5):
headers={'User-agent':user_agent}
request=urllib2.Request(url,headers=headers)
try:
html=urllib2.urlopen(request).read()
except urllib2.URLError as e:
print 'Downloading error:',e.reason
html = None
if num_reload>0 and ( hasattr(e,'code') and 500<=e.code<=600 ):
return download(url,user_agent,num_reload-1)
return html
download('http://httpstat.us/500')
现在,我们有了一个灵活的函数,可以设置用户代理,设置重试次数。
使用robots.txt文件中的网站地图(即sitemap文件)下载所有的网页。
robots.txt
# section 1
User-agent: BadCrawler
Disallow: /
# section 2
User-agent: *
Crawl-delay: 5
Disallow: /trap
# section 3
Sitemap: http://example.webscraping.com/sitemap.xml
下面是使用sitemap文件爬虫的代码:
#!/usr/bin/python
#coding:utf-8
import urllib2
import re
def download(url,user_agent='wswp',num_reload=5):
headers={'User-agent':user_agent}
request=urllib2.Request(url,headers=headers)
try:
html=urllib2.urlopen(request).read()
except urllib2.URLError as e:
print 'Downloading error:',e.reason
html = None
if num_reload>0 and ( hasattr(e,'code') and 500<=e.code<=600 ):
return download(url,user_agent,num_reload-1)
return html
def crawl_sitemap(url):
sitemap = download(url) #下载网页文件
links = re.findall('(.*?) ',sitemap) # 提取sitemap文件里的格式化连接
for link in links:
print link
html = download(link)
# print html
crawl_sitemap('http://example.webscraping.com/sitemap.xml')
下面是一些示例国家的URL
http://example.webscraping.com/view/Afghanistan-1
http://example.webscraping.com/view/Aland-Islands-2
http://example.webscraping.com/view/Albania-3
http://example.webscraping.com/view/Algeria-4
http://example.webscraping.com/view/American-Samoa-5
http://example.webscraping.com/view/Andorra-6
http://example.webscraping.com/view/Angola-7
http://example.webscraping.com/view/Anguilla-8
可以看出,这些URL只在结尾处有区别。在URL中包含页面别名是非常普遍的做法,可以对搜索引擎起到优化的作用。一般情况下,Web服务器会忽略这个字符串,只用ID来匹配数据中的相关记录。尝试使用http://example.webscraping.com/view/-%d
来匹配所有页面。下面是示例代码:
#!/usr/bin/python
#coding:utf-8
import urllib2
import itertools
def download(url,user_agent='wswp',num_reload=5):
headers={'User-agent':user_agent}
request=urllib2.Request(url,headers=headers)
try:
html=urllib2.urlopen(request).read()
except urllib2.URLError as e:
print 'Downloading error:',e.reason
html = None
if num_reload>0 and ( hasattr(e,'code') and 500<=e.code<=600 ):
return download(url,user_agent,num_reload-1)
return html
for page in itertools.count(1):
url='http://example.webscraping.com/view/%d'%page
html=download(url)
print url
if html is None:
break
本次将使用正则表达式来确定要下载哪些页面。