如何使用自建代理ip池尽享数据搭建

摘要:
在进行网络爬虫时,对代理IP的需求通常很大。代理IP可以通过以下方式获得:从免费网站获得,质量很低。可用的IP很少购买付费代理服务,而且质量要高得多。代理服务器由自己构建,稳定,但需要大量的服务器资源。获取可用代理的核心代码是ProxyManager,它由RxJava2实现。它主要执行以下操作:创建ParallelFlowable,并并行抓取提供免费代理IP的每个页面。

做网络爬虫时,一般对代理IP的需求量比较大。因为在爬取网站信息的过程中,很多网站做了反爬虫策略,可能会对每个IP做频次控制。这样我们在爬取网站时就需要很多代理IP。
代理IP的获取,可以从以下几个途径得到:
从免费的网站上获取,质量很低,能用的IP极少
购买收费的代理服务,质量高很多
自己搭建代理服务器,稳定,但需要大量的服务器资源。
本文的代理IP池是通过爬虫事先从多个免费网站上获取代理IP之后,再做检查判断IP是否可用,可用的话就存放到MongoDB的中,最后展示到前端的页面上。
获取可用代理
获取代理的核心代码是ProxyManager,它采用RxJava2来实现,主要做了以下几件事:
创建ParallelFlowable,针对每一个提供免费代理IP的页面并行地抓取。
针对每一个页面进行抓取,返回列表<代理>

map(new Function<String, List<Proxy>>() { @Override public List<Proxy> apply(String s) throws Exception { try { return newProxyPageCallable(s).call(); } catch (Exception e) {
e.printStackTrace(); } return null; } })

对每一个页面获取的代理IP列表进行校验,判断是否可用

flatMap(new Function<List<Proxy>, Publisher<Proxy>>() { @Override publicPublisher<Proxy> apply(List<Proxy> proxies) throws Exception { if (proxies ==null) return null; List<Proxy> result = proxies
.stream() .parallel() .filter(new Predicate<Proxy>() { @Override public boolean test(Proxy proxy) { HttpHost httpHost = new HttpHost(proxy.getIp(), proxy.getPort(), proxy.getType()); return HttpManager.get().checkProxy(httpHost); }}).collect(Collectors.toList()); return Flowable.fromIterable(result); } })
依次保存到proxyListsubscribe(newConsumer<Proxy>(){@Overridepublicvoid accept(Proxy proxy)throwsException{
log.debug("Result Proxy = "+proxy.getType()+"://"+proxy.getIp()+":"+proxy.getPort());
proxy.setLastSuccessfulTime(newDate().getTime());ProxyPool.proxyList.add(proxy);}});
附上完整的流程图

如何使用自建代理ip池尽享数据搭建第1张

再附上完整的ProxyManager代码:
import com.cv4j.proxy.domain.Proxy;
import com.cv4j.proxy.http.HttpManager;
import com.cv4j.proxy.task.ProxyPageCallable;
import io.reactivex.Flowable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.reactivestreams.Publisher;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Created by tony on 2017/10/25.
 */
@Slf4j
@Component
public class ProxyManager {

    /**
     * 抓取代理,成功的代理存放到ProxyPool中
     */
    public void start() {

        Flowable.fromIterable(ProxyPool.proxyMap.keySet())
                .parallel()
                .map(new Function<String, List<Proxy>>() {
                    @Override
                    public List<Proxy> apply(String s) throws Exception {

                        try {
                            return new ProxyPageCallable(s).call();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        return null;
                    }
                })
                .flatMap(new Function<List<Proxy>, Publisher<Proxy>>() {
                    @Override
                    public Publisher<Proxy> apply(List<Proxy> proxies) throws Exception {

                        if (proxies == null) return null;

                        List<Proxy> result = proxies
                                .stream()
                                .parallel()
                                .filter(new Predicate<Proxy>() {
                            @Override
                            public boolean test(Proxy proxy) {

                                HttpHost httpHost = new HttpHost(proxy.getIp(), proxy.getPort(), proxy.getType());
                                return HttpManager.get().checkProxy(httpHost);
                            }
                        }).collect(Collectors.toList());

                        return Flowable.fromIterable(result);
                    }
                })
                .sequential()
                .subscribe(new Consumer<Proxy>() {
                    @Override
                    public void accept(Proxy proxy) throws Exception {
                        log.debug("Result Proxy = "+proxy.getType()+"://"+proxy.getIp()+":"+proxy.getPort());
                        proxy.setLastSuccessfulTime(new Date().getTime());
                        ProxyPool.proxyList.add(proxy);
                    }
                });
    }
}
定时任务
每隔几个小时跑一次定时任务,在抓取完任务之后先删除旧的数据,然后再把新的数据插入到MongoDB的中。
import com.cv4j.proxy.ProxyManager;
import com.cv4j.proxy.ProxyPool;
import com.cv4j.proxy.dao.ProxyDao;
import com.cv4j.proxy.domain.Proxy;
import com.safframework.tony.common.utils.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created by tony on 2017/11/22.
 */
@Component
public class ScheduleJobs {

    @Autowired
    ProxyDao proxyDao;

    @Autowired
    ProxyManager proxyManager;

    /**
     * 每六个小时跑一次任务
     */
    @Scheduled(cron = "0 0 */6 * * ?")
    public void cronJob() {
        System.out.println("Job Start...");

        proxyManager.start();

        CopyOnWriteArrayList<Proxy> list = ProxyPool.proxyList;

        // 先删除旧的数据
        proxyDao.deleteAll();

        // 然后再进行插入新的proxy
        if (Preconditions.isNotBlank(list)) {

            for (Proxy p:list) {

                proxyDao.saveProxy(p);
            }
        }

        System.out.println("Job End...");
    }
}
总结
在做爬虫时,自己维护一个可用的代理IP池是很有必要的事情,当然想要追求更高稳定性的代理IP还是考虑购买比较好。

免责声明:文章转载自《如何使用自建代理ip池尽享数据搭建》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Hive速览C#操作redis下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

HttpClient配置及运用(二)

4.获取响应状态Status信息、获取状态码Status Code 一般服务器的响应状态有以下几种: 200 正常 400 未找到页面 403 拒绝 500 服务器错误 比如我们请求bootstrap中文网, 我们现在代码中获取状态码: public classDemo { public static void main(String[] args...

可能是一份没什么用的爬虫代理IP指南

写在前面 做爬虫的小伙伴一般都绕不过代理IP这个问题. PS:如果还没遇到被封IP的场景,要不就是你量太小人家懒得理你,要不就是人家压根不在乎... 爬虫用户自己是没有能力维护一系列的代理服务器和代理IP的,这个成本实在有点高了。 所以公用代理服务器应运而生,现在几大云服务商家都提供代理IP服务,一般论个买... 同时网上也有很多代理IP共享网站,会把一些...

简单爬虫-爬取免费代理ip

环境:python3.6 主要用到模块:requests,PyQuery 代码比较简单,不做过多解释了 #!usr/bin/python # -*- coding: utf-8 -*- import requests from pyquery import PyQuery as pq class GetProxy(object):...

linux设置上网代理

1、网页上网 网页上网设置代理很简单,在firefox浏览器下 Edit-->>Preferences-->>Advanced-->>Network 在Connection下点击Settings,里面的manual proxy configuration里设置IP和PORT即可 2、yum代理设置 编辑文件为:/etc/...

练习--爬取xici可用代理IP

通过爬虫实现xici可以使用的代理IP 端口 主要代码: #!/usr/bin/env python #coding:utf8 import telnetlib from urllib import request import re class getXici(): def __init__(self): self.url...

解决Android Studio无法下载sdk的问题

因为google被墙了,android sdk无法下载。然后各种百度,都是说让设置代理,给的代理地址一般都是用的下面这个代理服务器: 大连东软信息学院镜像服务器地址: mirrors.neusoft.edu.cn 端口:80 可是我设了上面这个代理,根本还是下载不了sdk,崩溃~~~ 然后终于在这个网址找到了解决办法:http://ping.chinaz....