| 
                        副标题[/!--empirenews.page--]
                         做爬虫抓取时,我们经常会碰到网站针对IP地址封锁的反爬虫策略。但只要有大量可用的IP资源,问题自然迎刃而解。 
以前尝试过自己抓取网络上免费代理IP来搭建代理池,可免费IP质量参差不齐,不仅资源少、速度慢,而且失效快,满足不了快速密集抓取的需求。 
收费代理提供的代理资源质量明显提升,最终选定使用站大爷作为代理提供平台。 
站大爷每天能提供大概5万个不重复的短效高匿代理,每个代理存活期为2分钟,总IP数有20亿,IP数量足够使用。价格为包天30元,包月500元,还有半年及一年的套餐可供选择。只要能满足项目要求,提供优质稳定的服务,这些成本值得付出。 
  
高匿代理才可以真正用来防止爬虫被封锁,如果使用普通代理,爬虫的真实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=5n" 
 - # 可用代理 
 - 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 confign") 
 -     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.按Squid 搭建正向代理服务器、Squid 配置高匿代理介绍的方法搭建运行 Squid 高匿服务器 
2.备份原始配置文件cp /etc/squid/squid.conf /etc/squid/squid.conf.original,以供软件使用 
3.在squid服务器上运行python zdy.py 
实例 
                                                (编辑:91站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |