分布式爬虫初探

工欲善其事,必先利其器。首先我们需要的软件工具有:

  • MongoDB(数据存储)
  • Scrapy(爬虫框架)
  • Redis(消息队列,去重

搭建MongoDB集群

为了使我们的分布式爬虫更加稳定,不至于MongoDB存储服务器宕机了,就让整个系统瘫痪,我们首先构建一个MongoDB集群,主节点将数据实时同步到从节点,主节点可读可写,从节点不能进行写操作。当主节点宕掉,从节点可以立刻通过仲裁来选举新的主节点,保持系统稳定。
下面配置在一台主机三个不同端口上进行演示,同理扩展到若干个不同的主机。

  1. 在主机上创建三个不同的文件夹,作为数据库的存储位置,每个文件夹里新建一个空的文件夹名为data。
  2. 开启三个命令行窗口来启动服务器,分别输入:
    • 主节点: mongod --dbpath I:\MongoDB\mongodb_master\data --port 1111 --bind_ip=127.0.0.1 --replSet=replcopy1
    • 从节点1:mongod --dbpath I:\MongoDB\mongodb_slave1\data --port 1112 --bind_ip=127.0.0.1 --replSet=replcopy1
    • 从节点2:mongod --dbpath I:\MongoDB\mongodb_slave2\data --port 1113 --bind_ip=127.0.0.1 --replSet=replcopy1
  3. 再开一个命令行窗口,任意登录上面其中一个服务,如登录主节点
    mongo 127.0.0.1:1111
    进行初始化:
> use admin
> config = {
      _id:"replcopy1",
       members:[{
        _id:1,
host:"127.0.0.1:1111"
    },{
_id:2,
host:"127.0.0.1:1112"
    },{
_id:3,
host:"127.0.0.1:1113"
    }]
    }
> rs.initiate(config) #初始化 

一些其他有用的命令:

rs.conf() #查看配置 
rs.status() #查看状态
rs.isMaster() #查看是否是主节点
  1. 测试主从数据是否同步
    在主节点插入数据:
show dbs
show collections
db.country.insert({name:"China"})
show collections

登录从节点:mongo 127.0.0.1:1112
查询数据:db.country.find() 发现并没有查到,而且报错。
这是因为:

对于SECONDARY节点(从节点)默认是不可读的。因为SECONDARY是不允许读和写的,在写多读少的应用中,使用Replica Sets来实现读写分离。通过在连接时指定或者在主库指定slaveOk,由SECONDARY来分担读的压力,PRIMARY(主节点)只承担写操作。一般默认首先进行初始化操作的节点为选择的主节点,其余节点暂时为从节点。
参考:让mongodb的secondary支持读操作

我们在从节点上设置读写分离:
输入rs.slaveOk()或者db.getMongo().setSlaveOk()
不过,下次再通过mongo进入实例的时候,查询仍然会报错,就需要重新配置读写分离了。

  1. 测试主节点宕机时是否可以选举出新的主节点。
    把主节点强制关掉,观察是否有从节点被选为新的主节点。

Scrapy遇到的一些问题

我使用Scrapy框架来做分布式爬虫的过程中,遇到了好多问题,记录如下:

  1. 大致流程:
  • 新建项目: scrapy startproject mySpider
  • 新建爬虫模块:scrapy genspider -t crawl zhihu.com zhihu.com
  • 定义Item:确定要提取的数据
  • 编写爬虫模块:
    spider可以继承的类型有scrapy.Spider,CrawlSpider等。scrapy.Spider是相对最简单的。下面就介绍下CrawlSpider的要注意的点:
    新的属性rules,包含一个或多个Rule对象的集合,Rule对爬取网站的动作定义了特定规则。举个例子,
    rules = ( Rule(LinkExtractor(allow=r'/bk/so2/n(\d+)p(\d+)'), callback='parse_book_list', follow=True), )
    LinkExtractor定义了如何从爬取的页面提取链接。
    callback是每次从LinkExtractor中获取到链接时调用函数。
    follow是指定根据该规则从response提取的链接是否跟进。若callback为None,follow默认为True,否则默认为False。例如:rules = ( Rule(LinkExtractor(allow=r'/bk/so2/n(\d+)p(\d+)'),), )
    这句没有callback,作为“跳板”,只下载网页并根据allow中的匹配的链接,继续遍历下一步的页面,因为有些情况我们并不只抓取某个页面,而是需要“顺藤摸瓜”,从几个种子页面依次推进,最终定位到我们需要的页面。
  • Pipeline:将Item数据写入MongoDB。
  • 反爬虫措施: 伪造随机User-Agent,自动限速,禁用cookie(如果不需登录),IP代理。
  • 去重优化:参考爬虫去重方案

Redis

下面说明一下Redis在分布式爬虫中作用。
一个是作为消息队列,来实现不同主机间的通信。
另一个是去重,来实现增量爬取。
可以看一下使用Redis时在Scrapy的settings.py中的配置:

#使用scrapy_redis的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 在redis中保持scrapy-redis用到的各个队列,从而允许暂停和暂停后恢复
SCHEDULER_PERSIST = True
#使用scrapy_redis的去重方式
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
REDIS_HOST = '127.0.0.1' #redis所在主机的ip
REDIS_PORT = 6379

另外,Redis中去重方式是将生成的fingerprint信息经过SHA-1进行摘要后放入Redis的set数据结构中进行去重的,相对来说比较低效。可以将Redis和BloomFilter结合起来。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,423评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,339评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,241评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,503评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,824评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,262评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,615评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,337评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,989评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,300评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,829评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,193评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,753评论 3 230
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,970评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,708评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,295评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,207评论 2 258

推荐阅读更多精彩内容