Java实现Ip代理池
设置Ip代理很多时候都会有用到,尤其是在写爬虫相关项目的时候。虽然自己目前没有接触这种需求,但由于最近比较闲,就写着当作练习吧
爬取代理IP
爬取
关于爬取代理IP,国内首先想到的网站当然是 西刺代理 。首先写个爬虫获取该网站内的Ip吧。
先对 国内Http代理 标签页面进行爬取,解析页面使用的Jsoup ,这里大概代码如下
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即成功。
/**
* 检测代理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对象即可
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipBean.getIp(), ipBean.getPort()));
connection = (HttpsURLConnection) new URL(url).openConnection(proxy);
https 稍微复杂点了,中间加上了ssl协议
/**
* @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方法参考了 这篇博客
全局代理
直接上代码,就几行代码
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
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
Java实现Ip代理池的更多相关文章
- 免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作简易流量爬虫
前言 我们之前的爬虫都是模拟成浏览器后直接爬取,并没有动态设置IP代理以及UserAgent标识,本文记录免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作 ...
- 开源IP代理池续——整体重构
开源IP代理池 继上一篇开源项目IPProxys的使用之后,大家在github,我的公众号和博客上提出了很多建议.经过两周时间的努力,基本完成了开源IP代理池IPProxyPool的重构任务,业余时间 ...
- 记一次企业级爬虫系统升级改造(六):基于Redis实现免费的IP代理池
前言: 首先表示抱歉,春节后一直较忙,未及时更新该系列文章. 近期,由于监控的站源越来越多,就偶有站源做了反爬机制,造成我们的SupportYun系统小爬虫服务时常被封IP,不能进行数据采集. 这时候 ...
- 爬取西刺ip代理池
好久没更新博客啦~,今天来更新一篇利用爬虫爬取西刺的代理池的小代码 先说下需求,我们都是用python写一段小代码去爬取自己所需要的信息,这是可取的,但是,有一些网站呢,对我们的网络爬虫做了一些限制, ...
- scrapy_随机ip代理池
什么是ip代理? 我们电脑访问网站,其实是访问远程的服务器,通过ip地址识别是那个机器访问了服务器,服务器就知道数据该返回给哪台机器,我们生活中所用的网络是局域网,ip是运营商随机分配的,是一种直接访 ...
- Python爬虫之ip代理池
可能在学习爬虫的时候,遇到很多的反爬的手段,封ip 就是其中之一. 对于封IP的网站.需要很多的代理IP,去买代理IP,对于初学者觉得没有必要,每个卖代理IP的网站有的提供了免费IP,可是又很少,写了 ...
- 5 使用ip代理池爬取糗事百科
从09年读本科开始学计算机以来,一直在迷茫中度过,很想学些东西,做些事情,却往往陷进一些技术细节而蹉跎时光.直到最近几个月,才明白程序员的意义并不是要搞清楚所有代码细节,而是要有更宏高的方向,要有更专 ...
- python开源IP代理池--IPProxys
今天博客开始继续更新,谢谢大家对我的关注和支持.这几天一直是在写一个ip代理池的开源项目.通过前几篇的博客,我们可以了解到突破反爬虫机制的一个重要举措就是代理ip.拥有庞大稳定的ip代理,在爬虫工作中 ...
- python爬虫实战(三)--------搜狗微信文章(IP代理池和用户代理池设定----scrapy)
在学习scrapy爬虫框架中,肯定会涉及到IP代理池和User-Agent池的设定,规避网站的反爬. 这两天在看一个关于搜狗微信文章爬取的视频,里面有讲到ip代理池和用户代理池,在此结合自身的所了解的 ...
随机推荐
- Android sutdio单元测试 简单使用步骤
1.简介 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证.比如一个函数,一个方法等 2.添加依赖 dependencies { testCompile 'junit: ...
- HTML5移动开发即学即用(双色) 王志刚 pdf扫描版
HTML5已经广泛应用于各智能移动终端设备上,而且绝大部分技术已经被各种最新版本的测览器所支持:逐一剖析HTML5标准中包含的最新技术,详细介绍了HTML5新标准中提供的各种API,各种各样的应用实例 ...
- C# enum 枚举 反射
枚举遍历 public enum EMyType { [System.ComponentModel.Description("A类型")] TypeA = 1, [System.C ...
- .Net Core 项目区域请求设置
.net core 和asp.net MVC区域请求有个区别,这里重点记录一下 asp.net MVC 区域请求直接是/区域名称/控制名称/方法名称,其他不需要设置任何东西,而Core 项目这样请求路 ...
- SqlServer给一个表增加多个字段语法
添加字段语法 alter table table_name add column_name +字段类型+ 约束条件 给一个表增加多个字段: use NatureData go alter table ...
- WinForm中自定义搜索框(水印、清空按钮、加载中图标)
public partial class CustomSearchBar : TextBox { private readonly Label lblwaterText = new Label(); ...
- libcurl坑
code = curl_easy_setopt(conn, CURLOPT_URL, ca.strUrl.c_str()); 要char* 不能string
- loj #2305. 「NOI2017」游戏
#2305. 「NOI2017」游戏 题目描述 小 L 计划进行 nnn 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 AAA.BBB. ...
- window.open()弹出窗口被拦截
之前有个需求是输入一些配置,然后点击预览,通过接口保存配置并返回预览页面链接,在新页面中打开链接.后来测试一直说没有新页面打开,我一看,原来是被浏览器拦截了. 原因如下: 浏览器只有在认为click和 ...
- ubuntu15.04下安装docker
##获得更多资料欢迎进入我的网站或者 csdn或者博客园 最近听说docker很火,不知道什么东西,只知道是一个容器,可以跨平台.闲来无事,我也来倒弄倒弄.本文主要介绍:ubuntu下的安装,以及基 ...