Scrapy如何设置iP,并实现IP重用, IP代理池重用

前置知识

1/3乐观锁

这是我学Redis时的笔记

2/3 Scrapy流程(非全部)

在这里插入图片描述

3/3 关于付费代理

我用的"快代理", 1000个ip, 每个ip1min的有效期, 你用的时候, 把你的链接, 用户名填上去就行

设置代理IP 🔒

  • & 帮助文档: ①meta ②meta#proxy
  • $ 语法: ①proxy的设置: Request对象中有个meta属性, 其下有个proxy属性, request.meta['proxy']="http://2.2.3.3:4324" ②download-timeout属性
  • ! 卡点: Scrapy的异步是, 将所有的请求(近乎)同一时刻发出, 所以需要一个"版本锁"/"乐观锁"的思想(Redis的锁)

1.不可重用, 同步的思路

# Version_1: 因为异步延迟问题, 导致的ip复用失败
class IpDownloaderMiddleware:
    def __init__(self):
        # self.current_proxy_ip = self.get_proxy_ip()  # 初始化当前代理IP
        self.current_proxy_ip = "http://3.3.3.3:3333"  # 模拟ip失效

    @classmethod
    def from_crawler(cls, crawler):
        s = cls()
        return s

    def process_request(self, request: Request, spider):
        request.meta['proxy'] = self.current_proxy_ip  # 使用当前代理IP
        request.meta['download_timeout'] = 1  # 1s内没有返回就超时
        return None

    def process_response(self, request: Request, response: Response, spider):
        if response.status != 200:
            print(f"请求失败: {request.url}, 状态码: {response.status}")
            self.current_proxy_ip = self.get_proxy_ip()  # 获取新的代理IP
            request.meta['proxy'] = self.current_proxy_ip  # 更新请求的代理IP
            return request  # 返回请求以重试
        return response

    def process_exception(self, request, exception, spider):
        print(f"请求 {request.url} 发生异常: {exception}")
        self.current_proxy_ip = self.get_proxy_ip()  # 获取新的代理IP
        request.meta['proxy'] = self.current_proxy_ip  # 更新请求的代理IP
        return request  # 返回请求以重试

    def get_proxy_ip(self):
        api_url = "换成你的付费ip代理地址"
        proxy_ip = requests.get(api_url).text
        username = "你的账号"
        password = "你的密码"
        return f"http://{username}:{password}@{proxy_ip}/"

2. 可重用单ip版本

# Version_2: 采用类似"版本锁"的思想, 构建复用单ip
#   大体思路: 一个ip就是一个版本, ①版本相同+报错=ip失效(需要获取新ip) ②版本不同+报错=ip未及时更新(更新版本即可,无需获取新ip)
class IpDownloaderMiddleware_V2:
    def __init__(self):
        # self.current_proxy_ip = self.get_proxy_ip()  # 初始化当前代理IP
        self.current_proxy_ip = "http://3.3.3.3:8923"  # 模拟ip失效

    @classmethod
    def from_crawler(cls, crawler):
        s = cls()
        return s

    def process_request(self, request: Request, spider):
        request.meta['proxy'] = self.current_proxy_ip  # 使用当前代理IP
        request.meta['download_timeout'] = 1  # 1s内没有返回就超时
        request.meta['max_retry_times'] = 3  # 最多尝试0次
        # 打印当前是第几次try
        if "retry_times" not in request.meta:
            request.meta['retry_times'] = 1
        print(f"url:{request.url}, {request.meta['retry_times']}/{request.meta['max_retry_times']}")
        return None

    def process_response(self, request: Request, response: Response, spider):
        if response.status != 200:
            self.check_version(request)
            return request
        return response

    def process_exception(self, request, exception, spider):
        if isinstance(exception, twisted.internet.error.TimeoutError):
            self.check_version(request)
            return request

    def check_version(self, request):
        # 检测版本
        # case1:版本相同,意味着ip失效, 需要新的ip
        if request.meta['proxy'] == self.current_proxy_ip:
            self.current_proxy_ip = self.get_proxy_ip()  # 更新ip
            request.meta['proxy'] = self.current_proxy_ip
            print("获取新ip成功!!!")
        # case2: 版本不同,意味着未及时更新ip
        else:
            print("ip未及时更新,已正确赋值新ip")
            request.meta['proxy'] = self.current_proxy_ip

    def get_proxy_ip(self):
        api_url = "换成你的付费ip代理地址"
        proxy_ip = requests.get(api_url).text
        username = "你的账号"
        password = "你的密码"
        return f"http://{username}:{password}@{proxy_ip}/"

3. 可复用ip代理池

# Version_3: 同Version_2的思想, 构建ip池
class IpDownloaderMiddleware_V3:
    def __init__(self):
        self.pool_size = 5
        self.proxy_ip_pool = [f"http://3.3.3.3:333{i}" for i in range(self.pool_size)]  # 模拟失效ip
        # self.proxy_ip_pool = [self.get_proxy_ip() for _ in range(self.pool_size)]  # 初始化当前代理IP

    @classmethod
    def from_crawler(cls, crawler):
        s = cls()
        return s

    def process_request(self, request: Request, spider):
        request.meta['proxy'] = random.choice(self.proxy_ip_pool)  # 使用当前代理IP
        request.meta['download_timeout'] = 1  # 1s内没有返回就超时
        request.meta['max_retry_times'] = 3  # 最多尝试0次
        # 打印当前是第几次try
        if "retry_times" not in request.meta:
            request.meta['retry_times'] = 1
        print(f"url:{request.url}, {request.meta['retry_times']}/{request.meta['max_retry_times']}")
        return None

    def process_response(self, request: Request, response: Response, spider):
        if response.status != 200:
            self.check_version(request)
            return request
        return response

    def process_exception(self, request, exception, spider):
        if isinstance(exception, twisted.internet.error.TimeoutError):
            self.check_version(request)
            return request

    def check_version(self, request):
        # 检测版本
        # case1:版本相同[在ip池里有],意味着ip失效, 需要新的ip
        if request.meta['proxy'] in self.proxy_ip_pool:
            # 更新ip
            self.proxy_ip_pool.remove(request.meta['proxy'])  # 删除错误版本
            self.proxy_ip_pool.append(self.get_proxy_ip())  # 相当于替换

            request.meta['proxy'] = random.choice(self.proxy_ip_pool)
            print("获取新ip成功!!!")
        # case2: 版本不同,意味着未及时更新ip
        else:
            request.meta['proxy'] = random.choice(self.proxy_ip_pool)
            print("ip未及时更新,已正确赋值新ip")
        print(f"当前代理池:{self.proxy_ip_pool}")

    def get_proxy_ip(self):
        api_url = "换成你的付费ip代理地址"
        proxy_ip = requests.get(api_url).text
        username = "你的账号"
        password = "你的密码"
        return f"http://{username}:{password}@{proxy_ip}/"

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

消息队列篇--通信协议篇--网络通信模型(OSI7层参考模型,TCP/IP分层模型)

一、OSI参考模型(Open Systems Interconnection Model) OSI参考模型是一个用于描述和标准化网络通信功能的七层框架。它由国际标准化组织(ISO)提出,旨在为不同的网络设备和协议提供一个通用的语言和结构,以…

开源智慧园区管理系统对比五款主流产品探索智能运营新模式

内容概要 在这个数字化迅速发展的时代,园区管理也迎来了全新的机遇和挑战。众所周知,开源智慧园区管理系统作为一种创新解决方案,正逐步打破传统管理的局限性。它的开放性不仅使得系统可以根据具体需求进行灵活调整,也为用户提供…

leetcode——删除链表的倒数第N个节点(java)

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5] 示例 2: 输入:head [1], n 1 输出:[] 示例 3&#xf…

WPS数据分析000009

一、函数与数据透视表统计数据时效率差异 函数 F4绝对引用 数据透视表 二、数据透视表基础操作 数据透视表:一个快速的生成报表的工具 显示详细信息 方式一; 方式二: 移动数据透视表 删除数据透视表 复制粘贴数据透视表 留足空间,否则拖动字…

【C++图论】1761. 一个图中连通三元组的最小度数|2005

本文涉及知识点 C图论 LeetCode1761. 一个图中连通三元组的最小度数 给你一个无向图,整数 n 表示图中节点的数目,edges 数组表示图中的边,其中 edges[i] [ui, vi] ,表示 ui 和 vi 之间有一条无向边。 一个 连通三元组 指的是 …

ubuntu 更新24LTS中断导致“系统出错且无法恢复,请联系系统管理员”

22LTS to 24LTS 更新过程中手jian把更新程序controlC导致的。 解决 目前企图完成更新来恢复,重启后有软件包冲突,sudo apt upgrade报冲突。无法进行。 将原来source.list重新 sudo dpkg --configure -a sudo apt install -f 这些都不管用。还是显示gno…

vscode环境中用仓颉语言开发时调出覆盖率的方法

在vscode中仓颉语言想得到在idea中利用junit和jacoco的覆盖率,需要如下几个步骤: 1.在vscode中搭建仓颉语言开发环境; 2.在源代码中右键运行[cangjie]coverage. 思路1:编写了测试代码的情况(包管理工具) …

C语言的灵魂——指针(1)

指针是C语言的灵魂,有了指针C语言才能完成一些复杂的程序;没了指针就相当于C语言最精髓的部分被去掉了,可见指针是多么重要。废话不多讲我们直接开始。 指针 一,内存和地址二,编址三,指针变量和地址1&#…

mantisbt添加修改用户密码

文章目录 问题当前版本安装流程创建用户修改密码老的方式探索阶段 问题 不太好改密码啊。貌似必须要域名要发邮件。公司太穷,看不见的东西不关心,只能改源码了。 当前版本 当前mantisbt版本 2.27 php版本 7.4.3 安装流程 (下面流程不是…

DIY QMK量子键盘

最近放假了,趁这个空余在做一个分支项目,一款机械键盘,量子键盘取自固件名称QMK(Quantum Mechanical Keyboard)。 键盘作为计算机或其他电子设备的重要输入设备之一,通过将按键的物理动作转换为数字信号&am…

PostGIS笔记:PostgreSQL 数据库与用户 基础操作

数据库基础操作包括数据模型的实现、添加数据、查询数据、视图应用、创建日志规则等。我这里是在Ubuntu系统学习的数据库管理。Windows平台与Linux平台在命令上几乎无差异,只是说在 Windows 上虽然也能运行良好,但在性能、稳定性、功能扩展等方面&#x…

深度解析:基于Vue 3的教育管理系统架构设计与优化实践

一、项目架构分析 1. 技术栈全景 项目采用 Vue 3 TypeScript Tailwind CSS 技术组合,体现了现代前端开发的三大趋势: 响应式编程:通过Vue 3的Composition API实现细粒度响应 类型安全:约60%的组件采用TypeScript编写 原子化…

linux 管道符、重定向与环境变量

1. 输入输出重定向 在linux工作必须掌握的命令一文中,我们已经掌握了几乎所有基础常用的Linux命令,那么接下来的任务就是把多个命令适当的组合到一起,使其协同工作,会更高效的处理数据,做到这一点就必须搞清楚命令的输…

C语言编程笔记:文件处理的艺术

大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文一、为什么要用文件二、文件的分…

K8s运维管理平台 - KubeSphere 3.x 和4.x 使用分析:功能较强,UI美观

目录标题 Lic使用感受优点:优化点: 实操首页项目 | 应用负载 | 配置 | 定制资源定义存储监控告警集群设置 **KubeSphere 3.x** 和 **4.x**1. **架构变化**:2. **多集群管理**:3. **增强的 DevOps 功能**:4. **监控与日…

堆的简要分析与实现(Java)

目录 开场白 顺序存储下标的关系 堆的定义 堆的实现 大顶堆 准备工作 建堆 获取最大元素 删除最大元素 删除指定索引元素 替换指定索引元素 新增元素 完整实现 & 单元测试 小顶堆 统一实现 总结 开场白 在上一篇文章中我们简要分析并实现了二叉树&#xff…

初学FreeRTOS --- 介绍

FreeRTOS介绍: “RTOS” 全称是 Real Time Operating System, 中文名就是实时操作系统,要注意的是, RTOS 并不是指某一特定的操作系统,而是指一类操作系统,例如, C/OS, FreeR…

【记录】日常|从零散记录到博客之星Top300的成长之路

文章目录 shandianchengzi 2024 年度盘点概述写作风格简介2024年的创作内容总结 shandianchengzi 2024 年度盘点 概述 2024年及2025年至今我创作了786即84篇文章,加上这篇就是85篇。 很荣幸这次居然能够入选博客之星Top300,这个排名在我之前的所有年份…

基于Django的Boss直聘IT岗位可视化分析系统的设计与实现

【Django】基于Django的Boss直聘IT岗位可视化分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python作为主要开发语言,利用Django这一高效、安全的W…

神经网络|(一)加权平均法,感知机和神经元

【1】引言 从这篇文章开始,将记述对神经网络知识的探索。相关文章都是学习过程中的感悟和理解,如有雷同或者南辕北辙的表述,请大家多多包涵。 【2】加权平均法 在数学课本和数理统计课本中,我们总会遇到求一组数据平均值的做法…