以下是一个简单的示例,使用Python、Scrapy(一个流行的爬虫框架)、Redis(作为消息队列和去重存储)和Celery(用于任务调度)来实现分布式爬虫。
1. 设置Redis
Redis用于存储待抓取的URL集合(Set)和任务队列(List)。
bash复制代码
# 安装Redis
sudo apt-get install redis-server
2. 安装依赖库
bash复制代码
pip install scrapy redis celery
3. 配置Celery和Redis
创建一个Celery配置文件celeryconfig.py:
python复制代码
broker_url = 'redis://localhost:6379/0'
result_backend = 'redis://localhost:6379/0'
4. 定义Scrapy爬虫
创建一个Scrapy项目并定义爬虫。在Scrapy项目中,你需要修改一些设置以使用Redis作为调度器和去重过滤器。
bash复制代码
scrapy startproject distributed_spider
cd distributed_spider
修改settings.py:
python复制代码
# settings.py
# 使用Redis去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用Redis调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 设置Redis连接
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
# 开始URL从Redis队列中获取
START_URLS = []
# 从Redis的spider:start_urls队列中获取初始URL
REDIS_START_URLS_AS_SET = True
REDIS_START_URLS_KEY = 'myspider:start_urls'
创建一个爬虫文件,比如example_spider.py:
python复制代码
# example_spider.py
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
def parse(self, response):
# 你的解析逻辑
yield {
'url': response.url,
'title': response.xpath('//title/text()').get()
}
# 继续抓取页面中的其他URL
for href in response.css('a::attr(href)').getall():
yield response.follow(href, self.parse)
5. 使用Celery启动Worker Nodes
创建一个Celery任务来启动Scrapy爬虫:
python复制代码
# tasks.py
from celery import Celery
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from distributed_spider.spiders.example_spider import ExampleSpider
app = Celery('tasks', broker='redis://localhost:6379/0')
@app.task
def crawl():
settings = get_project_settings()
process = CrawlerProcess(settings)
process.crawl(ExampleSpider)
process.start()
6. 启动Master Node和Worker Nodes
启动Redis服务器:
bash复制代码
redis-server
启动Celery Worker:
bash复制代码
celery -A tasks worker --loglevel=info
在Master Node上,你可以使用Redis CLI或其他工具将URL添加到myspider:start_urls队列中:
bash复制代码
redis-cli
LPUSH myspider:start_urls "http://example.com"
然后,你可以通过调用Celery任务来启动爬虫:
python复制代码
# 在Python交互式环境中或另一个脚本中
from tasks import crawl
crawl.delay()
结论
这只是一个基本的示例,实际的分布式爬虫系统可能会更加复杂,需要考虑更多的因素,如故障恢复、负载均衡、动态扩展等。根据具体需求,你可能还需要集成更多的工具和库来完善你的系统。