Loading

分币不花,K哥带你白嫖海外代理 ip!

00

前言

近来,国内的数据采集环境越来越严峻,不是“非法入侵计算机信息系统”,就是“侵犯公民个人隐私信息”,一个帽子砸下来,直接就“包吃包住”,推荐阅读一下 【K哥爬虫普法专栏】。虽然大伙常说“搏一搏单车变摩托”,但这就像高空走钢丝,谁也说不好下一步会不会掉入万丈深渊。因此何不换个赛道,把目标放到各类海外数据,比如海外电商平台、社交媒体平台等等,同样能带来巨大的价值,最重要的,大多数人的技术也不足以惊动 FBI、ICPO,整个国际红色通缉令,被跨国追捕 ≖‿≖。

不过很多海外平台都有着较严格的风控策略,既然咱无法“肉身出国”,全球各地到处跑,最好的选择自然是使用海外代理 ip,但是大多数海外代理 ip 都价格不菲,下图是一家海外代理商官网的 ISP(住宅)按流量付费产品的价格表,注意货币单位可是“美元”:

01

这么一来,采集海外数据的成本就太高了,那有什么好的解决办法呢?自然是有的,K哥深知大伙都坚决贯彻着“能白嫖绝不付费”的思想,有免费的用绝不花钱买 ( ´◔ ‸◔`),但是用过国内那些网站的免费代理的都知道,免费的真没啥好东西,质量堪忧。那么问题就来了,海外代理 ip 还更值钱一些,哪里能找到能用且好用的免费海外代理 ip 呢?K哥还真找到一个,本文将手把手教你如何采集该网站的免费海外代理 ip,并给出源代码,一起来给这年轻的网站“上上课”。

采集目标

采集过程

该网站为快代理的海外独立站,首先进入到网页,可以看到有很多地区的海外代理 ip,美国、新加坡、泰国等等,全球各地的都有,而且都是高匿名的。这些 ip 时效都显示的 1-10 分钟,但是根据实际测试,部分 ip 半小时之后仍然可用。并且半小时刷新一次,也就是每隔半小时能获取到 12 个新的可用 ip,结合一些合理的调度策略,每天都能够不间断地“白嫖”~

当然,没必要整啥并发之类的,每半小时获取一次就可以了,不间断请求也不会给你一批新货,还会被封哦:

02

现在,咱们分析下如何采集这些海外代理 ip。

鼠标移动到网页上,右键查看页面源代码(ctrl+u),搜索一下目标 ip,会发现能直接搜索到,且其他 ip 相关数据也都在其中。证明这些数据不是通过接口传输的,可以直接使用一些常用的 Python 解析库,例如 XPath、pyquery 或者正则表达式等方法匹配到想要的数据,而且该页面大概率也是没啥反爬的:

03

那么,还是老样子,F12,先打开开发者人员工具进行抓包,刷新网页,可以看到,https://www.iphaiwai.com/free/ 请求的响应内容包含我们所需要的 html 源代码:

04

先点击开发者人员工具左上角的按钮,检查网页元素,再随便点击一个 ip,即可跳转到其在 html 代码中的位置,页面是个表格样式,这里自然就是一些 tr、td 标签,tr 包裹了每行的内容,td 则对应该行中每个单元格的值,如下图所示:

05

这里我们使用 lxml 解析库中的 Xpath 方法来匹配这部分内容,先简单介绍一下,XPath(XML Path Language)是一种用于在 XML 文档中查找信息的语言,通过特定的路径表达式来匹配在 XML 文档结构中的位置。使用前,需要先安装一下 lxml 解析库:

# 直接安装
pip install lxml
# 镜像安装
pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple

下面是 Xpath 的一些基本表达式,更详细的可以阅读 K 哥往期文章 【0基础学爬虫】爬虫基础之网页解析库的使用

06

我们需要获取 <td data-title="IP">134.35.9.162</td> 中的 ip 值,只用匹配 td 标签的属性 data-title 值为 IP 的即可,基本写法如下:

import requests
from lxml import etree
from loguru import logger


headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
}
url = "https://www.iphaiwai.com/free/"
response = requests.get(url, headers=headers, timeout=5)

# 获取 ip
# xpath 匹配 ip 值
html = etree.HTML(response.text)
ip_list = html.xpath("//td[@data-title='IP']/text()")
logger.info(ip_list)

如果还想要别的数据,例如时效、位置等等,方法也都一样,依此类推。这里的样式较为简单,比较容易就能够匹配到值,一般复杂些的,我们可以用些工具先校验一下 xpath 表达式是否正确,比如浏览器插件 XPath Helper,能够显示出输入的 xpath 表达式匹配出来的结果。该插件可以去K哥公众号回复关键字 XPath Helper 获取。

插件安装后,按快捷键 ctrl + shift + x 即可启动。以下为结果验证,可以看到,该表达式正确匹配到了 12 个 ip 值:

07

完整代码

以下代码只是简单实现了一些基本的功能,可以根据自己的需求进行相应的调整,经过K哥测试,这些 ip 好像不区分使用环境,大家可以自行测试一下:

# ======================
# -*-coding: Utf-8 -*-
# author: K哥爬虫
# ======================
import requests
from lxml import etree
from loguru import logger
from concurrent.futures import ThreadPoolExecutor, as_completed

# 免费海外代理 ip 页
FREE_IP_URL = 'https://www.iphaiwai.com/free'
# 验证网站
VERIFY_URL = 'https://web.whatsapp.com'


class OverseasFree:
    def __init__(self):
        self.headers = {
            "Accept-Encoding": "gzip",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
        }
        self.effective_ip_list = []

    @staticmethod
    def get_proxies(proxy: str) -> dict:
        proxies = {
            "http": "http://%(proxy)s/" % {"proxy": proxy},
            "https": "http://%(proxy)s/" % {"proxy": proxy}
        }
        return proxies

    def verify_ip(self, proxy_ip_data: str):
        """
        验证 ip 可用性
        :param proxy_ip_data: 获取到的免费海外代理 ip
        """
        # 获取代理 ip
        proxy = proxy_ip_data.split(',')[0]
        proxies = self.get_proxies(proxy)
        try:
            # 验证可用性, 国内环境无法访问该网站
            response = requests.get(url=VERIFY_URL, proxies=proxies, timeout=20)
            response.encoding = 'utf-8'
            # <title>WhatsApp Web</title>
            if response.status_code == 200:
                logger.success('ip <%s> verify success' % proxy)
                self.effective_ip_list.append(proxy_ip_data)
            else:
                logger.error('ip <%s> verify error, status code: %s' % (proxy, response.status_code))
        except Exception as e:
            logger.error('ip <%s> verify error: %s' % (proxy, e))

    def get_data(self) -> list:
        """
        获取 ip 相关信息
        """
        try:
            response = requests.get(url=FREE_IP_URL, headers=self.headers, timeout=5)
            html = etree.HTML(response.text)

            # 获取 ip
            ip_list = html.xpath("//td[@data-title='IP']/text()")
            port_list = html.xpath("//td[@data-title='PORT']/text()")

            # 获取 ip 位置
            area_list = html.xpath("//td[@data-title='位置']/text()")

            # 获取 ip 有效期
            period_of_validity_list = html.xpath("//td[@data-title='IP时效(分钟)']/text()")

            # 获取到的所有 ip 的相关数据
            proxy_list = [f"{ip}:{port}, {area}, {period}" for ip, port, area, period in zip(ip_list, port_list, area_list, period_of_validity_list)]

            return proxy_list
        except Exception as e:
            logger.error('get ip error: %s' % e)

    def main(self):
        # 获取所有的免费代理 ip
        proxy_data_list = self.get_data()

        # 验证 ip 可用性
        with ThreadPoolExecutor(max_workers=12) as executor:
            futures = [executor.submit(self.verify_ip, proxy) for proxy in proxy_data_list]
        verify_result = [future.result() for future in as_completed(futures)]
        if verify_result:
            # 处理返回的数据
            pass

        # 打印所有的有效 ip
        logger.info(self.effective_ip_list)
        logger.info('Get IP Number: %d' % len(self.effective_ip_list))


if __name__ == '__main__':
    OverseasFree().main()

结果验证

08

posted @ 2024-01-26 18:55  K哥爬虫  阅读(168)  评论(0编辑  收藏  举报