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


    目录

    一、前言

    二、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的代码:

    1. import requests
    2. from lxml import etree
    3. # 获取代理IP的函数
    4. def get_proxies():
    5.     url = 'https://www.zdaye.com/free/'
    6.     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'}
    7.     response = requests.get(url, headers=headers)
    8.     html = etree.HTML(response.text)
    9.     trs = html.xpath('//table[@id="ip_list"]//tr')[1:]  # 去除表头
    10.     proxies = []
    11.     for tr in trs:
    12.         ip = tr.xpath('.//td[2]/text()')[0]  # IP
    13.         port = tr.xpath('.//td[3]/text()')[0]  # 端口
    14.         proxies.append(f'http://{ip}:{port}')
    15.     return proxies
    2. 验证代理IP可用性

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

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

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

    1. import threading
    2. import time
    3. class ProxyPool:
    4.     def __init__(self, threshold=10):
    5.         self.proxies = []  # 代理IP列表
    6.         self.threshold = threshold  # 可用代理IP阈值
    7.         self.lock = threading.Lock()  # 线程锁
    8.     # 获取可用代理IP
    9.     def get_proxy(self):
    10.         while True:
    11.             self.lock.acquire()  # 加锁
    12.             try:
    13.                 if len(self.proxies) < self.threshold:
    14.                     self.update_proxy()  # 更新代理IP
    15.                 if len(self.proxies) > 0:
    16.                     proxy = self.proxies.pop()  # 弹出代理IP
    17.                     if verify_proxies(proxy):  # 验证代理IP是否可用
    18.                         print(f'使用代理IP: {proxy}')
    19.                         return proxy
    20.             finally:
    21.                 self.lock.release()  # 解锁
    22.     # 更新代理IP
    23.     def update_proxy(self):
    24.         new_proxies = get_proxies()
    25.         for proxy in new_proxies:
    26.             self.lock.acquire()  # 加锁
    27.             try:
    28.                 if proxy not in self.proxies:
    29.                     self.proxies.append(proxy)
    30.             finally:
    31.                 self.lock.release()  # 解锁
    32. # 测试
    33. p = ProxyPool(5)  # 初始化代理IP池,可用代理IP的阈值为5
    34. while True:
    35.     p.get_proxy()
    36.     time.sleep(1)

    三、多线程实现

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

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

    1. import threading
    2. import time
    3. class ProxyPool:
    4.     def __init__(self, threshold=10):
    5.         self.proxies = []  # 代理IP列表
    6.         self.threshold = threshold  # 可用代理IP阈值
    7.         self.lock = threading.Lock()  # 线程锁
    8.     # 获取可用代理IP
    9.     def get_proxy(self):
    10.         while True:
    11.             self.lock.acquire()  # 加锁
    12.             try:
    13.                 if len(self.proxies) < self.threshold:
    14.                     self.update_proxy()  # 更新代理IP
    15.                 if len(self.proxies) > 0:
    16.                     proxy = self.proxies.pop()  # 弹出代理IP
    17.                     if verify_proxies(proxy):  # 验证代理IP是否可用
    18.                         print(f'使用代理IP: {proxy}')
    19.                         return proxy
    20.             finally:
    21.                 self.lock.release()  # 解锁
    22.     # 更新代理IP
    23.     def update_proxy(self):
    24.         new_proxies = get_proxies()
    25.         threads = []  # 线程列表
    26.         for proxy in new_proxies:
    27.             thread = threading.Thread(target=self.verify_proxy, args=(proxy,))  # 创建新的线程
    28.             threads.append(thread)
    29.             thread.start()  # 启动线程
    30.         for thread in threads:
    31.             thread.join()  # 等待线程结束
    32.     # 验证代理IP的可用性
    33.     def verify_proxy(self, proxy):
    34.         if verify_proxies(proxy):
    35.             self.lock.acquire()  # 加锁
    36.             try:
    37.                 if proxy not in self.proxies:
    38.                     self.proxies.append(proxy)
    39.             finally:
    40.                 self.lock.release()  # 解锁
    41. # 测试
    42. p = ProxyPool(5)  # 初始化代理IP池,可用代理IP的阈值为5
    43. while True:
    44.     p.get_proxy()
    45.     time.sleep(1)

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

    四、代理IP的使用

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

    1. import requests
    2. p = ProxyPool(5)  # 初始化代理IP池,可用代理IP的阈值为5
    3. while True:
    4.     proxy = p.get_proxy()
    5.     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'}
    6.     proxies = {'http': proxy, 'https': proxy}
    7.     response = requests.get(url, headers=headers, proxies=proxies, timeout=5)
    8.     print(response.text)
    9.     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代理池,可以大大提高网络爬虫的效率和稳定性,有效降低被封禁的风险,是网络爬虫中不可缺少的一个重要工具。

  • 相关阅读:
    单商户商城系统功能拆解03—店铺主页编辑
    Slim GAIN(SGAIN)介绍及代码实现——基于生成对抗网络的缺失数据填补
    java计算机毕业设计-酒店管理系统-源码+mysql数据库+系统+lw文档+部署
    【2023年11月第四版教材】第16章《采购管理》(第二部分)
    Verilog语句
    canvas画一个笑脸和画一个三角形
    5款好用的工具软件推荐给你
    Windows Server FTP文件服务器安装和配置
    Runc 漏洞(CVE-2021-30465)离线修复
    0066 线程基础
  • 原文地址:https://blog.csdn.net/wq10_12/article/details/133699608