信息发布→ 登录 注册 退出

用python构建IP代理池详解

发布时间:2026-01-11

点击量:
目录
  • 概述
    • 提供免费代理的网站
  • 代码
    • 导包
    • 网站页面的url
    • ip地址
    • 检测
    • 整理
    • 必要参数
    • 总代码
  • 总结

    概述

    用爬虫时,大部分网站都有一定的反爬措施,有些网站会限制每个 IP 的访问速度或访问次数,超出了它的限制你的 IP 就会被封掉。对于访问速度的处理比较简单,只要间隔一段时间爬取一次就行了,避免频繁访问;而对于访问次数,就需要使用代理 IP 来帮忙了,使用多个代理 IP 轮换着去访问目标网址可以有效地解决问题。

    目前网上有很多的代理服务网站提供代理服务,也提供一些免费的代理,但可用性较差,如果需求较高可以购买付费代理,可用性较好。

    因此我们可以自己构建代理池,从各种代理服务网站中获取代理 IP,并检测其可用性(使用一个稳定的网址来检测,最好是自己将要爬取的网站),再保存到数据库中,需要使用的时候再调用。

    提供免费代理的网站

    厂商名称地址
    66代理http://www.66ip.cn/
    西刺代理https://www.xicidaili.com
    全网代理http://www.goubanjia.com
    云代理http://www.ip3366.net
    IP海http://www.iphai.com
    快代理https://www.kuaidaili.com
    免费代理IP库http://ip.jiangxianli.com
    小幻代理https://ip.ihuan.me/

    代码

    导包

    import loguru, requests, random, time  # 发送请求,记录日志,等
    from lxml import etree  # 分析数据
    from concurrent.futures import ThreadPoolExecutor  # 线程池
    

    网站页面的url

    由于小幻代理的每个页面的url没有规律,所以需要一一获取

    def get_url():  # 得到存放ip地址的网页
        print("正在获取ip池", ",不要着急!")
        for i in range(random.randint(10, 20)):  # 爬取随机页数
            time.sleep(1)
            if i == 0:
                url = "https://ip.ihuan.me/"
            else:
                url = url_list[-1]
            try:
                resp = requests.get(url=url, headers=headers_test, timeout=10)
            except Exception as e:
                print(e)
                break
            html = etree.HTML(resp.text)
            ul = html.xpath('//ul[@class="pagination"]')
            ul_num = html.xpath('//ul[@class="pagination"]/li')
            for j in range(len(ul_num)):
                if j != 0 and j != len(ul_num) - 1:
                    a = ul[0].xpath(f"./li[{j}+1]/a/@href")[0]
                    url_list.append("https://ip.ihuan.me/" + a)  # 得到许多的代理ip网址
            loguru.logger.info(f"over,{url}")
    

    ip地址

    def get_ip():
        for i in url_list:
            time.sleep(1)
            resp = requests.get(url=i, headers=headers)
            html = etree.HTML(resp.text)
            td = html.xpath("//tbody/tr")
            for i in td:
                ip = i.xpath("./td[1]//text()")[0]  # 地址
                pt = i.xpath("./td[2]//text()")[0]  # 端口
                tp = "http" if i.xpath("./td[5]//text()")[0] == "不支持" else "https"  # 访问类型
                ip_list.append({"type": tp, "proxy": f"{ip}:{pt}"})
        loguru.logger.info("ip地址获取完成")
    

    检测

    def test_ip(ip):
        proxy_test = {
            "http": f"{ip}",
            "https": f"{ip}"
            # 注意:如果请求的ip是https类型的,但代理的ip是只支持http的,那么还是使用本机的ip,如果请求的ip是http类型的,那么代理的ip一定要是http的,前面不能写成https,否则使用本机IP地址
        }
        resp = requests.get(url=url_test, headers=headers, proxies=proxy_test, timeout=6)
        if resp.json()["origin"] == ip.split(":")[0]:
            ip = {"type": url.strip(":")[0], "proxy": ip}  # 格式化ip,便于后期处理,是的其有http/https标识
            temp_ip.append(ip)  # 符合条件的添加,不符合条件的抛弃
    

    整理

    def set_ip(url) -> "动态构建ip池":  # 要传入需要爬取网页的url
        try:
            f = open('./app/ip.txt', "r")
            for j in eval(f.read()):
                temp_ip.append(j)
            f.close()
        except Exception as e:
            print("没有ip,正在构造ip池,请稍等")
    
        if not temp_ip:  # 判断是否有ip地址
            print("没有ip地址,正在获取")
            get_url()
        else:
            for i in temp_ip:
                ip_list.append(i)  # 将已有的ip添加到测试ip中
            temp_ip.clear()
    
        get_ip()  # 得到大量ip地址
        with open('./app/ip.txt', "w") as file:
            file.write(ip_list)
        ip_able = list(set(j["proxy"] for j in ip_list if j["type"] == url.split(":")[0]))  # 存放符合要求的ip字符串,同时利用字典去重
        url_test = "http://httpbin.org/ip" if url.split(":")[0] == "http" else ""  # 测试ip地址是否有用
    
        def test_ip(ip):
            proxy_test = {
                "http": f"{ip}",
                "https": f"{ip}"
                # 注意:如果请求的ip是https类型的,但代理的ip是只支持http的,那么还是使用本机的ip,如果请求的ip是http类型的,那么代理的ip一定要是http的,前面不能写成https,否则使用本机IP地址
            }
            resp = requests.get(url=url_test, headers=headers, proxies=proxy_test, timeout=6)
            if resp.json()["origin"] == ip.split(":")[0]:
                ip = {"type": url.strip(":")[0], "proxy": ip}  # 格式化ip,便于后期处理,是的其有http/https标识
                temp_ip.append(ip)  # 符合条件的添加,不符合条件的抛弃
    
        with ThreadPoolExecutor(50) as pool:  # 使用多线程测试
            pool.map(test_ip, ip_able)
    
        pool.join()
    
        print("测试完毕")
    
        if temp_ip:
            i = random.choice(temp_ip)
            proxy = {
                "http": f"{i['proxy']}",
                "https": f"{i['proxy']}"
            }
            return proxy
        else:
            set_ip(url=url)
    

    必要参数

    # 参数
    
    headers = {
        'User-Agent': "Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 96.0.4664 .93 Safari / 537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
    }
    headers_test = {
        'User-Agent': "Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 96.0.4664 .93 Safari / 537.36",
        "accept-encoding": "gzip, deflate, br",
        "cookie": "Hm_lvt_8ccd0ef22095c2eebfe4cd6187dea829=1642389014,1642412091",
        "Referer": "https://ip.ihuan.me/"
    }
    url_list, ip_list, temp_ip = ["https://ip.ihuan.me/"], [], []  # 存放url, 存放ip地址, 有用的ip地址
    

    总代码

    import loguru, requests, random, time
    from lxml import etree
    from concurrent.futures import ThreadPoolExecutor
    
    
    def get_url():  # 得到存放ip地址的网页
        print("正在获取ip池", ",不要着急!")
        for i in range(random.randint(10, 20)):  # 爬取随机页数
            time.sleep(1)
            if i == 0:
                url = "https://ip.ihuan.me/"
            else:
                url = url_list[-1]
            try:
                resp = requests.get(url=url, headers=headers_test, timeout=10)
            except Exception as e:
                print(e)
                break
            html = etree.HTML(resp.text)
            ul = html.xpath('//ul[@class="pagination"]')
            ul_num = html.xpath('//ul[@class="pagination"]/li')
            for j in range(len(ul_num)):
                if j != 0 and j != len(ul_num) - 1:
                    a = ul[0].xpath(f"./li[{j}+1]/a/@href")[0]
                    url_list.append("https://ip.ihuan.me/" + a)  # 得到许多的代理ip网址
            loguru.logger.info(f"over,{url}")
    
    
    def get_ip():
        for i in url_list:
            time.sleep(1)
            resp = requests.get(url=i, headers=headers)
            html = etree.HTML(resp.text)
            td = html.xpath("//tbody/tr")
            for i in td:
                ip = i.xpath("./td[1]//text()")[0]  # 地址
                pt = i.xpath("./td[2]//text()")[0]  # 端口
                tp = "http" if i.xpath("./td[5]//text()")[0] == "不支持" else "https"  # 访问类型
                ip_list.append({"type": tp, "proxy": f"{ip}:{pt}"})
        loguru.logger.info("ip地址获取完成")
    
    
    def set_ip(url) -> "动态构建ip池":  # 要传入需要爬取网页的url
        try:
            f = open('./app/ip.txt', "r")
            for j in eval(f.read()):
                temp_ip.append(j)
            f.close()
        except Exception as e:
            print("没有ip,正在构造ip池,请稍等")
    
        if not temp_ip:  # 判断是否有ip地址
            print("没有ip地址,正在获取")
            get_url()
        else:
            for i in temp_ip:
                ip_list.append(i)  # 将已有的ip添加到测试ip中
            temp_ip.clear()
    
        get_ip()  # 得到大量ip地址
        with open('./app/ip.txt', "w") as file:
            file.write(ip_list)
        ip_able = list(set(j["proxy"] for j in ip_list if j["type"] == url.split(":")[0]))  # 存放符合要求的ip字符串,同时利用集合去重
        url_test = "http://httpbin.org/ip" if url.split(":")[0] == "http" else ""  # 测试ip地址是否有用
    
        def test_ip(ip):
            proxy_test = {
                "http": f"{ip}",
                "https": f"{ip}"
                # 注意:如果请求的ip是https类型的,但代理的ip是只支持http的,那么还是使用本机的ip,如果请求的ip是http类型的,那么代理的ip一定要是http的,前面不能写成https,否则使用本机IP地址
            }
            resp = requests.get(url=url_test, headers=headers, proxies=proxy_test, timeout=6)
            if resp.json()["origin"] == ip.split(":")[0]:
                ip = {"type": url.strip(":")[0], "proxy": ip}  # 格式化ip,便于后期处理,是的其有http/https标识
                temp_ip.append(ip)  # 符合条件的添加,不符合条件的抛弃
    
        with ThreadPoolExecutor(50) as pool:  # 使用多线程测试
            pool.map(test_ip, ip_able)
    
        pool.join()
    
        print("测试完毕")
    
        if temp_ip:
            i = random.choice(temp_ip)
            proxy = {
                "http": f"{i['proxy']}",
                "https": f"{i['proxy']}"
            }
            return proxy
        else:
            set_ip(url=url)
    
    
    # 参数
    
    headers = {
        'User-Agent': "Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 96.0.4664 .93 Safari / 537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
    }
    headers_test = {
        'User-Agent': "Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 96.0.4664 .93 Safari / 537.36",
        "accept-encoding": "gzip, deflate, br",
        "cookie": "Hm_lvt_8ccd0ef22095c2eebfe4cd6187dea829=1642389014,1642412091",
        "Referer": "https://ip.ihuan.me/"
    }
    url_list, ip_list, temp_ip = ["https://ip.ihuan.me/"], [], []  # 存放url, 存放ip地址, 有用的ip地址
    
    if __name__ == '__main__':
        proxy = set_ip(url="https://www.baidu.com")  # 得到代理ip
        print(proxy)
    

    总结

    如果安装了数据库的话,可以使用数据库存储得到的ip,代码中使用的是本地的文件存储数据,同时,要尽量避免本机ip被封

    在线客服
    服务热线

    服务热线

    4008888355

    微信咨询
    二维码
    返回顶部
    ×二维码

    截屏,微信识别二维码

    打开微信

    微信号已复制,请打开微信添加咨询详情!