redis+python 建立免费http-ip代理池;验证+留接口

news2024/12/22 6:31:21

前言:

效果图:

对于网络上的一些免费代理ip,http的有效性还是不错的;但是,https的可谓是凤毛菱角; 正巧,有一个web可以用http访问,于是我就想到不如直接拿着免费的HTTP代理去做这个!

思路:

1.单页获取ip+port+time (获取time主要是为了后面使用的时候,依照时效可以做文章)

2.整页验证(一个page里面可能有N个ip,通过验证判断有多少个有效ip可以使用)----这里需要使用多线程进行验证;否则,光验证那么多ip都要耗掉不少时间!

import logging
from bs4 import BeautifulSoup
from datetime import datetime, timedelta
import time
import requests
from concurrent.futures import ThreadPoolExecutor

# 配置日志记录器
logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s',
                    filename='get_ip_error.log')

time_threshold = 15  # 录入IP的时间和当前时间差阈值小于等于15分钟时进行检查
page_valid = 3  # 当每次超过X个有效IP时返回


url_kuai= 'http://www.kuaidaili.com/free/inha/'
#请求头
headers = {

    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
}


def check_proxy(p):
    '''
    多线程检查代理IP的有效性
    :param p: 代理IP列表[]
    :return: 有效的代理IP列表
    '''
    url = "http://httpbin.org/ip"  # 用于测试代理IP有效性的网站
    valid_proxies = []

    def check_single_proxy(proxy):
        proxies = {
            "http": f"http://{proxy['ip']}:{proxy['port']}",
            # "https": f"https://{proxy['ip']}:{proxy['port']}"
        }
        try:
            response = requests.get(url, proxies=proxies, timeout=1.5)
            if response.ok:
                valid_proxies.append(proxy)
        except requests.exceptions.RequestException as e:
            pass

    # 开启多线程检查
    with ThreadPoolExecutor() as executor:
        executor.map(check_single_proxy, p)

    return valid_proxies




def get_kuaidaili(page):
    '''
    获取89ip的代理IP列表
    :param page: 页码
    :return: 有效的代理IP列表和页码
    '''

    try:
        valid_ip_list = []

        while page <= 25:#在这里,只有当有效ip数量>=3的时候,他才会停止;否则,就会不停增加page去爬取;
            full_url = url_kuai+str(page)   # 根据页码构建URL
            print('当前正在爬取网页--->:', full_url)
            response = requests.get(full_url,headers=headers)
            if response.ok:
                html = response.text
                soup = BeautifulSoup(html, 'html.parser')
                table = soup.find('table', class_='table table-b table-bordered table-striped')
                tbody = table.find('tbody')

                # if time_diff(tbody,6): #如果时间差在XX分钟以内,就开始检验ip(第6个td是时间) 他更新不快,所以不能用时间去筛选
                valid_proxies = tbody_add_proxy(tbody,6)  # 获取tbody的数据(time的位置=6)

                if valid_proxies is not None and len(valid_proxies) > 0:
                    valid_ip_list.extend(valid_proxies)


                    if len(valid_ip_list) >= page_valid:  # 有效 IP 数量大于等于 page_valid 就停止爬取
                        break

            page += 1
        else:
            page=0

            #当page>25的时候,page=1重新开始
        return valid_ip_list, page



    except requests.exceptions.RequestException as e:
        print(f"爬取异常: {e}")
        return valid_ip_list, page







def time_diff(table,much):
    '''
    查询当前页的IP更新时间,判断是否小于等于阈值 time_threshold,若是返回True
    :param table: IP表格
    :return: 时间是否小于等于阈值
    '''
    rows = table.find_all('tr')

    given_time = datetime.strptime(rows[0].find_all('td')[much].text.strip(), "%Y/%m/%d %H:%M:%S")
    current_time = datetime.now()
    time_difference = current_time - given_time

    return time_difference <= timedelta(minutes=time_threshold)


def tbody_add_proxy(tbody,much):
    '''
    提取代理IP和端口信息,并将其构建为列表形式
    :param tbody: 表格内容
    :return: 代理IP和端口的列表
    '''
    proxy_list = []

    rows = tbody.find_all('tr')
    for row in rows:
        proxy = {}
        cells = row.find_all('td')
        proxy["ip"] = cells[0].text.strip()
        proxy["port"] = cells[1].text.strip()
        proxy["time"] = cells[much].text.strip()
        proxy_list.append(proxy)
    return check_proxy(proxy_list)  #返回有效的ip[(list)]







3.存入redis(我需要考虑的是:ip是否重复了?ip提取的时候什么时候进行补充?)

import redis
import json

# 创建连接池
pool_config = {
    'host': 'localhost',
    'port': 6379,
    'db': 0,
    'max_connections': 10,
    'decode_responses': True,
    'encoding': 'utf-8'
}

# 创建redis连接池
pool = redis.ConnectionPool(**pool_config)


def add_to_sorted_set(ip):
    '''
    将IP添加到有序集合中,确保唯一性
    :param ip: IP信息的字典
    '''
    r = redis.Redis(connection_pool=pool)
    ip_de = json.dumps(ip)

    # 判断IP在有序集合中是否已存在
    if not r.zscore('valid', ip_de):
        r.zadd('valid', {ip_de: 0})



def find_valid_ip():
    '''
    获取当前Redis中有效IP的数量
    :return: 有效IP的数量
    '''
    r = redis.Redis(connection_pool=pool)
    count = r.zcard('valid') #因为是有序集合,所以需要用zcard
    if count is None:
        return 0
    return count

def pop_from_sorted_set():
    '''
    从有序集合中弹出一个元素(按添加顺序)
    :return: 弹出的IP信息字典
    '''
    r = redis.Redis(connection_pool=pool)
    ip_de = r.zrange('valid', 0, 0)[0]

    # 从有序集合中移除已弹出的元素
    r.zrem('valid', ip_de)

    return json.loads(ip_de)






4.如何合理去运行ip的爬取?


from redis_task import redis_task as redis,get_ip

import time
import requests





# 配置日志记录器





import time

def ip_control():
    '''
    1.检查redis里面是否有足够的有效ip(>10)
        - 足够
            - 达到目标数量(例如 20)后停止更新
            - 休眠一段时间后再继续更新
        - 不足够
            - 开始从 check_url(url_parse_dict) 获取新的有效ip
                - 新的ip如果与现有的 redis ip 重复,则不放入
                - 不重复则放入,直到 redis 有效 ip 数量达到目标数量

    '''
    target_count = 20  # 目标有效 IP 数量
    current_page = 1  # 保存当前页码
    while True:
        count = redis.find_valid_ip()
        print('*******************************************************************')
        print(f"目前redis里面有{count}个有效ip")

        if count < target_count:
            valid_ips, page = get_ip.get_kuaidaili(current_page)  # 使用 current_page
            print(f"当前返回的页码:{page}")


            if valid_ips:
                print(f"有效代理IP有:{len(valid_ips)}")

                redis.add_to_sorted_set(valid_ips)  #必须添加有序集合,确保唯一性 以及后期提取时可以自动移除
                current_page =page+1  # 更新 current_page,使其递增
            else:
                #此时是redis内的有效ip没达到20个
                print('此时没有达到20个,怎么办?')

        else:
            print(f"已经达到目标数量:{target_count},30秒后再更新")
            time.sleep(10)




ip_control()

最后:

当然,此时的`快代理`已经有点不行了.经过我的测试,1~25page 平局只有 8个左右ip有效!  于是需要添加其他的网站------>那么什么是好的免费ip网站呢?  就是一小时内,他的免费ip会更新的,一般都是比较不错的网站!!!    

把这代码搞懂了,需要"素材"的可以私

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

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

相关文章

矩阵运算_矩阵的协方差矩阵/两个矩阵的协方差矩阵_求解详细步骤示例

1. 协方差矩阵定义 在统计学中&#xff0c;方差是用来度量单个随机变量的离散程度&#xff0c;而协方差则一般用来刻画两个随机变量的相似程度。 参考&#xff1a; 带你了解什么是Covariance Matrix协方差矩阵 - 知乎 2. 协方差矩阵计算过程 将输入数据A进行中心化处理得到A…

马斯克的SpaceX星舰又炸了!发射不久后失联自毁

就在几小时前&#xff0c;马斯克旗下SpaceX 发射了有史以来最强大的星舰&#xff0c;但在发射后不久发生爆炸。 在这次发射尝试中&#xff0c;星舰一二级成功进行了分离&#xff0c;但二级助推器和星舰都发生了快速意料之外的解体。在发射半小时后&#xff0c;SpaceX 宣布二级自…

7个最佳开源免费库存/仓库管理系统(WMS)

库存/仓库管理软件是一种用于帮助企业管理库存、仓储位置和交付过程的软件系统。这种类型的软件对于拥有大量库存和多个仓库的企业非常有用。 库存/仓库管理软件的作用包括以下几个方面&#xff1a; &#xff08;1&#xff09;减少库存节约成本 通过跟踪库存水平和存储位置&…

从零开始:Rust环境搭建指南

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将一起探讨如何从零开始搭建Rust开发环境。 Rust环境搭建概览 Rust是一种系统编程语言&#xff0c;以其安全性、并发性和性能闻名。搭建Rust环境是学习和使用这一语言的第一步。 第一步&#xff1a;安装Rust Rust的…

二维码智慧门牌管理系统升级解决方案:查询功能大提升,让地址查找变得轻松便捷!

文章目录 前言一、支持地址名称、小区等信息进行模糊查询二、支持地图上绘制多边形、圆形、矩形进行范围查询三、高效的数据处理能力&#xff0c;保证查询速度四、灵活的应用场景&#xff0c;满足多种需求 前言 随着科技的快速发展和城市化的加速推进&#xff0c;传统的门牌管…

六.Linux远程登录

1.说明&#xff1a;公司开发的时候&#xff0c;具体的应用场景是这样的 1.linux服务器是开发小组共享 2.正式上线的项目是运行在公网 3.因此程序员需要远程登录到Linux进行项目管理或者开发 4.画出简单的网络拓扑示意图(帮助理解) 5.远程登录客户端有Xshell6、Xftp6&#xff0…

MyISAM和innoDB两种引擎的对比

innoDB 3.23就有了innoDB引擎&#xff0c;5.5成为了默认引擎&#xff0c;支持外键 是一种事务型引擎&#xff0c;可以保证完整提交和回滚 更新、删除比较多的场景&#xff0c;推荐使用innoDB 不过innoDB对内存要求高&#xff0c;因为索引和数据存到一个表了&#xff1b;写操作…

7.22 SpringBoot项目实战【收藏 和 取消收藏】

文章目录 前言一、编写控制器二、编写服务层三、Postman测试最后前言 本系统还支持 收藏图书,就是对心仪的书加一下收藏,大家都懂,这是一个很常见的功能。 那么我们来看看怎么来做,先分析一下:【一个人】对【一本书】只需【收藏一次】,但可以【收藏N本】不同的书,收藏…

数据结构之链表练习与习题详细解析

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 数据结构初阶 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.前言 2.习题解…

【LeetCode刷题-树】--654.最大二叉树

654.最大二叉树 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 1.创建一个根节点&#xff0c;其值为 nums 中的最大值。 2.递归地在最大值 左边 的 子数组前缀上 构建左子树。 3.递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回…

庖丁解牛:NIO核心概念与机制详解 03 _ 缓冲区分配、包装和分片

文章目录 Pre概述缓冲区分配和包装 &#xff08;allocate 、 wrap&#xff09;缓冲区分片 (slice)缓冲区份片和数据共享只读缓冲区 &#xff08;asReadOnlyBuffer&#xff09;直接和间接缓冲区内存映射文件 I/O将文件映射到内存 Pre 庖丁解牛&#xff1a;NIO核心概念与机制详解…

开源供应链管理系统 S2B2B2C系统方案及源码输出

这个开源供应链管理系统提供针对企业供应链管理需求的开放源代码解决方案。通过开源供应链管理系统&#xff0c;企业能够实现对供应商、进销存和物流配送等方面的全面管理和优化&#xff0c;涵盖了从供应商选择到门店到消费者服务交付的整个流程。开源系统使企业能够根据自身需…

ssm+vue的高校疫情防控管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的高校疫情防控管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

Network(四)NAT实现方式与VRRP概述

一 NAT 1 NAT概述 &#xff08;1&#xff09;NAT的作用 Network Address Translation&#xff0c;网络地址转换 通过将内部网络的私有IP地址转换成全球唯一的公网IP地址使内部网络可以连接到互联网。 &#xff08;2&#xff09;私有IP地址分类 A类10.0.0.0~10.255.255.…

【LeetCode刷题-树】--998.最大二叉树II

998.最大二叉树II /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

8.1 Windows驱动开发:内核文件读写系列函数

在应用层下的文件操作只需要调用微软应用层下的API函数及C库标准函数即可&#xff0c;而如果在内核中读写文件则应用层的API显然是无法被使用的&#xff0c;内核层需要使用内核专有API&#xff0c;某些应用层下的API只需要增加Zw开头即可在内核中使用&#xff0c;例如本章要讲解…

CICD 持续集成与持续交付——gitlab

部署 虚拟机最小需求&#xff1a;4G内存 4核cpu 下载&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 安装依赖性 [rootcicd1 ~]# yum install -y curl policycoreutils-python openssh-server perl[rootcicd1 ~]# yum install -y gitlab-ce-15.9.3-ce.0…

图像倾斜角度求取-Radon变换

Radon算法 Radon&#xff08;拉东&#xff09;算法是一种通过定方向投影叠加&#xff0c;找到最大投影值时角度&#xff0c;从而确定图像倾斜角度的算法。具体过程如图所示 图1 Radon变换算法 Radon计算示例 对于纹理方向明显的图像&#xff0c;如图2所示&#xff0c;可以通…

GitHub如何删除仓库

GitHub如何删除仓库 删除方法第一步第二步第三步 删除方法 第一步 在仓库的界面选择Settings 第二步 选择General,页面拉到最后。 第三步 删除仓库。

程序员开发者神器:10个.Net开源项目

今天一起盘点下&#xff0c;8月份推荐的10个.Net开源项目&#xff08;点击标题查看详情&#xff09;。 1、基于C#开发的适合Windows开源文件管理器 该项目是一个基于C#开发、开源的文件管理器&#xff0c;适用于Windows&#xff0c;界面UI美观、方便轻松浏览文件。此外&#…