Python 抓取可用代理IP

问题描述

在做数据抓取的时候,经常会碰到有些网站对同一IP的访问频率做限制。遇到这种情况一般只有两种解决方案:

  1. 降低抓取频率。这种方法在数据变化不频繁,数据量不大的情况下还好,但是,如果数据变化频繁或者数据量庞大,此方法明显不能满足需求。
  2. 使用代理IP。抓取的过程中,经常更换代理IP,这种方法基本可以有效解决同一IP访问频率限制的问题。此方案的难点在于如何获取大量可用的代理IP。

代理IP获取

代理IP的获取途径基本也就两种:

  1. 购买付费代理IP。一般都是按使用时长和代理IP数收费,优点就是可靠性高。
  2. 使用免费代理。可以从免费代理网站获取,但是稳定性不好,绝大部分都会很快失效。

付费代理没什么好讲的,付款之后一般就可以拿到数据接口,程序里边直接调用即可。

下面讲一下免费代理IP的获取及筛选。这种出力不讨好的繁琐工作当然应该交给程序来自动完成。

这里以西刺代理为例讲一下获取https代理的分析过程并给出示例程序。

通过对页面请求进行分析,可以找到包含https代理的实际请求地址是: http://www.xicidaili.com/wn/{page},第一页page=1,第二页page=2...以此类推。西刺代理的IP每几分钟都会更新一次,所以每次只抓取前几页基本就可以了。

网络请求使用Python的requests库,页面解析使用pyquery。也可以使用urllib和beautifulSoup,不过个人感觉稍微麻烦一些。

废话不多说了,下面直接上程序,代码基于Python3编写,如果要在Python2下运行需要稍作修改。

"""
该程序用于从代理网站获取可用ip
使用方法1: 直接运行该文件,会在同目录下生成ips.txt文件,文件内包含可用的代理
使用方法2: 其他程序导入该文件,然后直接使用该文件内定义的全局变量'proxies'
"""
import random
import threading
import time
from concurrent import futures

import requests
from pyquery import PyQuery

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) \
                  Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2306.400 QQBrowser/9.5.10530.400'}
# 检测代理ip有效性的网站
CHECK_URL = 'https://ip.cn'
# 抓取地址(西刺代理)
FETCH_URL = 'http://www.xicidaili.com/wn/{}'
# 抓取页数,每页100条
PAGES = 3
# 代理类型(http/https)
PROXY_TYPE = 'https'
# 有效代理ip列表
proxies = []
# 线程池,用于同时验证多个代理ip
POOL = futures.ThreadPoolExecutor(max_workers=50)


def add_proxy(proxy: str):
    """
    添加代理

    :param proxy: 代理ip+端口号
    :return:
    """
    try:
        r = requests.get(CHECK_URL, proxies={PROXY_TYPE: proxy}, timeout=30)
        print(PyQuery(r.content.decode()).find('#result').text(), '\n')

        if r.status_code == 200 and proxy not in proxies:
            proxies.append(proxy)
    except Exception as e:
        if proxy in proxies:
            proxies.remove(proxy)
        print(proxy, e)


def fetch_proxy():
    """
    抓取代理ip
    :return:
    """
    for page in range(1, PAGES + 1):
        r = requests.get(FETCH_URL.format(page), headers=headers)
        doc = PyQuery(r.content.decode('utf-8'))
        # 获取数据列表对应的table
        table = doc('#ip_list')
        # 获取table中除了表头以外的所有行
        rows = table('tr:nth-of-type(n+2)').items()
        # 提取每一行中的ip和端口号
        for row in rows:
            ip = row('td:nth-of-type(2)').text()
            port = row('td:nth-of-type(3)').text()
            proxy = ip + ':' + port
            # 在线程池中检测该代理是否可用
            POOL.submit(add_proxy, proxy)
        # 10秒钟后抓取下一页
        time.sleep(10)


def run():
    while True:
        try:
            fetch_proxy()
            print('有效代理:', proxies)
            # 将有效代理写入文件
            with open('ips.txt', 'w', encoding='utf-8') as f:
                f.write('\n'.join(proxies))
        except Exception as e:
            print(e)
        # 抓取一次之后休息一段时间,防止被屏蔽
        time.sleep(random.randint(100, 600))


# 启动抓取线程
threading.Thread(target=run).start()

程序运行一段时间之后,打开ips.txt文件即可看到抓取到的可用代理IP,如图:



  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值