python爬虫:多线程收集/验证IP从而搭建有效IP代理池

news2025/1/10 10:43:53

目录

一、前言

二、IP池的实现

1. 收集代理IP

2. 验证代理IP可用性

3. 搭建IP代理池

三、多线程实现

四、代理IP的使用

五、总结


一、前言

在网络爬虫中,IP代理池的作用非常重要。网络爬虫需要大量的IP地址来发送请求,同时为了降低被封禁的风险,使用代理IP来发送请求也是一个不错的选择。但是由于代理IP的性质,代理IP的可用性非常低,需要经常更新和验证。因此,本文介绍如何使用Python实现一个多线程的IP代理池,以便于我们在爬虫中使用。

二、IP池的实现

1. 收集代理IP

我们可以从各大免费IP代理网站上获取代理IP。具体获取方法可以通过网页分析获取代理IP的API接口,然后使用Python的requests库发送请求获取代理IP的列表。获取的代理IP可以通过保存到文件中或者直接保存到数据库中,在使用时需要进行解析。

下面是一个从站大爷免费代理ip网站获取代理IP的代码:

import requests
from lxml import etree

# 获取代理IP的函数
def get_proxies():
    url = 'https://www.zdaye.com/free/'
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}
    response = requests.get(url, headers=headers)
    html = etree.HTML(response.text)
    trs = html.xpath('//table[@id="ip_list"]//tr')[1:]  # 去除表头
    proxies = []
    for tr in trs:
        ip = tr.xpath('.//td[2]/text()')[0]  # IP
        port = tr.xpath('.//td[3]/text()')[0]  # 端口
        proxies.append(f'http://{ip}:{port}')
    return proxies
2. 验证代理IP可用性

代理IP的可用性很难保证,因此我们需要通过验证来筛选可用的代理IP。验证代理IP的方法可以通过发送一个请求来判断代理IP是否能够正常工作。如果代理IP无法正常工作,则需要将其从代理IP池中删除。下面是一个验证代理IP可用性的代码:

import requests

# 验证代理IP的可用性
def verify_proxies(proxy):
    url = 'http://httpbin.org/get'
    try:
        response = requests.get(url, proxies={'http': proxy, 'https': proxy}, timeout=5)
        if response.status_code == 200:
            return True
        else:
            return False
    except:
        return False
3. 搭建IP代理池

在IP池中,我们需要保存可用的代理IP。可以使用列表或者队列的方式来保存代理IP。当池中可用的代理IP数量低于一定阈值时,需要重新获取新的代理IP并验证,保证代理IP池中的可用代理数量不低于一定阈值。下面是一个简单的IP代理池的代码:

import threading
import time

class ProxyPool:
    def __init__(self, threshold=10):
        self.proxies = []  # 代理IP列表
        self.threshold = threshold  # 可用代理IP阈值
        self.lock = threading.Lock()  # 线程锁

    # 获取可用代理IP
    def get_proxy(self):
        while True:
            self.lock.acquire()  # 加锁
            try:
                if len(self.proxies) < self.threshold:
                    self.update_proxy()  # 更新代理IP
                if len(self.proxies) > 0:
                    proxy = self.proxies.pop()  # 弹出代理IP
                    if verify_proxies(proxy):  # 验证代理IP是否可用
                        print(f'使用代理IP: {proxy}')
                        return proxy
            finally:
                self.lock.release()  # 解锁

    # 更新代理IP
    def update_proxy(self):
        new_proxies = get_proxies()
        for proxy in new_proxies:
            self.lock.acquire()  # 加锁
            try:
                if proxy not in self.proxies:
                    self.proxies.append(proxy)
            finally:
                self.lock.release()  # 解锁

# 测试
p = ProxyPool(5)  # 初始化代理IP池,可用代理IP的阈值为5
while True:
    p.get_proxy()
    time.sleep(1)

三、多线程实现

在实际的网络爬虫中,需要同时发送多个请求,这就需要使用多线程来实现并发。多线程可以极大地提高爬虫的效率,尤其是在获取代理IP时,可以同时获取多个代理IP,从而进一步提高获取代理IP的速度。

下面是一个多线程的代理IP池的代码:

import threading
import time

class ProxyPool:
    def __init__(self, threshold=10):
        self.proxies = []  # 代理IP列表
        self.threshold = threshold  # 可用代理IP阈值
        self.lock = threading.Lock()  # 线程锁

    # 获取可用代理IP
    def get_proxy(self):
        while True:
            self.lock.acquire()  # 加锁
            try:
                if len(self.proxies) < self.threshold:
                    self.update_proxy()  # 更新代理IP
                if len(self.proxies) > 0:
                    proxy = self.proxies.pop()  # 弹出代理IP
                    if verify_proxies(proxy):  # 验证代理IP是否可用
                        print(f'使用代理IP: {proxy}')
                        return proxy
            finally:
                self.lock.release()  # 解锁

    # 更新代理IP
    def update_proxy(self):
        new_proxies = get_proxies()
        threads = []  # 线程列表
        for proxy in new_proxies:
            thread = threading.Thread(target=self.verify_proxy, args=(proxy,))  # 创建新的线程
            threads.append(thread)
            thread.start()  # 启动线程
        for thread in threads:
            thread.join()  # 等待线程结束

    # 验证代理IP的可用性
    def verify_proxy(self, proxy):
        if verify_proxies(proxy):
            self.lock.acquire()  # 加锁
            try:
                if proxy not in self.proxies:
                    self.proxies.append(proxy)
            finally:
                self.lock.release()  # 解锁

# 测试
p = ProxyPool(5)  # 初始化代理IP池,可用代理IP的阈值为5
while True:
    p.get_proxy()
    time.sleep(1)

在上面的代码中,我们在更新代理IP时,为每个代理IP创建了一个新的线程。这样可以让更新代理IP的操作并发处理,从而提高获取代理IP的效率。

四、代理IP的使用

在使用代理IP时,我们需要将代理IP配置在请求头中,从而让HTTP请求使用代理IP进行请求。下面是一个使用代理IP发送HTTP请求的代码:

import requests

p = ProxyPool(5)  # 初始化代理IP池,可用代理IP的阈值为5
while True:
    proxy = p.get_proxy()
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'}
    proxies = {'http': proxy, 'https': proxy}
    response = requests.get(url, headers=headers, proxies=proxies, timeout=5)
    print(response.text)
    time.sleep(1)

在上面的代码中,我们将获取的代理IP配置到requests库的proxies参数中,从而使用代理IP发送请求。

五、总结

在本文中,我们介绍了如何使用Python实现一个多线程的IP代理池,以便于我们在网络爬虫中使用代理IP。通过使用代理IP,我们可以增加发送请求的IP数量,从而提高爬虫的效率,同时降低被封禁的风险。但是由于代理IP的可用性较低,需要经常更新和验证。因此,需要定期获取新的代理IP,并验证其可用性。同时,在实际的网络爬虫中,需要同时发送多个请求,这就需要使用多线程来实现并发。

在使用代理IP时,我们需要将代理IP配置在HTTP请求头中,从而让HTTP请求使用代理IP进行请求。但是需要注意,代理IP并不是绝对可靠的,有可能代理IP的服务器在使用过程中会出现故障或者被封禁。因此,在网络爬虫中使用代理IP时,需要做好容错处理,当代理IP无法使用时,及时更换代理IP或者等待代理IP恢复使用。同时,还需要对代理IP的有效性进行定期检测和更新。

总之,通过使用一个多线程的IP代理池,可以大大提高网络爬虫的效率和稳定性,有效降低被封禁的风险,是网络爬虫中不可缺少的一个重要工具。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四、WebGPU Storage Buffers 存储缓冲区

四、WebGPU Storage Buffers 存储缓冲区 存储缓冲区 storage buffers 在许多方面 uniform buffers 缓冲区相似。如果我们所做的只是在JavaScript中将UNIFORM改为STORAGE&#xff0c;WGSL 中的 var 改为 var<storage,read>&#xff0c;上一节的示例代码同样可以运行并达到…

React +ts + babel+webpack

babel babel/preset-typescript 专门处理ts "babel/cli": "^7.17.6", "babel/core": "^7.17.8", "babel/preset-env": "^7.16.11", "babel/preset-react": "^7.16.7", "babel/preset…

vue3学习(二)--- ref和reactive

文章目录 ref1.1 ref将基础类型和对象类型数据转为响应式1.2 ref()获取id元素1.3 isRef reactive1.1 reactive()将引用类型数据转为响应式数据&#xff0c;基本类型无效1.2 ref和reactive的联系 toRef 和 toRefs1.1 如果原始对象是非响应式的就不会更新视图 数据是会变的 ref …

Redis高可用技术 二:主从复制、哨兵、Cluster集群

文章目录 1. 主从复制1.1 简介1.2 主从复制的作用1.3 主从复制的特性1.4 主从复制的工作原理1.4.1 全量复制1.4.2 增量复制 1.5 Redis主从同步策略 2. 搭建Redis主从复制2.1 前置准备2.2 配置master节点2.3 配置slave1-2节点2.4 主从复制结果验证 3. 哨兵模式3.1 简介3.2 哨兵的…

若依微服务部署,裸服务部署、docker部署、k8s部署

目录 前言windows 部署若依-微服务版本浏览器验证docker部署若依-微服务版本浏览器验证k8s部署若依-微服务版本浏览器验证总结 前言 环境&#xff1a;centos7、Win10 若依是一个合适新手部署练习的开源的微服务项目&#xff0c;本篇讲解Windows部署若依微服务、docker部署若依…

【鼠标右键菜单添加用VSCode打开文件或文件夹】

鼠标右键菜单添加用VSCode打开文件或文件夹 演示效果如下&#xff1a; 右击文件 或右击文件夹 或在文件夹内空白处右击 方法一&#xff1a;重装软件 重装软件&#xff0c;安装时勾选如图所示方框&#xff08;如果登录的有账号保存有配置信息可以选择重装软件&#xff0c…

YOLOv7暴力涨点:Gold-YOLO,遥遥领先,超越所有YOLO | 华为诺亚NeurIPS23

💡💡💡本文独家改进:提出了全新的信息聚集-分发(Gather-and-Distribute Mechanism)GD机制,Gold-YOLO,替换yolov7 head部分 实现暴力涨点 Gold-YOLO | 亲测在多个数据集能够实现大幅涨点,适用各个场景的涨点 收录: YOLOv7高阶自研专栏介绍: http://t.csdnim…

49位主播带货破亿,单品直播销量100万+,9月的黑马都是谁?

9月&#xff0c;抖音电商开始为下半年重要的营销节点做出筹备&#xff0c;不仅发起抖音中秋好礼季&#xff0c;还抢先发布双11品牌玩法攻略&#xff0c;活跃平台的消费氛围。 那么&#xff0c;9月有哪些主播表现突出&#xff0c;哪些商品在畅销&#xff0c;哪些达人的粉丝数飙升…

【数据结构与算法】如何对快速排序进行细节优化以及实现非递归版本的快速排序?

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;国庆长假结束了&#xff0c;无论是工作还是学习都该回到正轨上来了&#xff0c;从今天开始恢复正常的更新频率&#xff0c;今天为大家带来的内容…

将nginx注册为Windows系统服务

文章目录 1、使用nssm小工具2、使用winsw小工具2.1、下载2.2、用法2.3、重命名2.4、创建配置文件2.4.1、xml文件2.4.2、config文件&#xff08;该文件可省略&#xff09; 2.5、最终文件2.6、安装与卸载 1、使用nssm小工具 该方法最简单 首先&#xff0c;下载nssm小工具&#…

C语言——二周目——字符串与内存库函数总结

目录 一、字符串函数 1.求字符串长度——strlen 模拟实现 2.字符串拷贝函数——strcpy/strncpy 3.字符串追加函数——strcat/strncat 4.字符串比较函数——strcmp/strncmp 5.字符串查找函数——strstr 6.字符串分割函数——strtok 二、内存操作函数 1.内存拷贝函数—…

每日leetcode_2441

Leetcode每日一题_2441 记录自己的成长&#xff0c;加油。 题目 解题 class Solution {public int findMaxK(int[] nums) {int k -1;Set<Integer> set new HashSet<Integer>();for (int x : nums) {set.add(x);}for (int x : nums) {if (set.contains(-x)) {k …

linux 分区 添加 挂载centos挂载 Microsoft basic

​ 一 背景 es 忽然写不进去了 报错 TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark查看发现 磁盘已经满了 2T 的磁盘已经使用完了 ​ fdisk -l 查看原来磁盘有64000G 有64T 装机的人只分区了2T,白白浪费58T. 二 添加分区 利用剩余的空间 1添加分区 添…

光伏发电站并网新能源消纳数据采集监控监测方案

全市分布式光伏大数据平台&#xff0c;上报省级能源大数据中心。光伏电站实时运行数据&#xff1a;包括逆变器运行数据和状态、样板逆变器实时出力曲线&#xff0c;光伏电站并网点实际功率&#xff0c;气象监测数据&#xff0c;数据实时采集&#xff0c;采集频率根据光伏电站实…

Pytorch之EfficientNetV2图像分类

文章目录 前言一、EfficientNet V21. 网络简介2. EfficientNetV1弊端&#x1f947;训练图像的尺寸很大时&#xff0c;训练速度非常慢&#x1f948;在网络浅层中使用Depthwise convolutions速度会很慢&#x1f949;同等的放大每个stage是次优的 3.NAS Search4. Progressive Lear…

【C++】Vector -- 详解

一、vector的介绍及使用 1、vector的介绍 https://cplusplus.com/reference/vector/vector/ vector 是表示可变大小数组的序列容器。 就像数组一样&#xff0c;vector 也采用的连续存储空间来存储元素。也就是意味着可以采用下标对 vector 的元素进行访问&#xff0c;和数组一…

华天OA任意文件上传漏洞 复现

文章目录 华天OA任意文件上传漏洞 复现0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 华天OA任意文件上传漏洞 复现 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播…

整理笔记——推挽输出、开漏输出

在使用MCU时&#xff0c;常看到配置IO口为推挽输出、开漏输出&#xff0c;以STM32为例&#xff0c;IO口有一下集中模式&#xff0c;单片机的内部电路简化图如下&#xff1a; 1.推挽输出 2.开漏输出 3.复用推挽输出 4.复用开漏输出 一、推挽输出 推挽电路的示意图&#xff1a; …

Linux系统常用指令篇---(完)

Linux系统常用指令篇—(完) 1.时间相关的指令 date显示 date 指定格式显示时间&#xff1a; date %Y:%m:%d date 用法&#xff1a; date [OPTION]… [FORMAT] 1.在显示方面&#xff0c;使用者可以设定欲显示的格式&#xff0c;格式设定为一个加号后接数个标记&#xff0c;其…

【AI】深度学习——前馈神经网络——全连接前馈神经网络

文章目录 1.1 全连接前馈神经网络1.1.1 符号说明超参数参数活性值 1.1.2 信息传播公式通用近似定理 1.1.3 神经网络与机器学习结合二分类问题多分类问题 1.1.4 参数学习矩阵求导链式法则更为高效的参数学习反向传播算法目标计算 ∂ z ( l ) ∂ w i j ( l ) \frac{\partial z^{…