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


    前言:

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

    思路:

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

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

    1. import logging
    2. from bs4 import BeautifulSoup
    3. from datetime import datetime, timedelta
    4. import time
    5. import requests
    6. from concurrent.futures import ThreadPoolExecutor
    7. # 配置日志记录器
    8. logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s',
    9. filename='get_ip_error.log')
    10. time_threshold = 15 # 录入IP的时间和当前时间差阈值小于等于15分钟时进行检查
    11. page_valid = 3 # 当每次超过X个有效IP时返回
    12. url_kuai= 'http://www.kuaidaili.com/free/inha/'
    13. #请求头
    14. headers = {
    15. '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',
    16. }
    17. def check_proxy(p):
    18. '''
    19. 多线程检查代理IP的有效性
    20. :param p: 代理IP列表[]
    21. :return: 有效的代理IP列表
    22. '''
    23. url = "http://httpbin.org/ip" # 用于测试代理IP有效性的网站
    24. valid_proxies = []
    25. def check_single_proxy(proxy):
    26. proxies = {
    27. "http": f"http://{proxy['ip']}:{proxy['port']}",
    28. # "https": f"https://{proxy['ip']}:{proxy['port']}"
    29. }
    30. try:
    31. response = requests.get(url, proxies=proxies, timeout=1.5)
    32. if response.ok:
    33. valid_proxies.append(proxy)
    34. except requests.exceptions.RequestException as e:
    35. pass
    36. # 开启多线程检查
    37. with ThreadPoolExecutor() as executor:
    38. executor.map(check_single_proxy, p)
    39. return valid_proxies
    40. def get_kuaidaili(page):
    41. '''
    42. 获取89ip的代理IP列表
    43. :param page: 页码
    44. :return: 有效的代理IP列表和页码
    45. '''
    46. try:
    47. valid_ip_list = []
    48. while page <= 25:#在这里,只有当有效ip数量>=3的时候,他才会停止;否则,就会不停增加page去爬取;
    49. full_url = url_kuai+str(page) # 根据页码构建URL
    50. print('当前正在爬取网页--->:', full_url)
    51. response = requests.get(full_url,headers=headers)
    52. if response.ok:
    53. html = response.text
    54. soup = BeautifulSoup(html, 'html.parser')
    55. table = soup.find('table', class_='table table-b table-bordered table-striped')
    56. tbody = table.find('tbody')
    57. # if time_diff(tbody,6): #如果时间差在XX分钟以内,就开始检验ip(第6个td是时间) 他更新不快,所以不能用时间去筛选
    58. valid_proxies = tbody_add_proxy(tbody,6) # 获取tbody的数据(time的位置=6)
    59. if valid_proxies is not None and len(valid_proxies) > 0:
    60. valid_ip_list.extend(valid_proxies)
    61. if len(valid_ip_list) >= page_valid: # 有效 IP 数量大于等于 page_valid 就停止爬取
    62. break
    63. page += 1
    64. else:
    65. page=0
    66. #当page>25的时候,page=1重新开始
    67. return valid_ip_list, page
    68. except requests.exceptions.RequestException as e:
    69. print(f"爬取异常: {e}")
    70. return valid_ip_list, page
    71. def time_diff(table,much):
    72. '''
    73. 查询当前页的IP更新时间,判断是否小于等于阈值 time_threshold,若是返回True
    74. :param table: IP表格
    75. :return: 时间是否小于等于阈值
    76. '''
    77. rows = table.find_all('tr')
    78. given_time = datetime.strptime(rows[0].find_all('td')[much].text.strip(), "%Y/%m/%d %H:%M:%S")
    79. current_time = datetime.now()
    80. time_difference = current_time - given_time
    81. return time_difference <= timedelta(minutes=time_threshold)
    82. def tbody_add_proxy(tbody,much):
    83. '''
    84. 提取代理IP和端口信息,并将其构建为列表形式
    85. :param tbody: 表格内容
    86. :return: 代理IP和端口的列表
    87. '''
    88. proxy_list = []
    89. rows = tbody.find_all('tr')
    90. for row in rows:
    91. proxy = {}
    92. cells = row.find_all('td')
    93. proxy["ip"] = cells[0].text.strip()
    94. proxy["port"] = cells[1].text.strip()
    95. proxy["time"] = cells[much].text.strip()
    96. proxy_list.append(proxy)
    97. return check_proxy(proxy_list) #返回有效的ip[(list)]

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

    1. import redis
    2. import json
    3. # 创建连接池
    4. pool_config = {
    5. 'host': 'localhost',
    6. 'port': 6379,
    7. 'db': 0,
    8. 'max_connections': 10,
    9. 'decode_responses': True,
    10. 'encoding': 'utf-8'
    11. }
    12. # 创建redis连接池
    13. pool = redis.ConnectionPool(**pool_config)
    14. def add_to_sorted_set(ip):
    15. '''
    16. 将IP添加到有序集合中,确保唯一性
    17. :param ip: IP信息的字典
    18. '''
    19. r = redis.Redis(connection_pool=pool)
    20. ip_de = json.dumps(ip)
    21. # 判断IP在有序集合中是否已存在
    22. if not r.zscore('valid', ip_de):
    23. r.zadd('valid', {ip_de: 0})
    24. def find_valid_ip():
    25. '''
    26. 获取当前Redis中有效IP的数量
    27. :return: 有效IP的数量
    28. '''
    29. r = redis.Redis(connection_pool=pool)
    30. count = r.zcard('valid') #因为是有序集合,所以需要用zcard
    31. if count is None:
    32. return 0
    33. return count
    34. def pop_from_sorted_set():
    35. '''
    36. 从有序集合中弹出一个元素(按添加顺序)
    37. :return: 弹出的IP信息字典
    38. '''
    39. r = redis.Redis(connection_pool=pool)
    40. ip_de = r.zrange('valid', 0, 0)[0]
    41. # 从有序集合中移除已弹出的元素
    42. r.zrem('valid', ip_de)
    43. return json.loads(ip_de)

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

    1. from redis_task import redis_task as redis,get_ip
    2. import time
    3. import requests
    4. # 配置日志记录器
    5. import time
    6. def ip_control():
    7. '''
    8. 1.检查redis里面是否有足够的有效ip(>10)
    9. - 足够
    10. - 达到目标数量(例如 20)后停止更新
    11. - 休眠一段时间后再继续更新
    12. - 不足够
    13. - 开始从 check_url(url_parse_dict) 获取新的有效ip
    14. - 新的ip如果与现有的 redis ip 重复,则不放入
    15. - 不重复则放入,直到 redis 有效 ip 数量达到目标数量
    16. '''
    17. target_count = 20 # 目标有效 IP 数量
    18. current_page = 1 # 保存当前页码
    19. while True:
    20. count = redis.find_valid_ip()
    21. print('*******************************************************************')
    22. print(f"目前redis里面有{count}个有效ip")
    23. if count < target_count:
    24. valid_ips, page = get_ip.get_kuaidaili(current_page) # 使用 current_page
    25. print(f"当前返回的页码:{page}")
    26. if valid_ips:
    27. print(f"有效代理IP有:{len(valid_ips)}")
    28. redis.add_to_sorted_set(valid_ips) #必须添加有序集合,确保唯一性 以及后期提取时可以自动移除
    29. current_page =page+1 # 更新 current_page,使其递增
    30. else:
    31. #此时是redis内的有效ip没达到20个
    32. print('此时没有达到20个,怎么办?')
    33. else:
    34. print(f"已经达到目标数量:{target_count},30秒后再更新")
    35. time.sleep(10)
    36. ip_control()

    最后:

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

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

  • 相关阅读:
    (算法设计与分析)第三章动态规划-第一节1:动态规划基本思想、框架
    川西旅游网系统-前后端分离(前台vue 后台element UI,后端servlet)
    【代码】Android|获取存储权限并创建、存储文件
    基础架构开发-操作系统、编译器、云原生、嵌入式、ic
    偏执的非合格公司
    Cadence导入IBIS模型用于仿真
    java基础巩固18
    VGW在 Windows 平台上局域网就绪的旁路由器程序
    Qt 自定义event
    house of storm+堆SROP+orw
  • 原文地址:https://blog.csdn.net/m0_56758840/article/details/134479431