爬虫关于ip的问题

在使用爬虫进行数据抓取时候,会遇到很多反爬虫措施,封IP是常见的一种反扒措施,但是这种反扒措施是很古老的方式,对于运维人员来说当时看起来是比较有效的一种方式,但是一般的大量抓取都会携带使用代理ip 去请求,也就是ip 池

现在爬虫使用代理一般有两种 方式:

1 购买市面上的一些 API 接口,每次返回多少ip,在爬虫程序种接入使用(买代理)

2 自己抓取一些免费的代理,去放到Redis 里面维护起来,定时进行筛选,过滤过期的IP

这两种方式都可以实现使用代理请求目标网站,但是使用过的朋友应知道这两种方式获取的ip 质量非常差,尤其是第二种,可以说根本没法用,除非你是自己玩玩,如果是企业级别或者是对数据质量要求较高,或许第一种方式可以尝试,但还是不稳定

今我推荐给大家第三种方式 动态拨号vps

VPS是什么? 我们平常使用ECS服务器,vps是低配版的ECS,vps 比ecs便宜

VPS(Virtual Private Server 虚拟专用服务器)技术,将一台服务器分割成多个虚拟专享服务器的优质服务。实现VPS的技术分为容器技术,和虚拟化技术  。在容器或虚拟机中,每个VPS都可分配独立公网IP地址、独立操作系统、实现不同VPS间磁盘空间、内存、CPU资源、进程和系统配置的隔离,为用户和应用程序模拟出“独占”使用计算资源的体验。VPS可以像独立服务器一样,重装操作系统,安装程序,单独重启服务器
 

ADSL (Asymmetric Digital Subscriber Line ,非对称数字用户环路)是一种新的数据传输方式。它因为上行和下行带宽不对称,因此称为非对称数字用户线环路。它采用频分复用技术把普通的电话线分成了电话、上行和下行三个相对独立的信道,从而避免了相互之间的干扰。

也就是你每拨一次号就换一次IP。

我买的是XX的VPS服务器,这种拨号服务器有很多,但一定要注意可靠。不推荐某家,都差不多,大家自己筛选就好。大多平均一个月100左右

我们可以在某平台购买一台一天使用时间低配vps测试使用(要开通拨号上网功能)

安装(前提是已经安装好pyhon3)  Centos安装Python3

以CentOS上TinyProxy为例:
安装
yum install -y epel-release
yum update -y
yum install -y tinyproxy

配置
vi /etc/tinyproxy/tinyproxy.conf

注释
Allow 127.0.0.1

启动
systemctl enable tinyproxy.service
systemctl restart  tinyproxy.service

开启

adsl-start

既可拨号成功,如果要断掉,则

adsl-stop

所以断线重播的命令就是二者组合起来,先执行adsl-stop再执行adsl-start,每拨一次号,ifocnfig命令观察一下主机的IP,发现主机的IP一直是在变化的,网卡名称叫做ppp0。

这样我们就得到了一个新的获取ip的方式,如果我们要在爬虫代码中使用这个IP作为代理ip,需获取这个ip 并验证可用性并保存到数据库直至获取一个新的ip 为止

    def get_ip(self, ifname='ppp0'):
        """
        获取本机IP
        :param ifname: 网卡名称
        :return:
        """
        (status, output) = subprocess.getstatusoutput('ifconfig')
        if status == 0:
            pattern = re.compile(ifname + '.*?inet.*?(\d+\.\d+\.\d+\.\d+).*?netmask', re.S)
            result = re.search(pattern, output)
            if result:
                ip = result.group(1)
                return ip

测试代理可用性

    def test_proxy(self, proxy):
        """
        测试代理
        :param proxy: 代理
        :return: 测试结果
        """
        try:
            proxies = {"http": "http://" + proxy}
            response = requests.get("http://www.baidu.com", proxies=proxies)
            if response.status_code == 200:
                return True
        except (ConnectionError, ReadTimeout):
            return False

将代理放到Redis

    def remove_proxy(self):
        """
        移除代理
        :return: None
        """
        self.redis = RedisClient()
        self.redis.remove(CLIENT_NAME)
        print('Successfully Removed Proxy')

    def set_proxy(self, proxy):
        """
        设置代理
        :param proxy: 代理
        :return: None
        """
        self.redis = RedisClient()
        if self.redis.set(CLIENT_NAME, proxy):
            print('Successfully Set Proxy', proxy)

 Redis

class RedisClient(object):
    def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, proxy_key=PROXY_KEY):
        """
        初始化Redis连接
        :param host: Redis 地址
        :param port: Redis 端口
        :param password: Redis 密码
        :param proxy_key: Redis 哈希表名
        """
        self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True)
        self.proxy_key = proxy_key
    
    def set(self, name, proxy):
        """
        设置代理
        :param name: 主机名称
        :param proxy: 代理
        :return: 设置结果
        """
        return self.db.hset(self.proxy_key, name, proxy)
    
    def get(self, name):
        """
        获取代理
        :param name: 主机名称
        :return: 代理
        """
        return self.db.hget(self.proxy_key, name)
    
    def count(self):
        """
        获取代理总数
        :return: 代理总数
        """
        return self.db.hlen(self.proxy_key)
    
    def remove(self, name):
        """
        删除代理
        :param name: 主机名称
        :return: 删除结果
        """
        return self.db.hdel(self.proxy_key, name)
    
    def names(self):
        """
        获取主机名称列表
        :return: 获取主机名称列表
        """
        return self.db.hkeys(self.proxy_key)
    
    def proxies(self):
        """
        获取代理列表
        :return: 代理列表
        """
        return self.db.hvals(self.proxy_key)
    
    def random(self):
        """
        随机获取代理
        :return:
        """
        proxies = self.proxies()
        return random.choice(proxies)
    
    def all(self):
        """
        获取字典
        :return:
        """
        return self.db.hgetall(self.proxy_key)

主进程


    def adsl(self):
        """
        拨号主进程
        :return: None
        """
        while True:
            print('ADSL Start, Remove Proxy, Please wait')
            self.remove_proxy()
            (status, output) = subprocess.getstatusoutput(ADSL_BASH)
            if status == 0:
                print('ADSL Successfully')
                ip = self.get_ip()
                print(ip, '正则匹配到的ip')
                if ip:
                    print('Now IP', ip)
                    print('Testing Proxy, Please Wait')
                    proxy = '{ip}:{port}'.format(ip=ip, port=PROXY_PORT)
                    print('组装好的代理ip-port', proxy)
                    if self.test_proxy(proxy):
                        print('Valid Proxy')
                        self.set_proxy(proxy)
                        print('Sleeping', ADSL_CYCLE)
                        time.sleep(ADSL_CYCLE)
                    else:
                        print('Invalid Proxy')
                else:
                    print('Get IP Failed, Re Dialing')
                    time.sleep(ADSL_ERROR_CYCLE)
            else:
                print('ADSL Failed, Please Check')
                time.sleep(ADSL_ERROR_CYCLE)

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值