架构学习(四):scrapy下载中间件实现动态切换User-Agent

scrapy下载中间件实现动态与固定UserAgent

  • 前言
  • 关卡:实现动态切换User-Agent
    • scrapy设置User-Agent方式梳理
    • User-Agent生效梳理
    • 为何选择在下载中间件中实现
    • 自定义User-Agent下载中间件
  • 结束

前言

请求头User-Agent是比较常规的反爬手段,不同站点对其检测机制各异,有的是检测是否是合规的浏览器User-Agent,有的是在这基础上检测使用次数与频率,更有甚者是跟ip和cookie绑定在一起检测,这就要求我们能够动态去切换User-Agent(随机or判定切换)。

关卡:实现动态切换User-Agent

scrapy设置User-Agent方式梳理

这里整理一下笔者已知的scrapy设置User-Agent的方式:

  1. setting配置文件中设置DEFAULT_REQUEST_HEADERS
    在这里插入图片描述
  2. 生成requests请求时设置请求头
    在这里插入图片描述
  3. setting配置文件中设置USER_AGENT
    我们在源码看一下USER_AGENT的默认值
    在这里插入图片描述
    scrapy是有自带的USER_AGENT中间件的,而USER_AGENT就是跟它一起配合生效的,这个中间件默认也是开启的。所以大家注意了,如果我们直接使用scrapy自带的USER_AGENT机制,是很容易被是被为爬虫的!!!
    在这里插入图片描述
  4. 自定义User-Agent下载中间件,这种方式其实跟方式3是一样的逻辑

User-Agent生效梳理

我们来调试一下方式1方式2方式3,看看三种方式同时设置时最终是哪个方式生效
如下图,按顺序分别为三种方式设置好User-Agent
在这里插入图片描述在这里插入图片描述
如下图,在发起请求生成request队列前,方式1设置成功
在这里插入图片描述
如下图,生成request队列后,经过下载中间件可以看到方式2覆盖了方式1
在这里插入图片描述
我们仔细看下中间件的代码,特别是process_request这个具体实现方法。
在此之前先了解一下setdefault这个方法:
setdefault是Python中字典的一个方法, 它用于在字典中查找指定键 如果键存在, 则返回对应的值; 如果键不存在,则在字典中添加该键,并将其值设置为指定的默认值
由于request.headersUser-Agent有值且是2,所以经过下载中间件后,它还是2
在这里插入图片描述
综上,我们可以得到结论:

  1. 方式1方式2方式3共存时,结果会取方式2
  2. 只存在方式1方式2时,结果会取方式2
  3. 只存在方式1方式3时,结果会取方式1
  4. 方式3要生效必须只有它这种方式

为何选择在下载中间件中实现

首先要说明一下,并非一定要在中间件中才能实现User-Agent动态切换,也可以在脚本开发中对每次生成的request请求时动态设置User-Agent(请求头),但这种方式在笔者看来是不符合python之美的,功能未解耦而不够灵活,每个脚本都要单独实现,既繁琐又提高学习成本。

自定义User-Agent下载中间件

既然选择自定义中间件,那我们就可以随便玩了
首先思考一下,根据需求整理出设计方案:

  1. 动态:随机生成User-Agent
  2. 切换:控制是否动态生成
  3. 全局:需要适配不同场景(固定、动态、切换)

通过上面的思考,在一个全局改动的位置要适配各式各样的脚本应用场景,就需要引入全局控制参数来实现点对点应用,下面是笔者的想法:
在request.meta中增加 auto_change_uachange_ua_ua三个参数来实现,
auto_change_ua是自动切换,每次request都会切换User-Agent
change_ua是一个切换,当前request会切换User-Agent
_ua是固定存储,不切换时一直使用它
同时准备User-Agent列表,用于随机生成,大致样式如下:

def get_random_ua(self):"""Return a ua if possible"""return random.choice(self.ua_list)def process_request(self, request, spider):meta = request.metaua = Noneif meta.get('auto_change_ua') or meta.get('change_ua', None):ua = self.get_random_ua()elif meta.get('_ua', None):ua = meta['_ua']elif not request.headers.get('User-Agent', None):ua = self.get_random_ua()if ua:request.headers['User-Agent'] = uadef process_response(self, request, response, spider):request.meta['_ua'] = request.headers['User-Agent']if 'change_ua' in request.meta:del request.meta['change_ua']if 'auto_change_ua' in request.meta:request.meta['change_ua'] = Truereturn response

开发好后需要在settingDOWNLOADER_MIDDLEWARES配置才能生效,同时,记得把原生的UserAgentMiddleware设置为None,不然它还是会开启的。
在这里插入图片描述

结束

这个关卡的设计方案是笔者根据自己业务场景实现的,大家如果有同样的需求,需要结合自己的业务场景来思考、设计与实现。
好了,分享就到这了,有啥错误的地方请指正~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/453935.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue项目集成booststrap

1.首先安装bootstrap npm install bootstrap 我安装的是4.3的版本 2.在main.js中引用bootstrap import bootstrap/dist/css/bootstrap.css import bootstrap/dist/css/bootstrap.min.css import bootstrap/dist/js/bootstrap.js import bootstrap/dist/js/bootstrap.min.…

Linux ---- Shell编程之免交互

一、Here Document 多行重定向 1、Here Document定义 使用I/O重定向的方式将命令列表提供给交互式程序标准输入的一种替代品Here Document 是标准输 入的一种替代品,可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个文件…

数据类型完整版

第三章 数据类型 3.1 Key操作 3.1.1 相关命令 序号命令语法描述1DEL key该命令用于在 key 存在时删除 key2DUMP key序列化给定 key ,并返回被序列化的值3EXISTS key检查给定 key 是否存在,存在返回1,否则返回04EXPIRE key seconds为给定 k…

新兴人群消费观察:小红书话题浏览量20亿+,数据调研内容策略

近年,由“宅经济”延伸出的懒人经济持续高热。随现代生活观念和产品技术发展,“懒人经济”不止于家门,一波新兴人群正悄然发生变化……本期,笔者想就此进行小红书数据观察,挖掘其主流内容方向。 “新懒人主义”崛起&am…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(7)

接前一篇文章:《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(6) 4.1 PCIe总线的基础知识 与PCI总线不同,PCIe总线使用端到端的连接方式,在一条PCIe链路的两端只能各连接一个设备,这两个…

前端小案例——动态导航栏文字(HTML + CSS, 附源码)

一、前言 实现功能: 这案例是一个具有动态效果的导航栏。导航栏的样式设置了一个灰色的背景,并使用flex布局在水平方向上平均分配了四个选项。每个选项都是一个li元素,包含一个文本和一个横向的下划线。 当鼠标悬停在选项上时,选项的文本颜色…

19113133262(微信同号)【主题广范|见刊快】2024年新材料与应用化学国际学术会议(ICNMAC 2024)

【主题广范|见刊快】2024年新材料与应用化学国际学术会议(ICNMAC 2024) 2024 International Conference New Materials and Applied Chemistry(ICNMAC 2024) 一、【会议简介】 会议背景:随着科技的飞速发展,新材料与应用化学领域的研究成果日益丰富。为…

Golang专家级教程:crypto/rand 库的使用技巧与最佳实践

Golang专家级教程:crypto/rand 库的使用技巧与最佳实践 引言:为什么选择 crypto/randcrypto/rand 基本概念与原理1. 加密安全的伪随机数生成器(CSPRNG)2. 操作系统的随机数源3. 应用场景 如何使用 crypto/rand:基础示例…

canvas路径剪裁clip(图文示例)

查看专栏目录 canvas实例应用100专栏,提供canvas的基础知识,高级动画,相关应用扩展等信息。canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重…

InTouch WinCC多数据轴趋势曲线开发

InTouch新型报表,纯代码实现【免插件】 InTouch/WinCC通用报表控件CommReport V1.0.0发布 【InTouch】历史报警/历史事件插件-报表统计、分析、导出、打印(图文讲解)V2.1.6更新版下载 InTouch/WinCC/iFix/组态王 belt带图 InTouch 流水效…

精雕细琢的文档体验:Spring Boot 与 Knife4j 完美交汇

欢迎来到我的博客,代码的世界里,每一行都是一个故事 精雕细琢的文档体验:Spring Boot 与 Knife4j 完美交汇 前言Knife4j 与 Swagger 的区别1. 特性与优劣势对比:Knife4j:Swagger: 2. 选择 Knife4j 的理由&a…

JVM-双亲委派机制

双亲委派机制定义 双亲委派机制指的是:当一个类加载器接收到加载类的任务时,会自底向上查找是否加载过, 再由顶向下进行加载。 详细流程 每个类加载器都有一个父类加载器。父类加载器的关系如下,启动类加载器没有父类加载器&am…