手机套 东莞网站建设绍兴 网站制作
2026/1/2 2:44:49 网站建设 项目流程
手机套 东莞网站建设,绍兴 网站制作,网站开发软件最流行,scrm和crm如何配合前言 Scrapy 框架的高扩展性核心体现在其模块化的组件设计#xff0c;而中间件#xff08;Middleware#xff09;是连接引擎#xff08;Engine#xff09;与其他核心组件#xff08;下载器、爬虫、响应处理#xff09;的关键桥梁。无论是应对反爬机制#xff08;如 UA…前言Scrapy 框架的高扩展性核心体现在其模块化的组件设计而中间件Middleware是连接引擎Engine与其他核心组件下载器、爬虫、响应处理的关键桥梁。无论是应对反爬机制如 UA 伪装、IP 代理、Cookie 池还是实现请求 / 响应的个性化处理如数据加密 / 解密、请求重试自定义中间件都是最优解决方案。本文将从中间件的核心原理入手系统讲解 Scrapy 各类中间件的开发规范结合实战案例实现 UA 随机切换、代理池集成、请求重试等高频需求帮助开发者掌握中间件的定制化开发能力解决爬虫开发中的各类个性化与反爬问题。摘要本文聚焦 Scrapy 中间件的自定义开发实战首先剖析 Scrapy 中间件的分类下载器中间件、爬虫中间件及执行流程明确不同中间件的作用域与优先级规则其次通过多个实战案例目标站点豆瓣图书 Top100分别实现自定义 User-Agent 中间件、IP 代理中间件、请求重试中间件、响应数据清洗中间件最后讲解中间件的调试方法与优先级调优策略。通过本文读者可掌握 Scrapy 中间件的开发逻辑灵活应对各类爬虫场景的个性化需求提升爬虫的稳定性与抗反爬能力。一、Scrapy 中间件核心原理1.1 中间件分类与作用Scrapy 中间件分为两大类核心作用与执行阶段如下表所示中间件类型作用域核心作用下载器中间件引擎 ↔ 下载器处理请求如修改 UA、添加代理、加密参数、处理响应如解密、数据清洗、请求异常重试爬虫中间件引擎 ↔ 爬虫处理爬虫产出的 Item、调整请求优先级、过滤无效请求 / 响应1.2 中间件执行流程下载器中间件执行顺序请求方向引擎→下载器按settings.py中DOWNLOADER_MIDDLEWARES配置的优先级数字越小越先执行依次执行process_request方法响应方向下载器→引擎按优先级数字越大越先执行依次执行process_response方法异常处理请求失败时执行process_exception方法。爬虫中间件执行顺序请求方向爬虫→引擎执行process_spider_output方法响应方向引擎→爬虫执行process_spider_input方法异常处理执行process_spider_exception方法。1.3 核心方法说明方法名所属中间件触发时机返回值规则process_request下载器引擎将请求发送至下载器前返回 None继续执行后续中间件返回 Response直接返回响应返回 Request重新调度请求process_response下载器下载器返回响应至引擎前返回 Response继续执行后续中间件返回 Request重新调度请求process_exception下载器请求抛出异常时返回 None继续抛出异常返回 Response替代异常结果返回 Request重新调度请求process_spider_input爬虫响应发送至爬虫前返回 None正常执行抛出异常触发异常处理process_spider_output爬虫爬虫产出 Item/Request 后返回迭代器包含 Item/Request 对象二、环境搭建2.1 基础环境要求软件 / 库版本要求作用Python≥3.8基础开发环境Scrapy≥2.6爬虫框架fake-useragent≥1.1.1生成随机 User-Agentrequests≥2.28代理池接口请求可选2.2 环境安装bash运行pip install scrapy2.6.2 fake-useragent1.1.1 requests2.28.2三、自定义中间件实战开发3.1 创建基础爬虫项目bash运行# 创建项目 scrapy startproject douban_book_middleware # 进入项目目录 cd douban_book_middleware # 创建爬虫文件 scrapy genspider douban_book_top100 book.douban.com3.2 实战 1自定义 User-Agent 中间件反基础反爬3.2.1 开发思路目标网站常通过固定 User-Agent 识别爬虫需在请求头中随机切换 UA。通过下载器中间件的process_request方法修改请求头利用fake-useragent生成随机 UA。3.2.2 中间件实现middlewares.pypython运行from fake_useragent import UserAgent class RandomUserAgentMiddleware: 随机切换 User-Agent 中间件 def __init__(self): # 初始化 UA 生成器 self.ua UserAgent() def process_request(self, request, spider): 修改请求头中的 User-Agent # 随机选择一个 UA可选指定浏览器类型 random_ua self.ua.random request.headers[User-Agent] random_ua spider.logger.info(f当前使用 User-Agent{random_ua}) # 返回 None继续执行后续中间件 return None3.2.3 启用中间件settings.pypython运行# 启用自定义 UA 中间件优先级设置为 543Scrapy 默认中间件优先级范围 0-1000 DOWNLOADER_MIDDLEWARES { douban_book_middleware.middlewares.RandomUserAgentMiddleware: 543, # 关闭 Scrapy 默认的 UserAgent 中间件 scrapy.downloadermiddlewares.useragent.UserAgentMiddleware: None, }3.2.4 测试验证修改爬虫文件douban_book_top100.pypython运行import scrapy class DoubanBookTop100Spider(scrapy.Spider): name douban_book_top100 allowed_domains [book.douban.com] start_urls [https://book.douban.com/top250] def parse(self, response): # 仅打印响应状态码验证 UA 中间件生效 self.logger.info(f响应状态码{response.status}) yield {url: response.url, status: response.status}启动爬虫bash运行scrapy crawl douban_book_top1003.2.5 输出结果与原理输出日志示例plaintext2025-12-18 10:00:00 [douban_book_top100] INFO: 当前使用 User-AgentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 2025-12-18 10:00:01 [douban_book_top100] INFO: 响应状态码200核心原理process_request方法在请求发送至下载器前被调用修改request.headers即可替换 UA优先级 543 处于 Scrapy 默认中间件的中间区间确保自定义 UA 覆盖默认值fake-useragent内置主流浏览器的 UA 池可随机生成不同类型的 UA降低被识别为爬虫的概率。3.3 实战 2自定义 IP 代理中间件反 IP 封禁3.3.1 开发思路当单 IP 访问频率过高时目标网站会封禁 IP需通过代理池动态切换 IP。本案例实现从本地代理池接口获取可用代理在请求中添加代理配置。3.3.2 中间件实现middlewares.pypython运行import requests import random class RandomProxyMiddleware: 随机切换 IP 代理中间件 def __init__(self): # 代理池接口需自行搭建代理池如 scrapy-proxypool、ProxyPool self.proxy_pool_url http://127.0.0.1:5010/get/ # 无效代理列表 self.invalid_proxies [] def get_random_proxy(self): 从代理池获取随机可用代理 try: response requests.get(self.proxy_pool_url, timeout5) if response.status_code 200: proxy response.text.strip() if proxy and proxy not in self.invalid_proxies: return fhttp://{proxy} except Exception as e: self.logger.error(f获取代理失败{e}) return None def process_request(self, request, spider): 为请求添加代理 proxy self.get_random_proxy() if proxy: request.meta[proxy] proxy spider.logger.info(f当前使用代理{proxy}) return None def process_exception(self, request, exception, spider): 请求异常时标记代理无效并重新请求 if proxy in request.meta: invalid_proxy request.meta[proxy].replace(http://, ) self.invalid_proxies.append(invalid_proxy) spider.logger.warning(f代理 {invalid_proxy} 无效已加入黑名单) # 重新生成请求不使用该代理 new_request request.copy() new_request.dont_filter True # 避免被去重过滤 return new_request3.3.3 启用中间件settings.pypython运行DOWNLOADER_MIDDLEWARES { douban_book_middleware.middlewares.RandomUserAgentMiddleware: 543, douban_book_middleware.middlewares.RandomProxyMiddleware: 542, # 优先级高于 UA 中间件 scrapy.downloadermiddlewares.useragent.UserAgentMiddleware: None, } # 增加超时时间适配代理请求 DOWNLOAD_TIMEOUT 103.3.4 输出结果与原理输出日志示例plaintext2025-12-18 10:05:00 [douban_book_top100] INFO: 当前使用代理http://123.125.71.3:8080 2025-12-18 10:05:01 [douban_book_top100] INFO: 响应状态码200 2025-12-18 10:06:00 [douban_book_top100] WARNING: 代理 192.168.1.1:8888 无效已加入黑名单核心原理process_request为请求添加request.meta[proxy]配置Scrapy 下载器会通过该代理发送请求process_exception捕获请求异常如超时、连接失败标记代理无效并重新生成请求优先级 542 高于 UA 中间件确保代理配置先于 UA 生效dont_filter True避免重新生成的请求被去重组件过滤。3.4 实战 3自定义请求重试中间件提升稳定性3.4.1 开发思路网络波动或目标网站临时故障会导致请求失败需自定义重试逻辑针对特定状态码如 403、500或异常类型进行重试并限制重试次数。3.4.2 中间件实现middlewares.pypython运行from scrapy.downloadermiddlewares.retry import RetryMiddleware from scrapy.utils.response import response_status_message class CustomRetryMiddleware(RetryMiddleware): 自定义请求重试中间件 def process_response(self, request, response, spider): 根据响应状态码决定是否重试 # 如果请求设置了 dont_retry则不重试 if request.meta.get(dont_retry, False): return response # 针对 403、500、502、503 状态码重试 if response.status in [403, 500, 502, 503]: reason response_status_message(response.status) spider.logger.warning(f响应状态码 {response.status}触发重试{reason}) return self._retry(request, reason, spider) or response return response def process_exception(self, request, exception, spider): 针对特定异常重试 # 捕获连接超时、连接拒绝异常 if isinstance(exception, (scrapy.core.downloader.handlers.http11.TunnelError, scrapy.exceptions.ConnectionTimeout)): reason f请求异常{type(exception).__name__} spider.logger.warning(reason) return self._retry(request, reason, spider) return super().process_exception(request, exception, spider)3.4.3 启用中间件settings.pypython运行DOWNLOADER_MIDDLEWARES { douban_book_middleware.middlewares.RandomUserAgentMiddleware: 543, douban_book_middleware.middlewares.RandomProxyMiddleware: 542, douban_book_middleware.middlewares.CustomRetryMiddleware: 541, scrapy.downloadermiddlewares.useragent.UserAgentMiddleware: None, # 关闭 Scrapy 默认的重试中间件 scrapy.downloadermiddlewares.retry.RetryMiddleware: None, } # 重试配置 RETRY_TIMES 3 # 最大重试次数 RETRY_HTTP_CODES [403, 500, 502, 503] # 需重试的状态码3.4.4 输出结果与原理输出日志示例plaintext2025-12-18 10:10:00 [douban_book_top100] WARNING: 响应状态码 403触发重试Forbidden 2025-12-18 10:10:02 [douban_book_top100] WARNING: 响应状态码 403触发重试Forbidden 2025-12-18 10:10:04 [douban_book_top100] INFO: 响应状态码200核心原理继承 Scrapy 原生RetryMiddleware重写process_response和process_exception方法自定义重试规则_retry方法为内置方法会自动增加重试次数并重新调度请求RETRY_TIMES限制最大重试次数避免无限重试。3.5 实战 4自定义爬虫中间件数据过滤3.5.1 开发思路爬虫产出的 Item 可能包含无效数据如空值、重复值需通过爬虫中间件的process_spider_output方法过滤无效 Item。3.5.2 中间件实现middlewares.pypython运行class ItemFilterMiddleware: 过滤无效 Item 的爬虫中间件 def process_spider_output(self, response, result, spider): 处理爬虫输出的 Item/Request for item in result: # 仅处理 Item 对象Request 对象直接放行 if isinstance(item, scrapy.Item): # 过滤空标题的 Item if not item.get(title) or item.get(title).strip() : spider.logger.warning(f过滤无效 Item标题为空) continue # 过滤评分低于 8.0 的 Item score item.get(score, 0) try: if float(score) 8.0: spider.logger.warning(f过滤无效 Item评分 {score} 低于 8.0) continue except ValueError: spider.logger.warning(f过滤无效 Item评分 {score} 格式错误) continue yield item3.5.3 启用中间件settings.pypython运行# 启用爬虫中间件 SPIDER_MIDDLEWARES { douban_book_middleware.middlewares.ItemFilterMiddleware: 543, } # 完善 Item 定义items.py import scrapy class DoubanBookMiddlewareItem(scrapy.Item): title scrapy.Field() score scrapy.Field() author scrapy.Field()3.5.4 测试验证修改爬虫文件的parse方法python运行def parse(self, response): book_list response.xpath(//tr[classitem]) for book in book_list: item DoubanBookMiddlewareItem() item[title] book.xpath(.//a/title).extract_first() item[score] book.xpath(.//span[classrating_nums]/text()).extract_first() item[author] book.xpath(.//p[classpl]/text()).extract_first() yield item启动爬虫后日志输出示例plaintext2025-12-18 10:15:00 [douban_book_top100] WARNING: 过滤无效 Item评分 7.9 低于 8.0 2025-12-18 10:15:00 [douban_book_top100] WARNING: 过滤无效 Item标题为空核心原理process_spider_output接收爬虫产出的迭代器包含 Item/Request遍历并过滤无效 Item仅放行符合条件的 Item确保最终存储的数据有效性爬虫中间件优先级规则与下载器中间件一致数字越小越先执行。四、中间件调试与优先级调优4.1 中间件调试方法调试方式适用场景操作方法日志打印验证中间件是否执行、参数是否正确在中间件方法中添加spider.logger.info/.warning/error打印关键信息Scrapy shell测试单个请求的中间件执行流程scrapy shell https://book.douban.com/top250查看request.headers/meta断点调试定位中间件逻辑错误在中间件方法中添加import pdb; pdb.set_trace()启动爬虫后分步调试4.2 优先级调优规则优先级区间作用示例配置0-500核心基础中间件如代理、UA代理中间件542、UA 中间件543500-800业务逻辑中间件如重试、解密重试中间件541、数据解密中间件600800-1000后置处理中间件如数据清洗响应数据清洗中间件900核心原则依赖前置的中间件优先级更高如代理配置需先于 UA 配置数据处理类中间件后置执行如先获取响应再清洗数据避免优先级冲突相同优先级的中间件执行顺序不确定。五、常见问题与解决方案问题现象原因分析解决方案中间件未执行未在 settings.py 中启用 / 优先级配置错误检查DOWNLOADER_MIDDLEWARES/SPIDER_MIDDLEWARES配置调整优先级UA 未生效默认 UserAgent 中间件未关闭关闭scrapy.downloadermiddlewares.useragent.UserAgentMiddleware代理配置后请求超时代理无效 / 代理池接口不可用验证代理可用性增加代理池健康检查逻辑重试中间件无限重试未设置RETRY_TIMES/ 重试条件过于宽松配置RETRY_TIMES缩小重试状态码 / 异常范围爬虫中间件过滤掉有效 Request逻辑错误误过滤 Request 对象在process_spider_output中判断对象类型仅过滤 Item六、总结本文系统讲解了 Scrapy 中间件的自定义开发流程从核心原理出发通过 4 个实战案例覆盖了下载器中间件UA 切换、代理池、请求重试和爬虫中间件数据过滤的开发与配置同时给出了调试方法与优先级调优策略。中间件作为 Scrapy 框架的扩展核心能够灵活应对反爬机制、数据处理、请求稳定性等各类需求是企业级爬虫开发的必备技能。在实际开发中可根据业务场景扩展更多个性化中间件如 Cookie 池中间件、响应数据解密中间件、请求参数加密中间件等。掌握中间件的开发逻辑后可大幅提升爬虫的适应性与稳定性解决各类复杂的爬虫场景问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询