分布式爬虫笔记-2. Scrapy-Redis-MongoDB架构设计
2016-04-15
写在前面:本篇系统环境为CentOS 7.0 -阿里云主机(Master)、CentOS 6.5 -腾讯云主机(Slaver)。
[TOC]
1. 软硬件版本说明
Master主机
- CentOS 7.0 -阿里云主机
- Python 2.7.5
- Scrapy 1.0.5
- pip 8.1.1
- redis-py 2.10.5
- Redis-3.0.7
- pymongo-3.2.2
- MongoDB-3.2.2
- scrapy-redis-0.6.0
- requests-2.10.0
Slaver 主机
- CentOS 6.5 -腾讯云主机
- Python 2.7.11
- Scrapy 1.0.5
- redis-py 2.10.5
- pymongo-3.2.2
- redis-2.10.5-py2.py3-none-any.whl
- pip 8.1.1
- requests-2.10.0
2. 架构解析
2.1 Master-Slaver框架
Figure 1. Master-Slaver框架示意图
演示框架共有两台主机。Master主机安装Redis和MongoDB,分别进行任务调度和数据存储。Slaver主机运行Scrapy框架爬虫,抓取数据。
2.2 代码组件描述
Figure 2. 代码组件描述
MicroWebSpiders
实际上是一个Scrapy工程。
2.3 文件目录结构
#Master
.
└── master_crawler
├── json
├── logs
│ ├── mongodb.log
│ ├── redis.log
│ └── scrapy.log
├── master_crawler
│ ├── __init__.py
│ ├── commands
│ │ ├── __init__.py
│ │ └── init_single_mongodb.py #init DataBase
│ ├── items.py
│ ├── pipelines
│ │ ├── __init__.py
│ │ ├── json_pipeline.py
│ │ ├── mongodb_pipeline.py
│ │ └── mongodb_file_pipeline.py
│ ├── scrapy_redis
│ │ ├── connection.py
│ │ ├── dupefilter.py
│ │ ├── __init__.py
│ │ ├── pipelines.py
│ │ ├── queue.py
│ │ ├── scheduler.py
│ │ ├── spiders.py
│ │ └── tests.py
│ ├── settings.py
│ ├── spiders
│ │ ├── __init__.py
│ │ └── master_spider.py
│ └── utils
│ └── __init__.py
└── scrapy.cfg
3. 模块实现
3.1 settings.py文件
3.2 commands模块
3.2.1 init_single_mongodb.py文件:初始化单服务器MongoDB
- client = MongoClient(SingleMONGODB_SERVER_HOST,SingleMONGODB_SERVER_PORT)
- def drop_database(name_or_database)
- create_index()
- main
3.2.2 init_sharding_mongodb.py文件:初始化分片式MongoDB集群
3.3 spiders模块
3.3.1 master_spider.py文件:初始化单服务器MongoDB
- class MasterCrawlerItem(Item)
- name, allow_domains, start_urls
- urls_lx, items_lx
- rules = (
Rule(urls_lx), Rule(items_lx, callback='parse_items', follow=True) ) - def _set_crawler(self, crawler)
- def parse_items(self,response)
3.4 items.py文件
- class MasterSpider(CrawlSpider)
3.5 pipelines模块
3.5.1 mongodb_pipeline.py文件:存储信息到MongoDB
class SingleMongodbPipeline(object)
- MONGODB_SERVER_HOST, MONGODB_SERVER_PORT, MONGODB_DB_NAME
- def init(self)
- def from_crawler(cls, crawler)
- def process_item(self, item, spider)
class ShardMongodbPipeline(object)
- MONGODB_SERVER_HOST, MONGODB_SERVER_PORT, MONGODB_DB_NAME, GridFs_Collection
- def init(self)
- def from_crawler(cls, crawler)
- def process_item(self, item, spider)
3.5.2 mongodb_file_pipeline.py文件:存储文件到MongoDB
class SingleMongodbFilePipeline(object)
class ShardMongodbFilePipeline(object)
3.5.3 json_pipeline.py文件:存储json文件到本地
3.6 scrapy_redis模块
3.6.1 connection.py
负责根据setting中配置实例化redis连接。被dupefilter和scheduler调用,总之涉及到redis存取的都要使用到这个模块。
3.6.2 dupefilter.py
负责执行requst的去重,实现的很有技巧性,使用redis的set数据结构。但是注意scheduler并不使用其中用于在这个模块中实现的dupefilter键做request的调度,而是使用queue.py模块中实现的queue。
当request不重复时,将其存入到queue中,调度时将其弹出。
3.6.3 queue.py
其作用如II所述,但是这里实现了三种方式的queue:
FIFO的SpiderQueue,SpiderPriorityQueue,以及LIFI的SpiderStack。默认使用的是第二中,这也就是出现之前文章中所分析情况的原因(链接:)。
3.6.4 pipelines.py
这是是用来实现分布式处理的作用。它将Item存储在redis中以实现分布式处理。
另外可以发现,同样是编写pipelines,在这里的编码实现不同于文章(链接:)中所分析的情况,由于在这里需要读取配置,所以就用到了from_crawler()函数。
3.6.5 scheduler.py
此扩展是对scrapy中自带的scheduler的替代(在settings的SCHEDULER变量中指出),正是利用此扩展实现crawler的分布式调度。其利用的数据结构来自于queue中实现的数据结构。
scrapy-redis所实现的两种分布式:爬虫分布式以及item处理分布式就是由模块scheduler和模块pipelines实现。上述其它模块作为为二者辅助的功能模块。
3.6.6 spider.py
设计的这个spider从redis中读取要爬的url,然后执行爬取,若爬取过程中返回更多的url,那么继续进行直至所有的request完成。之后继续从redis中读取url,循环这个过程。
分析:在这个spider中通过connect signals.spider_idle信号实现对crawler状态的监视。当idle时,返回新的make_requests_from_url(url)给引擎,进而交给调度器调度。
3.7 utils模块
4. Example:抓取58同城租房信息
4.1 items.py文件设计
#!/usr/bin/python
#-*-coding:utf-8-*-
from scrapy.item import Item, Field
class MasterCrawlerItem(Item):
mongodbID = Field()
title = Field()
link = Field()
#link_hashcode = Field()
updateTime = Field()
viewTimes = Field()
price = Field()
payMethod = Field()
houseType = Field()
block = Field()
address = Field()
furnishing = Field()
content = Field()
#contentTel = Field()
#contentName = Field()
#contentLink = Field()
description = Field()
imageURLs = Field()
neighborDetails = Field()