基于Python,scrapy,redis的分布式爬虫实现框架

搬运自本人博客:http://www.xgezhang.com/python_scrapy_red://is_crawler.html


爬虫技术,无论是在学术领域,还是在工程领域,都扮演者非常重要的角色。相比于其他技术,爬虫技术虽然在实现上比较简单,没有那么多深奥的技术难点,但想要构建一套稳定、高效、自动化的爬虫框架,也并不是一件容易的事情。这里笔者打算就个人经验,介绍一种分布式爬虫框架的实现方法和工作原理,来给刚刚入门爬虫的同学们一点启发和提示。同时也希望大牛们能发表一些看法。

注:本文是对框架的宏观介绍,没有涉及具体代码,适合接触过爬虫和scrapy的读者。如果您对爬虫完全不了解,或者是刚刚入门,可以先看一些简单的爬虫教程和示例,这里贴几个链接:

人人网爬虫(针对老版本,目前可能没法用,但里面的技术是通用的):http://www.xgezhang.com/python_renren_spider_1.html

京东登陆爬虫:http://www.xgezhang.com/python_crawler_jingdong.html

scrapy中文教程:http://scrapy-chs.readthedocs.org/zh_CN/latest/intro/tutorial.html

爬虫,网页Xpath辅助分析工具:http://www.xgezhang.com/xpath_helper.html


框架的几个关键技术点:

scrapy : 实现爬虫的主体。scrapy是目前非常热门的一种爬虫框架,它把整个爬虫过程分为了多个独立的模块,并提供了多个基类可以供我们去自由扩展,让爬虫编写变得简单而有逻辑性。并且scrapy自带的多线程、异常处理、以及强大的自定义Settings也让整个数据抓取过程变得高效而稳定。

scrapy-redis:一个三方的基于redis的分布式爬虫框架,配合scrapy使用,让爬虫具有了分布式爬取的功能。github地址:https://github.com/darkrho/scrapy-redis

mongodb 、mysql 或其他数据库:针对不同类型数据可以根据具体需求来选择不同的数据库存储。结构化数据可以使用mysql节省空间,非结构化、文本等数据可以采用mongodb等非关系型数据提高访问速度。具体选择可以自行百度谷歌,有很多关于sql和nosql的对比文章。

其他:一台高性能的服务器。

分布式原理:

scrapy-redis实现分布式,其实从原理上来说很简单,这里为描述方便,我们把自己的核心服务器称为master,而把用于跑爬虫程序的机器称为slave。

我们知道,采用scrapy框架抓取网页,我们需要首先给定它一些start_urls,爬虫首先访问start_urls里面的url,再根据我们的具体逻辑,对里面的元素、或者是其他的二级、三级页面进行抓取。而要实现分布式,我们只需要在这个starts_urls里面做文章就行了。

我们在master上搭建一个redis数据库(注意这个数据库只用作url的存储,不关心爬取的具体数据,不要和后面的mongodb或者mysql混淆),并对每一个需要爬取的网站类型,都开辟一个单独的列表字段。通过设置slave上scrapy-redis获取url的地址为master地址。这样的结果就是,尽管有多个slave,然而大家获取url的地方只有一个,那就是服务器master上的redis数据库。

并且,由于scrapy-redis自身的队列机制,slave获取的链接不会相互冲突。这样各个slave在完成抓取任务之后,再把获取的结果汇总到服务器上(这时的数据存储不再在是redis,而是mongodb或者 mysql等存放具体内容的数据库了)

这种方法的还有好处就是程序移植性强,只要处理好路径问题,把slave上的程序移植到另一台机器上运行,基本上就是复制粘贴的事情。

url的生成:

看到这里,有同学应该已经想到了,上文只介绍了slave如何去读取url,那么这些url是怎么出现的呢?

首先明确一点,url是在master而不是slave上生成的。

对于每一个门类的urls(每一个门类对应redis下的一个字段,表示一个url的列表),我们可以单独写一个生成url的脚本。这个脚本要做的事很简单,就是按照我们需要的格式,构造除url并添加到redis里面。

对于slave,我们知道,scrapy可以通过Settings来让爬取结束之后不自动关闭,而是不断的去询问队列里有没有新的url,如果有新的url,那么继续获取url并进行爬取。利用这一特性,我们就可以采用控制url的生成的方法,来控制slave爬虫程序的爬取。

定时抓取:

有了上面的介绍,定时抓取的实现就变得简单了,我们只需要定时的去执行url生成的脚本即可。这里推荐linux下的crontab指令,能够非常方便的制定定时任务,具体的介绍大家可以自行查看文档。

程序化管理、web管理:

上述方法虽然能够实现一套完整的流程,但在具体操作过程中还是比较麻烦,可能的话还可以架构web服务器,通过web端来实现url的添加、爬虫状态的监控等,能够减轻非常大的工作量。这些内容如果要展开实在太多,这里就只提一下。


总结:

其实对于已有的scrapy程序,对其扩展成分布式程序还是比较容易的。总的来说就是以下几步:

  • 找一台高性能服务器,用于redis队列的维护以及数据的存储。
  • 扩展scrapy程序,让其通过服务器的redis来获取start_urls,并改写pipeline里数据存储部分,把存储地址改为服务器地址。
  • 在服务器上写一些生成url的脚本,并定期执行。



介绍完整个流程,再来介绍一些常见的防抓取屏蔽的方法:

  • 设置download_delay,这个方法基本上属于万能的,理论上只要你的delay足够长,网站服务器都没办法判断你是正常浏览还是爬虫。但它带来的副作用也是显然的:大量降低爬取效率。因此这个我们可能需要进行多次测试来得到一个合适的值。有时候download_delay可以设为一个范围随机值。
  • 随机生成User-agent:更改User-agent能够防止一些403或者400的错误,基本上属于每个爬虫都会写的。这里我们可以重写scrapy 里的middleware,让程序每次请求都随机获取一个User-agent,增大隐蔽性。具体实现可以参考http://www.sharejs.com/codes/python/8310
  • 设置代理IP池:网上有很多免费或收费的代理池,可以借由他们作为中介来爬。一个问题是速度不能保证,第二个问题是,这些代理很多可能本来就没办法用。因此如果要用这个方法,比较靠谱的做法是先用程序筛选一些好用的代理,再在这些代理里面去随机、或者顺序访问。
  • 设置好header里面的domian和host,有些网站,比如雪球网会根据这两项来判断请求来源,因此也是要注意的地方。

暂时想到这么多,以后有新的发现再补充,也欢迎各位来讨论。

转载请注明出处。


Scrapy-Redis是一个基于Scrapy框架分布式爬虫解决方案,它使用Redis作为分布式队列和去重集合,实现了多个爬虫节点共享一个Redis队列和去重集合,从而实现了高效的分布式爬取。 使用Scrapy-Redis,你可以很容易地将一个单机版的Scrapy爬虫转换成一个分布式爬虫。下面是简单的步骤: 1. 安装RedisScrapy-Redis 首先需要安装Redis,并且确保Redis服务正常运行。另外,需要安装Scrapy-Redis库,可以通过pip命令来进行安装: ``` pip install scrapy-redis ``` 2. 修改爬虫设置 在Scrapy爬虫的settings.py文件中,需要添加如下配置: ``` # 启用Redis调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 启用Redis去重过滤器 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 设置Redis为调度器和去重过滤器的数据存储位置 REDIS_URL = 'redis://localhost:6379' ``` 3. 修改爬虫代码 在Scrapy爬虫的代码中,需要将原来的start_urls修改为redis_key,例如: ``` class MySpider(RedisSpider): name = 'myspider' redis_key = 'myspider:start_urls' ``` 另外,需要将原来的parse方法改为如下形式: ``` def parse(self, response): # 爬虫代码 yield scrapy.Request(url, callback=self.parse_item) ``` 4. 运行爬虫 在启动爬虫之前,需要先往Redis队列中添加起始URL,例如: ``` redis-cli lpush myspider:start_urls http://www.example.com ``` 然后在命令行中启动分布式爬虫,例如: ``` scrapy crawl myspider ``` 这样就可以启动一个分布式Scrapy爬虫了。在多个爬虫节点共享同一个Redis队列和去重集合的情况下,可以大大提高爬取效率和速度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值