Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java实现Ip代理池

Java实现Ip代理池

作者头像
全栈程序员站长
发布于 2022-06-27 13:35:40
发布于 2022-06-27 13:35:40
99400
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
设置Ip代理很多时候都会有用到,尤其是在写爬虫相关项目的时候。虽然自己目前没有接触这种需求,但由于最近比较闲,就写着当作练习吧

爬取代理IP

爬取

关于爬取代理IP,国内首先想到的网站当然是 西刺代理 。首先写个爬虫获取该网站内的Ip吧。

先对 国内Http代理 标签页面进行爬取,解析页面使用的Jsoup ,这里大概代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 private List<IPBean> crawl(String api, int index){ 
   
        String html = HttpUtils.getResponseContent(api + index);
        System.out.println(html);

        Document document = Jsoup.parse(html);
        Elements eles = document.selectFirst("table").select("tr");

        for (int i = 0; i < eles.size(); i++){ 
   
            if (i == 0) continue;
            Element ele = eles.get(i);
            String ip = ele.children().get(1).text();
            int port = Integer.parseInt(ele.children().get(2).text().trim());
            String typeStr = ele.children().get(5).text().trim();

            int type;
            if ("HTTP".equalsIgnoreCase(typeStr))
                type = IPBean.TYPE_HTTP;
            else
                type = IPBean.TYPE_HTTPS;

            IPBean ipBean = new IPBean(ip, port, type);
            ipList.add(ipBean);
        }
        return ipList;
    }

对某些不明白的变量,可以参考我Github 其中关键的就是css选择器语法,这里需要注意的是不要乱加空格,不然会导致找不到出现空指针。 css选择器语法具体参考这里 , 这里就不讲解了。

爬取的信息包括 ip地址、端口号、和代理类型(http或https), 这三个信息我放在IPBean这个类里面。

过滤

上面爬取完成后,还要进一步过滤,筛选掉不能使用的。

筛选大概原理就是先设置上代理,然后请求某个网页,若成功则代表此代理ip有效。 其中请求成功的标志我们可以直接获取请求的返回码,若为200即成功。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /** * 检测代理ip是否有效 * * @param ipBean * @return */
    public static boolean isValid(IPBean ipBean) { 
   
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipBean.getIp(), ipBean.getPort()));
        try { 
   
            URLConnection httpCon = new URL("https://www.baidu.com/").openConnection(proxy);
            httpCon.setConnectTimeout(5000);
            httpCon.setReadTimeout(5000);
            int code = ((HttpURLConnection) httpCon).getResponseCode();
            System.out.println(code);
            return code == 200;
        } catch (IOException e) { 
   
            e.printStackTrace();
        }
        return false;
    }

注意这里要设置两个超时,连接超时和读取超时。连接超时还好,它默认只是有点长;然而读取超时如果不设置,它好像就会一直阻塞着。 时间设置为5s就够了,毕竟如果ip有效的话,会很快就请求成功的。这样过滤后,就得到有效的代理ip了

设置代理

单次代理

单次代理表示只在这一次连接中有效,即每次都需要代理。

http方式的代理非常简单,在URL对象的openConnection方法中加上个Proxy对象即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipBean.getIp(), ipBean.getPort()));

 connection = (HttpsURLConnection) new URL(url).openConnection(proxy);

https 稍微复杂点了,中间加上了ssl协议

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /** * @param url * @param headerMap 请求头部 * @param ipBean * @return * @throws Exception */
    public static String getResponseContent(String url, Map<String, List<String>> headerMap, IPBean ipBean) throws Exception { 
   
        HttpsURLConnection connection = null;

        // 设置代理
        if (ipBean != null) { 
   
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipBean.getIp(), ipBean.getPort()));

            connection = (HttpsURLConnection) new URL(url).openConnection(proxy);

            if (ipBean.getType() == IPBean.TYPE_HTTPS) { 
   
                SSLContext sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, new TrustManager[]{ 
   new TrustAnyTrustManager()}, new java.security.SecureRandom());
                connection.setSSLSocketFactory(sslContext.getSocketFactory());
                connection.setHostnameVerifier(new TrustAnyHostnameVerifier());
            }
        }

        if (connection == null)
            connection = (HttpsURLConnection) new URL(url).openConnection();

        // 添加请求头部
        connection.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36");
        if (headerMap != null) { 
   
            Iterator<Map.Entry<String, List<String>>> iterator = headerMap.entrySet().iterator();
            while (iterator.hasNext()) { 
   
                Map.Entry<String, List<String>> entry = iterator.next();
                List<String> values = entry.getValue();
                for (String value : values)
                    connection.setRequestProperty(entry.getKey(), value);
            }
        }

        InputStream inputStream = connection.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

        StringBuilder stringBuilder = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) { 
   
            stringBuilder.append(line);
        }
        reader.close();
        inputStream.close();
        return stringBuilder.toString();
    }


    private static class TrustAnyTrustManager implements X509TrustManager { 
   

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
   
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
   
        }

        public X509Certificate[] getAcceptedIssuers() { 
   
            return new X509Certificate[]{ 
   };
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier { 
   
        public boolean verify(String hostname, SSLSession session) { 
   
            return true;
        }
    }

这里https方法参考了 这篇博客

全局代理

直接上代码,就几行代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package util;

import other.IPBean;

/** * @author Asche * @github: https://github.com/asche910 * @date 2019年1月19日 */
public class ProxyUtils { 
   

    /** * 设置全局代理 * @param ipBean */
    public static void setGlobalProxy(IPBean ipBean){ 
   
        System.setProperty("proxyPort", String.valueOf(ipBean.getPort()));
        System.setProperty("proxyHost", ipBean.getIp());
        System.setProperty("proxySet", "true");
    }

}

需要注意一点就是全局只是在该java项目中生效,它不会更改系统中的代理。

检测

设置完代理后,也可以用另外一种方法来判断是否代理成功,即直接获取当前ip地址。 这里我使用的是 https://www.ipip.net/ip.html 这个网站,请求获取html后再解析得到自己的当前ip

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 private static final String MY_IP_API = "https://www.ipip.net/ip.html";

    // 获取当前ip地址,判断是否代理成功
    public static String getMyIp() { 
   
        try { 
   
            String html = HttpUtils.getResponseContent(MY_IP_API);

            Document doc = Jsoup.parse(html);
            Element element = doc.selectFirst("div.tableNormal");

            Element ele = element.selectFirst("table").select("td").get(1);

            String ip = element.selectFirst("a").text();

            // System.out.println(ip);
            return ip;
        } catch (Exception e) { 
   
            e.printStackTrace();
        }
        return null;
    }

优化

emmm 优化些啥呢???

速度

爬取ip时就几个网页,优化估计效果不大。而真正耗时的是检测ip是否有效,因此这里采用多线程,对每个ip的检测请求使用一个线程,最后副线程全部结束后再统计出有多少有效ip。然而问题又来了,怎么判断所有副线程全部结束了呢??? 脑中立刻想到的是join方法,然而仔细想想,才发现这样并不可取。最佳方法应该是设置一个计数器,每个线程结束后计数器加一,然后在主线程循环判断计数器的值是否与线程总数相等即可。由于涉及到并发,需要给某些方法加上锁。这里我代码中实现了,可以参考github

持久化

emmm 由于目前只是练练手,并没有这样的需求,比较懒, ( ̄▽ ̄)* 所以这个需求暂时放放吧,以后有时间再写

最后github入口:Asche910

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/133017.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年6月9,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
爬虫(第一篇) IP代理池
搞虫子的都知道,IP代理是必要的方法,为什么?这个大家知道就好了,最近写了个IP代理池,给大家围观一下:开始。
全栈程序员站长
2022/09/06
4570
解决PKIX问题:unable to find valid certification path to requested target【X509TrustManager】
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
奋飛
2019/08/15
2.6K0
Java工具集-网络工具(HttpUtils)
简单工具类 写作初衷:由于日常开发经常需要用到很多工具类,经常根据需求自己写也比较麻烦 网上好了一些工具类例如commom.lang3或者hutool或者Jodd这样的开源工具,但是 发现他们之中虽然设计不错,但是如果我想要使用,就必须要引入依赖并且去维护依赖,有些 甚至会有存在版本编译不通过问题,故此想要写作一个每个类都可以作为独立工具类使用 每个使用者只需要复制该类,到任何项目当中都可以使用,所以需要尊从以下两个原则才能 做到.在此诚邀各位大佬参与.可以把各自用过的工具,整合成只依赖JDK
cwl_java
2019/10/26
3.4K0
【Java】已解决:javax.net.ssl.SSLHandshakeException: SSL
在Java开发过程中,SSL(Secure Sockets Layer)握手异常是一个常见的网络通信错误,特别是在使用HTTPS协议进行安全通信时。本文将详细分析javax.net.ssl.SSLHandshakeException: SSL这一异常的背景、可能的原因,并通过代码示例帮助您理解和解决这一问题。
屿小夏
2024/09/13
3K0
使用Java进行网络采集:代理IP与参数传递详解
在Java编程语言中,参数传递机制是一个常见的讨论话题。理解这一点对于编写高效且无错误的Java代码至关重要。本文将探讨Java的参数传递机制,解析其究竟是“按引用传递”还是“按值传递”,并结合网络爬虫技术的实例,展示如何在实际应用中理解和利用这一机制。
jackcode
2024/06/05
1230
使用Java进行网络采集:代理IP与参数传递详解
http请求的方法里怎么设置信任所有ssl证书?(PKIX path building failed)
工作中,有时候需要跨系统调用。这个时候HttpURLConnection,而现在很多网站都是用的是HTTPS。我们知道HTTPS都是有证书的。证书有的是花钱买的,有的没有花钱。这请情况下,有时候,有些https请求,就不是可信任的。
凯哥Java
2019/06/28
2K0
http请求的方法里怎么设置信任所有ssl证书?(PKIX path building failed)
HttpClient工具类
基于restTemplate的httpClient通用工具类。 方案 import lombok.extern.slf4j.Slf4j; import org.springframework.http.*; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.Re
earthchen
2020/09/24
1.1K0
仿12306查询火车票功能
首先感谢http://www.zuidaima.com/share/1861712958622720.html对我的帮助,我在此基础上修改了页面的显示, 先上效果吧 public class Sear
xiangzhihong
2018/02/01
9100
仿12306查询火车票功能
自从用了 OkHttp,别的都完全不想用了!
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/03/04
1.1K0
鸿蒙 网络请求的各种实现方式(原生+okhttp+okhttputils+zzrhttp)【鸿蒙 专题2】
最近看了一下鸿蒙的网络请求部分的内容(这部分主要还是按照鸿蒙开发文档里面提到 java ui,js ui的网络请求请大家查看官方的文档即可)那么废话不多说我们正式开始。
徐建国
2021/12/08
3.4K1
鸿蒙 网络请求的各种实现方式(原生+okhttp+okhttputils+zzrhttp)【鸿蒙 专题2】
【Java爬虫】004-Jsoup学习笔记(补充:网页内容获取相关)
User-Agent和Referer从列表中随机挑选一个(防止被网站反爬虫程序发现);
訾博ZiBo
2025/01/06
1330
【Java爬虫】004-Jsoup学习笔记(补充:网页内容获取相关)
Java爬虫与SSL代理:实际案例分析与技术探讨
网络爬虫成为获取互联网数据的重要工具之一,然而,随着网络安全意识的提高,许多网站开始采用SSL加密来保护数据传输的安全性。本文将介绍如何使用Java编程语言结合SSL代理技术来实现网络爬虫,并通过实际案例分析和技术探讨来展示其应用价值。
小白学大数据
2024/01/29
2460
如何利用Java和Kotlin实现动态网页内容抓取
动态网页内容通常是通过JavaScript动态加载的,传统的静态网页抓取工具(如简单的HTTP请求)无法直接获取这些内容。因此,我们需要借助一些技术手段来模拟浏览器行为,或者直接解析动态加载的数据。
小白学大数据
2025/02/09
1240
Java封装OkHttp3工具类,用着贼舒服
说实在话,用过挺多网络请求工具,有过java原生的,HttpClient3和4,但是个人感觉用了OkHttp3之后,之前的那些完全不想再用了。怎么说呢,代码轻便,使用起来很很很灵活,响应快,比起HttpClient好用许多。当然,这些是我个人观点,不喜勿喷。
猿天地
2021/07/12
4.8K2
神器 | 教你使用 JAVA 开发 类似【百度翻译】功能
需求:使用java来实现一个类似‘百度翻译’的工具 项目下载地址:链接:https://pan.baidu.com/s/1R2hHU7sz7SGbGmCEYDVWYQ 密码:m0o1 技术:java、
码神联盟
2018/07/31
3840
神器 | 教你使用 JAVA 开发 类似【百度翻译】功能
springboot项目里面,发送http请求的get方法,post方法,ssl方法的工具类
A 项目要调用B项目一共接口,远程调用,有的B接口是post请求,有的是get请求,所以写一个工具类,只需要传url 和参数就可以了
一写代码就开心
2022/09/27
9340
https请求,Java代码忽略https证书:解决No subject alternative names present问题
https请求,Java代码忽略https证书:解决No subject alternative names present问题
oktokeep
2024/10/09
2160
JDK原生的HttpURLConnection请求实例
不想说啥,上代码! package com.my.https; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.security.SecureRandom; import j
JQ实验室
2022/02/09
2780
[问题记录]-PKIX-path-building-failed问题
Springboot请求外部https接口,由于ssl证书信任问题会导致PKIX path building failed问题。具体体现在请求小程序接口时,出现以上错误。
Java开发者之家
2021/06/17
1.7K0
【Java爬虫】006-URLConnection与HttpURLConnection(网页内容获取)
URLConnection是java.net包中的一个抽象类,其主要用于实现应用程序与URL之间的通信;
訾博ZiBo
2025/01/06
1870
推荐阅读
相关推荐
爬虫(第一篇) IP代理池
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验