利用爬虫获取豆瓣上可能喜欢的书籍
标签: 爬虫 Python
1.目标
博主比较喜欢看书,购物车里面会放许多书,然后等打折的时候开个大招。然而会遇到一个问题,就是不知道什么书是好书,不知道一本书到底好不好,所以常常会去豆瓣读书看看有什么好书推荐,不过这样效率比较低。最近学习了爬虫的基础知识,有点手痒,故写一个爬取豆瓣推荐书籍的爬虫,和大家分享一下。
我们给爬虫设置一个起始url,然后爬取豆瓣在该url推荐的书籍及推荐书籍的推荐书籍……直到达到预设的爬取次数或者某个终止条件。
由于篇幅有限,不可能讲解太多的基础知识,如果大家觉得理解有困难的话,可以看看慕课网Python开发简单爬虫的视频,这个视频非常的赞。
2.爬虫框架
爬虫一共有5个模块:调度器,url管理器,html下载器,html解析器和html输出器。
爬虫调度器通过调度其它的模块完成任务,上面推荐的视频中有一张非常棒的图说明了爬虫通过调度器运行的流程:
其中的应用模块对应的是输出器,解释一下运行流程:
(1) 调度器查询是否有未爬取的url
(2) 如果“无”则跳转至(8),如果“有”则获取一个url
(3) 下载器根据获取的url下载html数据
(4) 解析器解析下载的html数据,获得新的url和有价值数据
(5) 调度器将获得的url传递给url管理器
(6) 调度器将获得的有价值数据传递给输出器
(7) 跳转至(1)
(8) 将输出器中的有价值数据全部输出
3.爬虫实现
3.1 url管理器实现
url管理器对未爬取和已爬取的url进行管理,记录未爬取的url是为了对新的网页进行爬取,记录已爬取的url是为了防止爬取已经爬取过的网页。
url管理器中有2个集合,分别记录未爬取和已爬取的url。
url管理器中有4种方法,详见代码注释:
#file: url_manager.py
class UrlManager(object):
def __init__(self):
self.new_urls = set() #未爬取url集合
self.old_urls = set() #已爬取url集合
#添加新的单个url,只添加不在新旧集合中的url
def add_new_url(self, url):
if url is None:
return
if url not in self.new_urls and url not in self.old_urls:
self.new_urls.add(url)
#添加新的一堆url,调用add_new_url添加
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
#是否还有未爬取的url
def has_new_url(self):
return len(self.new_urls) != 0
#获取一个新的url,将该url从未爬取集合删除,添加到已爬取集合中
def get_new_url(self):
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
3.2 html下载器实现
html下载器根据传入的url下载网页的html数据。
下载器需要用到urllib2
库,这个库是Python编写爬虫时常用的库,具有根据给定的url获取html数据,伪装成浏览器访问网页,设置代理等功能。由于我们获取的是豆瓣的推荐书籍,不需要登录,所以只使用根据url获取html数据的功能即可。
需要注意的是,豆瓣是个很不错的网站,所以可能有很多的爬虫在爬取豆瓣,因此豆瓣也有很多的反爬虫机制,最直接的反爬虫机制就是禁制程序访问豆瓣,因此我们的爬虫要伪装成浏览器进行页面爬取。
#file: html_downloader.py
import urllib2
class HtmlDownloader(object):
def download(self, url):
if url is None:
return None
try:
request = urllib2.Request(url)
request.add_header('user-agent', 'Mozilla/5.0') #添加头信息,伪装成Mozilla浏览器
response = urllib2.urlopen(request) #访问这个url
except urllib2.URLError, e: #如果出错则打印错误代码和信息
if hasattr(e,"code"):
print e.code #错误代码,如403
if hasattr(e,"reason"):
print e.reason #错误信息,如Forbidden
if response.getcode() != 200: #200表示访问成功
return None
return response.read() #返回该url的html数据
3.3 html解析器实现
解析器解析下载的html数据,获得新的url和有价值数据,该模块是爬虫最麻烦的模块。
解析器需要用到BeautifulSoup
和re
库。
BeautifulSoup
是用Python写的一个HTML/XML的解析器,可以很方