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

前言:

效果图:

对于网络上的一些免费代理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会更新的,一般都是比较不错的网站!!!    

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

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

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

相关文章

庖丁解牛:NIO核心概念与机制详解 01

文章目录 Pre输入/输出Why NIO流与块的比较通道和缓冲区概述什么是缓冲区&#xff1f;缓冲区类型什么是通道&#xff1f;通道类型 NIO 中的读和写概述Demo : 从文件中读取1. 从FileInputStream中获取Channel2. 创建ByteBuffer缓冲区3. 将数据从Channle读取到Buffer中 Demo : 写…

照片+制作照片书神器,效果太棒了!

随着数码相机的普及&#xff0c;越来越多的人喜欢用照片记录生活点滴。而制作一本精美的照片书&#xff0c;不仅可以保存珍贵的回忆&#xff0c;还能让照片更加美观。今天&#xff0c;就为大家推荐一款制作照片书神器&#xff0c;让您的回忆更加完美&#xff01; 一、产品介绍 …

光敏传感器模块(YH-LDR)

目录 1. YH-LDR模块说明 1.1 简介 1.2 YH-LDR 模块的引脚说明 1.3 LDR 传感器工作原理与输出特性 2. 使用单片机系统控制 YH-LDR 模块 2.1 通用控制说明 1. YH-LDR模块说明 1.1 简介 YH-LDR 是野火设计的光强传感器&#xff0c;使用一个光敏电阻作为采集源&#x…

用cmd看星球大战大电影,c++版本全集星球大战,超长多细节

用cmd看星球大战 最近发现了一个有趣的指令。 是不是感觉很insteresting呢 教程 进入控制面板&#xff0c;点击系统与安全 然后&#xff0c;进入以后&#xff0c;点击启用或关闭 Windows 功能 启用Telnet Client并点击确定 用快捷键winr打开我们的cmd 输入指令 telnet towe…

【diffuser系列】ControlNet

ControlNet: TL;DRControl TypeStableDiffusionControlNetPipeline1. Canny ControlNet1.1 模型与数据加载1.2 模型推理1.3 DreamBooth微调 2. Pose ControlNet2.1 数据和模型加载2.2 模型推理 ControlNet: TL;DR ControlNet 是在 Lvmin Zhang 和 Maneesh Agrawala 的 Adding …

03 前后端数据交互【小白入门SpringBoot + Vue3】

项目笔记&#xff0c;教学视频来源于B站青戈 https://www.bilibili.com/video/BV1H14y1S7YV 前两个笔记。是把前端页面大致做出来&#xff0c;接下来&#xff0c;把后端项目搞一下。 后端项目&#xff0c;使用IDEA软件、jdk1.8、springboot2.x 。基本上用的是稳定版。 还有My…

【算法萌新闯力扣】:旋转字符串

力扣热题&#xff1a;796.旋转字符串 开篇 今天下午刷了6道力扣算法题&#xff0c;选了一道有多种解法的题目与大家分享。 题目链接:796.旋转字符串 题目描述 代码思路 完全按照题目的要求&#xff0c;利用StringBuffer中的方法对字符串进行旋转&#xff0c;寻找相同的一项 …

月子会所信息展示服务预约小程序的作用是什么

传统线下门店经营只依赖自然流量咨询或简单的线上付费推广是比较低效的&#xff0c;属于靠“天”吃饭&#xff0c;如今的年轻人学历水平相对较高&#xff0c;接触的事物或接受的思想也更多更广&#xff0c;加之生活水平提升及互联网带来的长期知识赋能&#xff0c;因此在寻找/咨…

HC-SR501传感器制作一个报警系统

接线图&#xff1a; 引脚连接&#xff1a; 1. 将 PIR 信号引脚连接到 arduino 数字 引脚 13。 2. 将 PIR V 引脚连接 到 arduino 5v 引脚。 3. 将 PIR GND 引脚连接到 arduino GND 引脚。 4. 将arduino数字 引脚12连接 到220欧姆电阻&#xff0c;并将该电阻连接到 LED V …

SPASS-距离分析

基本概念 距离分析是对观测量之间相似或不相似程度的一种测度&#xff0c;是计算一对观测量之间的广义距离。这些相似性或距离测度可以用于其他分析过程&#xff0c;例如因子分析、聚类分析或多维定标分析&#xff0c;有助于分析复杂的数据集。 统计原理 不相似性测度 对定距…

Java面向对象(高级)-- 单例(Singleton)设计模式

文章目录 一、单例设计模式&#xff08;1&#xff09; 设计模式概述&#xff08;2&#xff09; 何为单例模式&#xff08;3&#xff09; 实现思路&#xff08;4&#xff09; 单例模式的两种实现方式1. 饿汉式2. 懒汉式3. 饿汉式 vs 懒汉式 &#xff08;5&#xff09; 单例模式的…

Linux调试器:gdb的使用

我们知道在Visual Studio2022中&#xff0c;我们可以对编好的代码进行调试来分析dug的位置&#xff0c;那Linux环境下如何进行程序的调试呢&#xff1f;那就是使用Linux调试器&#xff1a;gdb。 目录 1.背景 2. 开始使用 1.背景 程序的发布方式有两种&#xff0c;debug模式…

基于51单片机水位监测控制报警仿真设计( proteus仿真+程序+设计报告+讲解视频)

这里写目录标题 &#x1f4a5;1. 主要功能&#xff1a;&#x1f4a5;2. 讲解视频&#xff1a;&#x1f4a5;3. 仿真&#x1f4a5;4. 程序代码&#x1f4a5;5. 设计报告&#x1f4a5;6. 设计资料内容清单&&下载链接&#x1f4a5;[资料下载链接&#xff1a;](https://doc…

Docker中的RabbitMQ已经启动运行,但是管理界面打不开

文章目录 前言一、解决方法方法一方法二 总结 前言 肯定有好多小伙伴在学习RabbitMQ的过程中&#xff0c;发现镜像运行&#xff0c;但是我的管理界面怎么进不去&#xff0c;或者说我第一天可以进去&#xff0c;怎么第二天进不去了&#xff0c;为什么每次重新打开虚拟机都进不去…

【沐风老师】3DMAX一键云生成器插件使用教程

3DMAX云生成器插件使用教程 3DMAX云生成器插件&#xff0c;是一款将物体变成云的简单而富有创意的工具。该工具通过在物体周围创建粒子结合材质&#xff0c;最终形成渲染后的云的效果。 【支持版本】 3dMax2018 – 2023 默认的扫描线渲染器 【安装方法】 1.复制“安装文件”…

PyQt(学习笔记)

学习资料来源&#xff1a; PyQt快速入门——b站王铭东老师 PyQt&#xff08;学习笔记&#xff09; Pycharm环境准备运行第一个程序QPushButtonQLabelQLineEdit调整窗口大小、位置、图标布局信号与槽PyQt引入多线程 Pycharm环境准备 新建环境——添加PyQt5模块——验证版本 如果…

python表白程序,无法拒绝

# codinggbk import tkinter as tk import random import tkinter.messagebox as messagebox# 创建主窗口并隐藏 root tk.Tk() root.attributes(-alpha, 0) # 设置主窗口为不可见# 表白内容 message "做我女朋友好不好&#xff1f;"# 获取屏幕宽度和高度 screen_w…

Java读写Jar

Java提供了读写jar的类库Java.util.jar&#xff0c;Java获取解析jar包的工具类如下&#xff1a; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; import java.util.HashMap; import …

Linux:补充一些常用命令

Linux&#xff1a;补充一些常用命令 1. free -h2. df -lh3. du -sh *4. uname -a5. which6. mvn install 编译打包7. find -name *.jar8. cd -9. nohup java -jar *.jar &10. ps -ef|grep java11. netstat -ntlp 1. free -h free 命令显示系统使用和空闲的内存情况&#x…