Squid代理服务器搭建亿级爬虫IP代理池

服务器
做爬虫抓取时,我们经常会碰到网站针对IP地址封锁的反爬虫策略。但只要有大量可用的IP资源,问题自然迎刃而解。

做爬虫抓取时,我们经常会碰到网站针对IP地址封锁的反爬虫策略。但只要有大量可用的IP资源,问题自然迎刃而解。

以前尝试过自己抓取网络上免费代理IP来搭建代理池,可免费IP质量参差不齐,不仅资源少、速度慢,而且失效快,满足不了快速密集抓取的需求。

收费代理提供的代理资源质量明显提升,最终选定使用站大爷作为代理提供平台。

站大爷每天能提供大概5万个不重复的短效高匿代理,每个代理存活期为2分钟,总IP数有20亿,IP数量足够使用。价格为包天30元,包月500元,还有半年及一年的套餐可供选择。只要能满足项目要求,提供优质稳定的服务,这些成本值得付出。

[[268270]]

高匿代理才可以真正用来防止爬虫被封锁,如果使用普通代理,爬虫的真实IP还是会暴露。

搭建思路

站大爷提供了大量的代理服务器资源,主要考虑如何将这些服务器分配给爬虫服务器使用。最初的想法是使用Redis作为代理服务器资源队列,一个程序自动获取站大爷API提供的代理,验证可用后push到Redis里,每个程序再从Redis中pop一个代理进行抓取,但这样的缺点是不太好控制每台爬虫服务器的代理质量,有的代理速度快,有的速度比较慢,影响抓取效率,其次就是需要自行维护一套代理验证、分配的程序,增加了代码量,不便后期维护。

为了解决这些问题,我想到可以使用 Squid 提供的父代理功能,自动将爬虫服务器的请求转发给代理服务器。Squid提供了自动轮询功能,自动验证并剔除不可用的代理。减少了我们多余的验证步骤。

爬虫软件只需将代理设置为 Squid 服务器即可,不需要每次重新设置为其他的代理服务器。

这套方案明显减少了工作量,提高了易用性和可维护性。

实现过程

1.首先获取代理平台提供的代理服务器资源

  • 建议购买短效代理,购买后在后台获取API地址并设置IP白名单等参数

2.将获取到的代理服务器写入squid配置文件

  • 解析网站提供的代理服务器,按照一定规则写入 /etc/squid/squid.conf

3.重新配置 squid

  • 写入配置文件之后重新加载***的文件,不会造成中断

4.自动更新,重复1-3

  • 由于网站提供的代理存活时间只有2分钟,所以需要每隔一段时间重新获取一批新IP
from gevent import monkey  # isort:skip 
monkey.patch_all()  # isort:skip 
import logging 
import os 
import time 
 
import requests 
from gevent.pool import Pool 
 
logger = logging.getLogger(__name__) 
logger.setLevel(logging.INFO) 
formatter = logging.Formatter( 
    "%(asctime)s - %(name)s - %(levelname)s: - %(message)s", datefmt="%Y-%m-%d %H:%M:%S" 

 
# 使用StreamHandler输出到屏幕 
ch = logging.StreamHandler() 
ch.setLevel(logging.INFO) 
ch.setFormatter(formatter) 
 
logger.addHandler(ch) 
 
# Squid的配置文件语法 
# 将请求转发到父代理 
PEER_CONF = "cache_peer %s parent %s 0 no-query weighted-round-robin weight=1 connect-fail-limit=2 allow-miss max-conn=5\n" 
# 可用代理 
GOOD_PROXIES = [] 
 
pool = Pool(50) 
 
 
def check_proxy(proxy): 
    """验证代理是否可用 
    :param proxy list:[ip, port]""
    global GOOD_PROXIES 
    ip, port = proxy 
    _proxies = {"http""{}:{}".format(ip, port)} 
    try: 
        ip_url = "http://2019.ip138.com/ic.asp" 
        res = requests.get(ip_url, proxies=_proxies, timeout=10) 
        assert ip in res.content 
        logger.info("[GOOD] - {}:{}".format(ip, port)) 
        GOOD_PROXIES.append(proxy) 
    except Exception as e: 
        logger.error("[BAD] - {}:{}, {}".format(ip, port, e)) 
 
 
def update_conf(): 
    with open("/etc/squid/squid.conf.original""r"as F: 
        squid_conf = F.readlines() 
    squid_conf.append("\n# Cache peer config\n"
    for proxy in GOOD_PROXIES: 
        squid_conf.append(PEER_CONF % (proxy[0], proxy[1])) 
    with open("/etc/squid/squid.conf""w"as F: 
        F.writelines(squid_conf) 
 
 
def get_proxy(): 
    global GOOD_PROXIES 
    GOOD_PROXIES = [] 
    # 1. 获取代理IP资源 
    api_url = "http://s.zdaye.com/?api=YOUR_API&count=100&fitter=1&px=2" 
    res = requests.get(api_url).content 
    if len(res) == 0: 
        logger.error("no data"
    elif "bad" in res: 
        logger.error("bad request"
    else
        logger.info("get all proxies"
        proxies = [] 
        for line in res.split(): 
            proxies.append(line.strip().split(":")) 
        pool.map(check_proxy, proxies) 
        pool.join() 
        # 2. 写入Squid配置文件 
        update_conf() 
        # 3. 重新加载配置文件 
        os.system("squid -k reconfigure"
        logger.info(">>>> DONE! <<<<"
 
 
def main(): 
    start = time.time() 
    while True
        # 每30秒获取一批新IP 
        if time.time() - start >= 30: 
            get_proxy() 
            start = time.time() 
        time.sleep(5) 
 
 
if __name__ == "__main__"
    main() 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.

使用方法

1.按Squid 搭建正向代理服务器、Squid 配置高匿代理介绍的方法搭建运行 Squid 高匿服务器

2.备份原始配置文件cp /etc/squid/squid.conf /etc/squid/squid.conf.original,以供软件使用

3.在squid服务器上运行python zdy.py

实例

如果按照上述方法搭建好代理IP池,只需要在爬虫代码中设置设置squid代理服务器地址和端口(比如139.xxx.xxx.66:3188)。

from __future__ import print_function 
 
import requests 
 
s = requests.Session() 
s.proxies.update({"http""139.xxx.xxx.66:3188"}) 
print(s.get("http://httpbin.org/ip")) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

每次运行这个程序时,返回的IP都不一样,而且仅有一个,说明IP代理池已经搭建成功,可以应用在网络爬虫项目中。

总结

这套解决方案结合了网络上的大量优质代理资源以及Squid服务器提供的特性,基本解决了网站对于爬虫IP的封锁。

成本比较低,而且有比较高的易用性,很方便地能结合到各种爬虫应用中,只需要增加一个代理地址即可,而由 Squid 统一管理父代理,不需要在爬虫程序中进行代理的获取验证等等操作,便于维护。

实际使用中还没有发现什么特别重大的问题,更多扩展性还有待后续继续研究。

项目地址: https://github.com/xNathan/squid_proxy_pool

责任编辑:武晓燕 来源: Python乱炖
相关推荐

2012-09-18 09:55:28

2011-02-21 09:24:05

2020-08-02 15:00:40

SquidSSH系统运维

2009-12-03 18:07:48

Squid代理服务器

2024-11-21 09:18:08

2009-02-12 15:51:00

squid代理服务器web服务器

2019-04-08 08:39:47

Nginx代理服务器

2024-02-20 14:53:01

2009-02-12 15:40:00

代理服务器隐藏ip地址

2010-11-15 14:46:04

linuxsquidsquidGuard

2009-02-10 15:42:00

代理服务器代理服务器设置

2018-11-05 09:34:43

2009-08-18 11:04:50

代理服务器设置代理服务器地址

2015-07-17 10:45:42

Squid服务器访问控制系统

2018-04-17 12:10:40

2011-04-20 16:59:31

2011-08-17 11:26:10

2009-02-27 13:13:00

代理服务器代理服务器软件代理服务器设置

2010-09-17 10:07:17

SIP协议SIP代理服务器

2009-11-24 19:36:34

代理服务器
点赞
收藏

51CTO技术栈公众号