运用squid轮询ip避免爬虫被封

爬虫使用过程中经常会遇到反爬限制的网站,爬的快一点就会被封IP网络上有很多免费代理随便扫描一批就可以使用.每增加一个代理IP爬取速度就会增加一倍,所以使用代理爬网站是最经济实用的。
首先是先安装squid.ubuntu系统直接使用下面的命令安装squid:
sudo apt-get install squid3
如果是centos系统就使用下面的命令安装:
yum -y install squid

windows下的安装自行百度。本人已成功安装并使用。

配置文件一般是在/etc/squid3/下的squid.conf文件,里边记录了待轮询的ip.ubuntu系统可以直接全部替换,centos对应修改就可以了.重启后就可以生效了.如果配置正确,ip可用,把代理ip换为squid的代理地址即可,如可以把浏览器的HTTP代理设置成127.0.0.1:6666或是服务器的IP.如果代理IP是免费采集的就需要写个脚本自动采集验证自动生成配置文件,然后重新载入配置文件或重启squid.

所以可以选择买少量的代理,再通过网上的开源框架采集一些免费的代理。网上已经有一些教程是基于IPpool的,本文用的是proxy_pool ,其使用方法可以参考github主页说明。

思路如下.

  1. 将获取到的代理服务器写入squid配置文件
    • 解析网站提供的代理服务器,按照一定规则写入/etc/squid/squid.conf
  2. 重新配置squid
    • 写入配置文件之后重新加载最新的文件,不会造成中断
  3. 自动更新,重复1-3
    • 由于网站提供的代理存活时间有限,所以需要每隔一段时间重新获取一批新IP

使用方法

  1. Squid 搭建正向代理服务器Squid 配置高匿代理介绍的方法搭建运行Squid高匿服务器
  2. 备份原始配置文件cp /etc/squid.conf /etc/squid.conf.or 这里根据配置文件路径不同自行设置
  3. 在squid服务器上运行python ippool.py即如下python文件。代码是python3的,省心。
#!/usr/bin/env python
# coding: utf-8
from gevent import monkey
monkey.patch_all()

import os
import time
import logging
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 delete_proxy(proxy):
    requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy))
def check_proxy(proxy):
    #GOOD_PROXIES=[]      
    try:
        html = requests.get('http://yingshi.51treenewbee.cn', proxies={"http": "http://{}".format(proxy)},timeout=10)
        #assert proxy in html.content
        logger.info('[GOOD] - {}'.format(proxy))
        #GOOD_PROXIES.append(proxy)
        return proxy
    except Exception as e:
        delete_proxy(proxy)
        logger.error('[BAD] - {}, {}'.format(proxy, e))
        return 'bad'
def update_conf(proxy1):
    try:
        with open('etc/squid.conf.or', 'r') as F:
            squid_conf = F.readlines()
        squid_conf.append('\n# Cache peer config\n')
        for line in proxy1:
        #采集代理ip端口分离
            proxy=line.strip().split(':')
            squid_conf.append(PEER_CONF % (proxy[0], proxy[1]))
        with open('etc/squid.conf', 'w') as F:
            F.writelines(squid_conf)
            return True
            logger.info('写入Squid配置文件成功')
    except Exception as e:
        logger.error(e)
        return False 

def get_proxy():
    # 1. 获取代理IP资源
    res = requests.get('http://127.0.0.1:5010/get_all').json()   
    try:       
        logger.info('get all proxies')
        proxies = []       

        #检查良好的代理
        Goodproxy=pool.map(check_proxy, res)
        pool.join()
        try:
            while 'bad' in Goodproxy:
                Goodproxy.remove('bad')
                
        # 2. 写入Squid配置文件
        except:
            logger.info('检查到所有代理均可同,这是小概率事件,请检查配置')
        update_conf(Goodproxy)
        # 3. 重新加载配置文件
        os.system('squid -k reconfigure -n Squid_Proxy')
        logger.info('>>>> DONE! <<<<') except Exception as e: logger.error(e) def main(): timeRange=300 print('ip存入squid开始') start = time.time()-timeRange+2 while True: # 每30秒获取一批新IP if time.time() - start >= timeRange:
            get_proxy()
            start = time.time()
        time.sleep(5)
if __name__ == '__main__':
    main()

See Also