1. 程式人生 > >構建一個給爬蟲使用的代理IP池

構建一個給爬蟲使用的代理IP池

做網路爬蟲時,一般對代理IP的需求量比較大。因為在爬取網站資訊的過程中,很多網站做了反爬蟲策略,可能會對每個IP做頻次控制。這樣我們在爬取網站時就需要很多代理IP。

代理IP的獲取,可以從以下幾個途徑得到:

  • 從免費的網站上獲取,質量很低,能用的IP極少

  • 購買收費的代理服務,質量高很多

  • 自己搭建代理伺服器,穩定,但需要大量的伺服器資源。

本文的代理IP池是通過爬蟲事先從多個免費網站上獲取代理IP之後,再做檢查判斷IP是否可用,可用的話就存放到MongoDB中,最後展示到前端的頁面上。

獲取可用Proxy

獲取代理的核心程式碼是ProxyManager,它採用RxJava2來實現,主要做了以下幾件事:

第一,建立ParallelFlowable,針對每一個提供免費代理IP的頁面並行地抓取。對於不瞭解ParallelFlowable的同學,可以看我之前的文章

RxJava 之 ParallelFlowable

  1. Flowable.fromIterable(ProxyPool.proxyMap.keySet())

  2. .parallel()

第二,針對每一個頁面進行抓取,返回List

  1. map(newFunction<String,List<Proxy>>(){

  2. @Override

  3. publicList<Proxy> apply(String s)throwsException{

  4. try{

  5. returnnewProxyPageCallable(s).call();

  6. }catch(Exception e){

  7.                            e

    .printStackTrace();

  8. }

  9. returnnull;

  10. }

  11. })

第三,對每一個頁面獲取的代理IP列表進行校驗,判斷是否可用

  1. flatMap(newFunction<List<Proxy>,Publisher<Proxy>>(){

  2. @Override

  3. publicPublisher<Proxy> apply(List<Proxy> proxies)throwsException{

  4. if(proxies ==null)returnnull;

  5. List<Proxy> result = proxies

  6. .stream()

  7. .parallel

    ()

  8. .filter(newPredicate<Proxy>(){

  9. @Override

  10. publicboolean test(Proxy proxy){

  11. HttpHost httpHost =newHttpHost(proxy.getIp(), proxy.getPort(), proxy.getType());

  12. returnHttpManager.get().checkProxy(httpHost);

  13. }

  14. }).collect(Collectors.toList());

  15. returnFlowable.fromIterable(result);

  16. }

  17. })

第四,依次儲存到proxyList

  1. subscribe(newConsumer<Proxy>(){

  2. @Override

  3. publicvoid accept(Proxy proxy)throwsException{

  4.                        log.debug("Result Proxy = "+proxy.getType()+"://"+proxy.getIp()+":"+proxy.getPort());

  5.                        proxy.setLastSuccessfulTime(newDate().getTime());

  6. ProxyPool.proxyList.add(proxy);

  7. }

  8. });

附上完整的流程圖