Java爬虫 (五) -- httpClient进阶:使用代理(详细解析)

一、前言

好久没有写博客,趁着难得的空闲时间更新一波。前面几期讲到的主要包括了爬虫开发中的页面获取、页面解析两个方面的知识,套用二八原则,可以解决80%的工作。但是其他的20%的工作,就可能要用到我们80%的时间和精力去研究。这个就是我接下去几期要讲的。这期主要是讲一些实际场景下可能需要用到的httpClient设置,大都是我在实际开发中需要用到的,都算是一些小知识点,但是还是希望能能够记录总结一下。

接下去的博文都会标注写文章时参考的资料,以便参考。(感觉跟写论文一样,2333~)

二、代理

代理是爬虫技术中很重要的一项。因为有一些网站会有相应的安全策略。例如检测一段时间内,某个IP地址的访问次数,如果访问频率过高,说明你不是正常访客,然后禁止你这个IP的访问。

应对这种机制有两种手段:

  1. 放慢抓取速度,减小对目标网站的访问压力
  2. 设置代理IP,实现高频率抓取,但是这需要多个稳定的代理IP。

代理ip资源可以自己去写爬虫去爬代理网站,去验证可用性,当然这种方式不稳定,而且可用的ip资源并不是很多。你也可以搭建自己的代理服务器。还有些爬虫每天的抓取任务可能需要消耗10多万的ip资源,这个时候一般是需要使用一些商业的代理ip商的服务了。

当然在本文中,不会涉及如何搭建代理服务器和如何获取ip资源。主要介绍如何在httpClient中配置ip。如果以后有机会涉及到,再写文章吧。

三、实战

由于httpClient十分灵活,设置代理也有很多种方式。

3.1 设置httpClient

  • 最简单的一种:
// proxyHost -- 代理ip; proxyPort -- 端口号
HttpHost proxy = new HttpHost("proxyHost", proxyPort, "HTTP");
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet get = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(proxy, get);

这种方式要注意一点:new HttpHost()是支持指定协议类型的,但是httpClient不默认支持socks协议,所以如果我们把上面代码中的协议改成new HttpHost("proxyHost", proxyPort, "SOCKS"),会报错。

> org.apache.http.conn.UnsupportedSchemeException: socks protocol is not supported

还有两种方法是官方文档上推荐的:

  • 使用RequestConfig:
CloseableHttpClient httpclient = HttpClients.createDefault();       
HttpGet request = new HttpGet(url);
 
request.setConfig(
    RequestConfig.custom()
        .setProxy(new HttpHost("proxyHost", proxyPort, "HTTP"))
        .build()
);
         
CloseableHttpResponse response = httpclient.execute(request);
  • 使用RoutePlanner
// 1. 设置默认参数的方法
HttpHost proxy = new HttpHost("proxyHost"proxyPort); 
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); 
CloseableHttpClient httpclient = HttpClients.custom(). 
        setRoutePlanner(routePlanner)
        .build();
// 2. 使用标准的JRE代理选择器,即使用系统代理
SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(
        ProxySelector.getDefault());
CloseableHttpClient httpclient = HttpClients.custom()
        .setRoutePlanner(routePlanner)
        .build();

3.2 RoutePlanner

这个类单独拿出来讲一下。在httpClient的请求执行过程中,HttpRoute首先出现在请求执行链的入口处,在进入请求执行链之前,使用routePlanner来根据目标主机、请求和请求上下文来计算出HttpRoute. 下列代码摘自InternalHttpClient类源码片段:

@Override  
protected CloseableHttpResponse doExecute(  
        final HttpHost target,  
        final HttpRequest request,  
        final HttpContext context) throws IOException, ClientProtocolException {  
          
    ...  
          
    <strong>final HttpRoute route = determineRoute(target, wrapper, localcontext);</strong>  
    // 开始调用请求执行链  
    return this.execChain.execute(<strong>route</strong>, wrapper, localcontext, execAware);  
      
    ...  
}  
  
private HttpRoute determineRoute(  
        final HttpHost target,  
        final HttpRequest request,  
        final HttpContext context) throws HttpException {  
    HttpHost host = target;  
    if (host == null) {  
        host = (HttpHost) request.getParams().getParameter(ClientPNames.DEFAULT_HOST);  
    }  
    <strong>return this.routePlanner.determineRoute(host, request, context);</strong>  
} 

HttpClient默认计算HttpRoute的算法大致为:

  • 如果在请求上下文context里能找到代理,直接用来创建HttpRoute对象;
  • 如果没有设置代理,并且没有使用系统属性,用DefaultRoutePlanner,计算出的HttpRoute的proxyChain为null;
  • 如果设置了代理,用DefaultProxyRoutePlanner,计算出的HttpRoute的proxyChain里只有一个,就是设置的代理;
  • 如果没有设置代理,但使用系统数据,用SystemDefaultRoutePlanner,它使用JDK的ProxySelector,从JVM配置和系统配置里获取代理链,再从代理链里寻找第一个HTTP类型的代理,来创建HttpRoute对象。如果没有找到HTTP类型的代理,计算出的HttpRoute的proxyChain为null.

对应到上面我们的代理配置的几种方法可以分为两种,1.给httpClient配置代理;2.配置系统代理。

3.3 设置系统代理

实战中最后一种方法就是使用系统代理的方法。那么怎么设置系统代理呢?

这里说的系统代理配置指的 JVM 系统,而不是操作系统。

3.3.1 Java System

可以通过下面的方式来分别设置 HTTP 代理,HTTPS 代理和 SOCKS 代理:

// HTTP 代理,只能代理 HTTP 请求
System.setProperty("http.proxyHost", "127.0.0.1");
System.setProperty("http.proxyPort", "9876");
 
// HTTPS 代理,只能代理 HTTPS 请求
System.setProperty("https.proxyHost", "127.0.0.1");
System.setProperty("https.proxyPort", "9876");
 
// 同时支持代理 HTTP/HTTPS 请求
System.setProperty("proxyHost", "127.0.0.1");
System.setProperty("proxyPort", "9876");

// SOCKS 代理,支持 HTTP 和 HTTPS 请求
// 注意:如果设置了 SOCKS 代理就不要设 HTTP/HTTPS 代理
System.setProperty("socksProxyHost", "127.0.0.1");
System.setProperty("socksProxyPort", "1080");

3.3.2 JVM 命令行参数

在IDE项目启动设置中设置JVM 参数。

如果idea的话如下:

image

参考资料

  1. http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e485
  2. http://blog.csdn.net/zjysource/article/details/52945494
  3. http://www.aneasystone.com/archives/2015/12/java-and-http-using-proxy.html
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,051评论 25 707
  • 时间像折扇在张驰与收缩间溜走, 岁月像油纸伞撑起的雨露从我们心间滑过, 相识的时光仿佛在昨日, 相拥的岁月伴我们前...
    静谧夜空阅读 226评论 0 1
  • * 如果你说你在下午四点来,从三点钟开始,我就开始感觉很快乐,时间越临近,我就越来越感到快乐。 * 到了四点钟的时...
    回眸最初阅读 173评论 0 1