IP代理池设计(抓取,清洗)

目录

 

简述

IP代理

免费抓取IP代理

清洗IP代理算法设计


简述

使用IP代理请求目标页面可以避免IP限流。以爬取淘宝商品信息背景为例,如果使用单个IP频繁的请求淘宝网站,就会被淘宝平台识别,返回的接口信息会报“请求被挤爆了....”

现在淘宝PC端商品列表页为了抵御防爬措施,对频繁访问的IP要求重新登录,或者或跳转至一个带有滑块验证的页面,要求用户登录或拖动滑块。同时,淘宝目前已经对一些含有危险性的灰黑IP做限制,能提供云上百万级已知针对性风险的IP黑灰产数据做出判断。目前,淘宝手机端还未做爬虫风险管理,所以使用动态IP代理访问淘宝手机端接口数据还是有效的。

IP代理

IP代理有透明代理、匿名代理、混淆代理和高匿代理。这四种代理,主要是代理服务器端的配置不同,导致其向目标地址发送请求时,REMOTE_ADDR、HTTP_VIA、HTTP_X_FORWARDED_FOR三个变量不同。

一:透明代理(Transparent Proxy)

REMOTE_ADDR=Proxy IP

HTTP_VIA=Proxy IP

HTTP_X_FORWARDED_FOR=Your IP

透明代理虽然可以直接”隐藏”你的IP,但是还是可以从HTTP_X_FORWARDED_FOR来查到你是谁。

二:匿名代理(Anonymous Proxy)

REMOTE_ADDR=Proxy IP

HTTP_VIA=Proxy IP

HTTP_X_FORWARDED_FOR=Proxy IP

匿名代理比透明代理进步一点:别人只能知道你用了代理,无法知道你是谁。

三:混淆代理(Distorting Proxies)

REMOTE_ADDR=Proxy IP

HTTP_VIA=Proxy IP

HTTP_X_FORWARDED_FOR=Random IP address

与匿名代理相同,如果使用了混淆代理,别人还是能知道你在用代理,但是会得到一个假的IP地址,伪装的更逼真

四:高匿代理(High Anonymity Proxy)

REMOTE_ADDR=Proxy IP

HTTP_VIA=not determined

HTTP_X_FORWARDED_FOR=not determined

使用高匿代理,能让别人根本无法发现你是在用代理,所以是最好的选择。

免费抓取IP代理

网上有很多IP代理供应商,但其价格昂贵,给中小型企业代理了不少的成本预算。如之前使用讯代理、大象代理等。也有不少人私立搭建提供免费IP代理、如西刺jiangxianliDATA5U等。本项目将定时去抓取免费IP代理,并将有效IP存入可用IP代理池中。

有关IP代理管理的都在crawl-proxy模块中,通过爬虫任务调度定时触发爬取免费IP代理网站信息,抓取其提供的IP,并存入redis中。

清洗IP代理算法设计

IP代理池有 可用IP代理池、IP代理池、废弃IP代理池,它们的生命周期依次递减。在免费IP代理页面抓取IP后,先把IP存放到IP代理池中,经过验证是否可用,如果可用,则把IP代理池中的IP存放到可用IP代理池中,并将其删除已存在的IP代理池;否则,将IP存放到废弃IP代理池中。

清洗IP是否可用采用的是多线程CompletionService异步非阻塞获取并行任务结果。使用Future和Callable可用获取线程执行结果,但获取方式为阻塞的,根据添加到线程池中的线程顺序,依次获取,获取不到就阻塞。为了更快获取结果,本项目采用CompletionService来实现异步快速收集线程执行结果,并采用基于Socket连接判断IP代理是否可用。具体核心源码如下所示:

public class VerifyProxy {

    static ExecutorService threads = Executors.newFixedThreadPool(120);

    public VerifyProxy() {
    }

    public Map<HostPort, Boolean> verifyProxy(List<HostPort> hostPortList) {
        Map<HostPort, Boolean> hostPortBooleanMap = Collections.synchronizedMap(new HashMap());
        CompletionService<Map<HostPort, Boolean>> cs = new ExecutorCompletionService(this.threads);

        int i;
        for(i = 0; i < hostPortList.size(); ++i) {
            cs.submit(new VerifyProxy.RequestCheck(hostPortList.get(i), hostPortBooleanMap));
        }

        //this.threads.shutdown();

        for(i = 0; i < hostPortList.size(); ++i) {
            try {
                Map var5 =cs.take().get();
            } catch (InterruptedException var6) {
                var6.printStackTrace();
            } catch (ExecutionException var7) {
                var7.printStackTrace();
            }
        }

        return hostPortBooleanMap;
    }

    class RequestCheck implements Callable<Map<HostPort, Boolean>> {
        HostPort hostPort = null;
        Map<HostPort, Boolean> map = null;

        public RequestCheck(HostPort hostPort, Map<HostPort, Boolean> map) {
            this.hostPort = hostPort;
            this.map = map;
        }

        public RequestCheck() {
        }

        public Map<HostPort, Boolean> call() throws Exception {
            Socket socket = new Socket();
            try {
                socket.connect(new InetSocketAddress(hostPort.getHostName(),hostPort.getPort()),2000);
                this.map.put(this.hostPort, true);
            } catch (IOException e) {
                this.map.put(this.hostPort, false);
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return this.map;
        }

    }

}

 

猜你喜欢

转载自blog.csdn.net/Lixuanshengchao/article/details/83109387