python爬虫之建立代理池(一)

背景

很多时候我们会使用爬虫或者脚本帮我们爬取数据用于数据分析、模型训练等,常见的反爬手段之一就是限制IP的访问频率,所以为了让爬虫或脚本能够正常运行,我们需要有足够多的IP。代理IP就是通过代理的IP去访问我们需要的网站,对于目标网站表现出的是代理IP, 从而防止同一IP访问频率过高被封。如何拥有足够多的代理地址呢?我们可以使用爬虫手段去自动爬取提供免费代理的网站,建立自己的代理池。本篇以爬取66代理为例,记录整个过程。

代理网站分析

打开网址后,页面如下:
img
为了快速找到我们需要的信息所在位置,我们使用xpath工具,可以在浏览器的插件市场搜索安装(XPath Helper)。
shift+鼠标左键点击表格:
img
可以看到我们需要的信息位于一个html表格中,因此我们只需要找出这个表格,然后遍历表格就可以获取到我们需要的信息。
另一方面,我们点击页面下方的翻页时,会发现网页地址是http://www.xxx.cn/2.html这种形式,这样翻页也就解决了。

实现

为了方便扩展到其他代理网站,我们先建立一个代理基类:

class BaseProxy:
    """
    代理基类
    """
    def __init__(self, page):
        self._proxies = self._get_proxies()
        self._page = page
     
    def _get_proxies():
        return []
        
    def get_one(self):
        """
        随机返回一个代理
        :return:
        """
        if not self._proxies:
            return []
        return random.choice(self._proxies)

    def get_all(self):
        """
        返回所有代理
        :return:
        """
        return self._proxies

    def check_proxy(self, proxy):
        """
        检测代理是否可用
        :return:
        """
        url = 'https://api.ipify.org/?format=json'
        try:
            res = requests.get(url, proxies=proxy, timeout=3).json()
            if 'ip' in res:
                return True
        except Exception as e:
            return False

下面写一个专属于66代理类,主要实现一个获取代理地址的接口:

class SixSixProxy(BaseProxy):
    """
    66代理
    """
    def __init__(self, page=10):
        super().__init__(page)
        self._count = page * 10
        self.base_url = "http://www.66ip.cn/{}.html"
        self._proxies = self._get_proxies()

    def _get_proxies(self):
        
        proxies = []
        for page in range(self._page):
            if page == 0:
                url = "http://www.66ip.cn/index.html"
            else:
                url = self.base_url.format(page+1)
            
            try:
                # 创建浏览器对象
                options = webdriver.EdgeOptions()
                options.add_argument('--headless')
                driver = webdriver.Edge(options=options)

                # 加载页面
                driver.get(url)

                # 执行JavaScript代码获取完整的HTML内容
                html = driver.execute_script('return document.documentElement.outerHTML')

                # 关闭浏览器
                driver.quit()
                selector = etree.HTML(html)
                table = selector.xpath("/html/body/div[@id='main']/div[@class='containerbox boxindex']/div[@class='layui-row layui-col-space15']/div[1]/table/tbody/tr")
                for tr in table[1:]:
                    ip = tr.xpath("./td[1]/text()")[0]
                    port = tr.xpath("./td[2]/text()")[0]
                    proxy_type = tr.xpath("./td[4]/text()")[0]

                    if proxy_type !="高匿代理":
                        continue

                    protocol = "http"
                    proxy = {
                        "http": '{}://{}:{}'.format(protocol, ip, port)
                    }
                    proxies.append(proxy)
            except Exception as e:
                print(e)
        
        return proxies

为了防止页面中部分信息是通过js获取而不完整,我们直接使用了selenium, 通过webdriver获取完整的html中,通过xpath获取我们需要的表格,然后遍历表格即可得到表格中的ip地址和端口。

测试

Proxy = SixSixProxy()
print(Proxy.get_all())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodingInCV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值