Scrapy 是一个强大的 Python 网络爬虫框架,它被广泛用于数据挖掘、网络监控和数据抽取。尽管 Scrapy 的基本功能已经非常强大,但它还有许多高级特性和隐藏技巧等待我们去探索。本文将带你深入了解 Scrapy 的奇妙世界,揭示一些你可能不知道的趣味玩法与技巧。

一、Scrapy 的基础回顾

1.1 安装 Scrapy

首先,确保你已经安装了 Python。然后使用 pip 安装 Scrapy:

pip install scrapy

1.2 创建一个简单的爬虫

使用 Scrapy 命令创建一个新项目和一个爬虫:

scrapy startproject myproject
cd myproject
scrapy genspider myspider example.com

编辑爬虫文件 myspider.py,添加基本的爬取逻辑:

import scrapy

class MySpider(scrapy.Spider):
    name = 'myspider'
    start_urls = ['http://example.com']

    def parse(self, response):
        self.log('A response from %s just arrived!' % response.url)
        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').get(),
                'author': quote.css('small.author::text').get(),
            }

运行爬虫:

scrapy crawl myspider -o output.json

二、Scrapy 的高级特性和技巧

2.1 使用中间件扩展爬虫功能

Scrapy 中间件提供了一种扩展爬虫功能的方式,可以在请求/响应被处理之前或之后执行自定义代码。例如,我们可以编写一个中间件来自动重定向到特定的 URL:

class MyRedirectMiddleware:
    def process_request(self, request, spider):
        if 'redir' in request.meta:
            request.url = request.meta['redir']

settings.py 中启用中间件:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.MyRedirectMiddleware': 543,
}

在爬虫中使用这个中间件:

def parse(self, response):
    yield scrapy.Request('http://example.com/some-page', meta={'redir': 'http://example.com/redirected-page'}, callback=self.parse_redirected)
    
    def parse_redirected(self, response):
        # 处理重定向后的页面
        pass

2.2 自定义管道处理数据

管道组件用于处理从爬虫返回的数据。你可以自定义管道以执行数据清洗、验证或存储操作。例如,将数据存储到 MongoDB:

import pymongo

class MongoDBPipeline:
    collection_name = 'scrapy_items'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.db[self.collection_name].insert_one(dict(item))
        return item

settings.py 中配置管道:

ITEM_PIPELINES = {
    'myproject.pipelines.MongoDBPipeline': 300,
}

MONGO_URI = 'mongodb://localhost:27017'
MONGO_DATABASE = 'mydatabase'

2.3 利用 Scrapy-Redis 实现分布式爬虫

Scrapy-Redis 是一个 Scrapy 扩展,它允许你使用 Redis 作为消息队列来实现分布式爬虫。首先,安装 Scrapy-Redis:

pip install scrapy-redis

settings.py 中配置 Scrapy-Redis:

#启用 Scrapy-Redis 的调度器组件
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

#确保所有的爬虫通过 Scrapy-Redis 去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

#可选,使用 Redis 进行持久化存储
JOBDIR = 'path/to/jobs/directory'

#连接 Redis 数据库
REDIS_HOST = 'localhost'
REDIS_PORT = 6379

修改爬虫以使用 Redis:

”`python import scrapy from scrapy_redis.spiders import RedisSpider

class MyRedisSpider(RedisSpider):

name = 'myredisspider'
redis_key = 'myrediss