Scrapy 中的高级用法:使用中间件和扩展自定义爬虫行为

2023-04-17 00:00:00 爬虫 自定义 用法

一、使用中间件

中间件是 Scrapy 中一个非常强大的功能,可以在请求和响应的处理过程中对程序自动处理的过程进行自定义的拦截和处理。同时也可以对 Scrapy 系统中的默认处理过程进行拓展和增强。

使用中间件需要继承 scrapy 模块的 Middleware 类,并且实现以下方法:

  1. process_request(request, spider)
    这个方法会在每一个请求被处理前自动被回调,可以实现对请求的过滤和处理。

  2. process_response(request, response, spider)
    这个方法会在每一个响应处理完毕后自动被回调,可以实现对响应的自定义处理。

  3. process_exception(request, exception, spider)
    这个方法会在处理一个请求出现异常时自动被回调,可以在异常出现的时候进行自定义的处理。

以下是一个示例:

import random

class RandomUserAgentMiddleware(object):
    def __init__(self):
        self.user_agents = [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
        ]

    def process_request(self, request, spider):
        agent = random.choice(self.user_agents)
        request.headers['User-Agent'] = agent
        return None

二、使用扩展

在 Scrapy 中使用扩展可以对爬虫进行一些额外的自定义操作,比如在运行过程中对爬虫的状态进行记录和分析等。

使用扩展需要继承 scrapy 模块的 extensions 扩展类,并实现以下方法:

  1. spider_opened(spider)
    在每个爬虫被开启时调用,可以实现爬虫开启前的自定义处理。

  2. spider_closed(spider)
    在每个爬虫被关闭时调用,可以实现爬虫关闭前的自定义处理。

  3. item_scraped(item, response, spider)
    在爬虫成功爬取到一个 item 时调用,可以实现对 item 的自定义处理。

以下是一个示例:

from datetime import datetime
import json

class CustomStatsExtension(object):
    def __init__(self, stats):
        self.stats = stats

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.stats)

    def spider_closed(self, spider):
        item_scraped_count = self.stats.get_value('item_scraped_count')
        data = {
            'spider': spider.name,
            'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'item_scraped_count': item_scraped_count
        }
        with open('stats.json', 'a') as f:
            f.write(json.dumps(data) + '\n')

相关文章