【愚公系列】《Python网络爬虫从入门到精通》053-Scrapy 自定义中间件

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟

📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主!

👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"挖山不止"的毅力为开发者们搬开知识道路上的重重阻碍!

💎【行业认证·权威头衔】
✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家
✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主
✔ 技术生态共建先锋:横跨鸿蒙、云计算、AI等前沿领域的技术布道者

🏆【荣誉殿堂】
🎖 连续三年蝉联"华为云十佳博主"(2022-2024)
🎖 双冠加冕CSDN"年度博客之星TOP2"(2022&2023)
🎖 十余个技术社区年度杰出贡献奖得主

📚【知识宝库】
覆盖全栈技术矩阵:
◾ 编程语言:.NET/Java/Python/Go/Node…
◾ 移动生态:HarmonyOS/iOS/Android/小程序
◾ 前沿领域:物联网/网络安全/大数据/AI/元宇宙
◾ 游戏开发:Unity3D引擎深度解析
每日更新硬核教程+实战案例,助你打通技术任督二脉!

💌【特别邀请】
正在构建技术人脉圈的你:
👍 如果这篇推文让你收获满满,点击"在看"传递技术火炬
💬 在评论区留下你最想学习的技术方向
⭐ 点击"收藏"建立你的私人知识库
🔔 关注公众号获取独家技术内参
✨与其仰望大神,不如成为大神!关注"愚公搬代码",让坚持的力量带你穿越技术迷雾,见证从量变到质变的奇迹!✨ |


🚀前言

在之前的文章中,我们已经深入学习了 Scrapy 的基本应用和数据处理方法,这一次,我们将带大家一起探索 Scrapy 中的一个高级特性——自定义中间件

在爬虫开发中,中间件是连接各个组件的重要桥梁,Scrapy 提供了一个灵活的中间件机制,可以在爬虫请求和响应的处理过程中插入自定义的逻辑。通过自定义中间件,我们能够实现各种高级功能,如代理池管理、请求重试、修改请求头、处理验证码等。

在本篇文章中,我们将会学习到:

  1. 中间件的基本概念:理解 Scrapy 中间件的作用及其工作流程。
  2. 如何编写自定义中间件:从创建到实现自定义功能,让中间件在请求和响应过程中发挥作用。
  3. 常见的中间件应用场景:如何使用自定义中间件处理代理、请求头、限速等。
  4. 配置和启用中间件:如何在 Scrapy 项目中配置并启用中间件,保证其正常工作。
  5. 调试与优化中间件:如何测试和调试自定义中间件,确保爬虫的高效与稳定。

通过本篇文章的学习,你将能够灵活运用 Scrapy 自定义中间件,解决爬虫开发中的各种复杂需求,提升爬虫的功能和性能。如果你已经在爬虫项目中遇到了一些瓶颈,或者希望使爬虫更强大,那么自定义中间件将是你不可或缺的工具。

🚀一、Scrapy 自定义中间件

Scrapy内置的中间件可能无法满足特殊需求,自定义中间件可通过重写关键方法实现特定功能。以下是三种典型场景的实现:

🔎1.随机请求头中间件

需求背景:防止请求头特征被识别导致封禁

实现步骤:

  1. 创建项目与爬虫

    scrapy startproject header
    cd header
    scrapy genspider headerSpider quotes.toscrape.com
    
  2. 安装依赖

    pip install fake-useragent
    
  3. 编写爬虫(headerSpider.py)

    import scrapy
    
    class HeaderSpider(scrapy.Spider):
        name = "headerSpider"
        
        def start_requests(self):
            urls = [
                "http://quotes.toscrape.com/page/1/",
                "http://quotes.toscrape.com/page/2/"
            ]
            for url in urls:
                yield scrapy.Request(url=url, callback=self.parse)
        
        def parse(self, response):
            print("请求头信息:", response.request.headers.get('User-Agent'))
    
  4. 自定义中间件(middlewares.py)

    from fake_useragent import UserAgent
    
    class RandomHeaderMiddleware:
        def __init__(self, crawler):
            self.ua = UserAgent()
            self.type = crawler.settings.get("RANDOM_UA_TYPE", "chrome")
    
        @classmethod
        def from_crawler(cls, crawler):
            return cls(crawler)
    
        def process_request(self, request, spider):
            request.headers['User-Agent'] = getattr(self.ua, self.type)
    
  5. 配置(settings.py)

    DOWNLOADER_MIDDLEWARES = {
        'header.middlewares.RandomHeaderMiddleware': 400,
        'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None
    }
    RANDOM_UA_TYPE = "random"  # 可选:random/chrome/firefox/ie
    

在这里插入图片描述

🔎2.Cookies模拟登录中间件

需求背景:实现免登录访问需要认证的页面

实现步骤:

  1. 爬虫代码(cookieSpider.py)

     import scrapy
     
     
     class CookiespiderSpider(scrapy.Spider):
         name = 'cookieSpider'                    # 爬虫名称
         allowed_domains = ['douban.com']    # 域名列表
         start_urls = ['http://www.douban.com'] # 请求初始化列表
     
         def start_requests(self):
             # 发送网络请求,请求地址为start_urls列表中的第一个地址
             yield scrapy.Request(url=self.start_urls[0],callback=self.parse)
     
         # 响应信息
         def parse(self, response):
             # 打印登录后的用户名信息
             print(response.xpath('//*[@id="db-global-nav"]/div/div[1]/ul/li[2]/a/span[1]/text()').extract_first())
             pass
    
  2. Cookies中间件(middlewares.py)

     # 自定义cookies中间件
     class CookiesdemoMiddleware(object):
         # 初始化
         def __init__(self,cookies_str):
             self.cookies_str = cookies_str
     
         @classmethod
         def from_crawler(cls, crawler):
             return cls(
                 # 获取配置文件中的cookies信息
                 cookies_str = crawler.settings.get('COOKIES_DEMO')
             )
         cookies = {}    # 保存格式化以后的cookies
         def process_request(self, request, spider):
             for cookie in self.cookies_str.split(';'):    # 通过;分割cookies字符串
                 key, value = cookie.split('=', 1)          # 将key与值进行分割
                 self.cookies.__setitem__(key,value)        # 将分割后的数据保存至字典中
             request.cookies = self.cookies                 # 设置格式化以后的cookies
    
  3. 随机请求头中间件(middlewares.py)

    from fake_useragent import UserAgent  # 导入请求头类
    # 自定义随机请求头的中间件
    class RandomHeaderMiddleware(object):
        def __init__(self, crawler):
            self.ua = UserAgent()  # 随机请求头对象
            # 如果配置文件中不存在就使用默认的Google Chrome请求头
            self.type = crawler.settings.get("RANDOM_UA_TYPE", "chrome")
    
        @classmethod
        def from_crawler(cls, crawler):
            # 返回cls()实例对象
            return cls(crawler)
    
        # 发送网络请求时调用该方法
        def process_request(self, request, spider):
            # 设置随机生成的请求头
            request.headers.setdefault('User-Agent', getattr(self.ua, self.type))
    
  4. 配置(settings.py)

     DOWNLOADER_MIDDLEWARES = {
         # 启动自定义cookies中间件
         'cookiesDemo.middlewares.CookiesdemoMiddleware': 201,
         # 启动自定义随机请求头中间件
        'cookiesDemo.middlewares.RandomHeaderMiddleware':202,
         # 禁用默认生成的配置信息
        'cookiesDemo.middlewares.CookiesdemoDownloaderMiddleware': None,
     }
    COOKIES_STR = "从浏览器获取的真实Cookie字符串"  # 格式:key1=value1; key2=value2
    

🔎3.随机代理IP中间件

需求背景:避免IP被封锁,提升请求成功率

实现步骤:

  1. 爬虫代码(ipSpider.py)

    # -*- coding: utf-8 -*-
    import scrapy
    
    
    class IpspiderSpider(scrapy.Spider):
        name = 'ipSpider'
        allowed_domains = ['httpbin.org/get']
        start_urls = ['http://httpbin.org/get/']
    
        # # 发送网络请求
        # def start_requests(self):
        #     return [scrapy.Request('http://httpbin.org/get',callback = self.parse,
        #                            meta={'proxy':'http://117.88.177.0:3000'})]
    
        #发送网络请求
        def start_requests(self):
            return [scrapy.Request('http://httpbin.org/get',callback = self.parse)]
        # 响应信息
        def parse(self, response):
            print(response.text)  # 打印返回的响应信息
            pass
    
    # 导入CrawlerProcess类
    from scrapy.crawler import CrawlerProcess
    # 导入获取项目设置信息
    from scrapy.utils.project import get_project_settings
    
    
    # 程序入口
    if __name__=='__main__':
        # 创建CrawlerProcess类对象并传入项目设置信息参数
        process = CrawlerProcess(get_project_settings())
        # 设置需要启动的爬虫名称
        process.crawl('ipSpider')
        # 启动爬虫
        process.start()
    
  2. 代理中间件(middlewares.py)

    class IpRandomProxyMiddleware(object):
        # 定义有效的代理ip列表
        PROXIES = [
            '117.88.177.0:3000',
            '117.45.139.179:9006',
            '202.115.142.147:9200',
            '117.87.50.89:8118']
        # 发送网络请求时调用
        def process_request(self, request, spider):
            proxy = random.choice(self.PROXIES)          # 随机抽取代理ip
            request.meta['proxy'] = 'http://'+proxy      # 设置网络请求所使用的代理ip
    
  3. 配置(settings.py)

    DOWNLOADER_MIDDLEWARES = {
        # 激活自定义随机获取代理ip的中间件
        'ipDemo.middlewares.IpRandomProxyMiddleware':200,
        # 禁用默认生成的中间件
       'ipDemo.middlewares.IpdemoDownloaderMiddleware': None
    }
    

🔎4.关键说明

  1. 中间件执行顺序:通过数字权重控制(范围100-900),数值越小越早执行
  2. 调试技巧:通过scrapy shell测试中间件效果
  3. 最佳实践:
    • 代理IP需定期验证有效性
    • Cookies需通过浏览器登录后获取真实值
    • 请求头类型建议优先使用"random"

完整项目结构应包含:

project/
├── scrapy.cfg
└── project/
    ├── __init__.py
    ├── middlewares.py
    ├── settings.py
    └── spiders/
        ├── __init__.py
        ├── headerSpider.py
        ├── cookieSpider.py
        └── ipSpider.py
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愚公搬代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值