httpclient是apache的一个项目:http://hc.apache.org/

文档比較完好:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/

这里就不啰嗦了,主要是在做demo的时候遇到的一些问题在这里总结一下:

[引用请注明出处http://blog.csdn.net/bhq2010/article/details/9210007]

1、使用连接池

虽说http协议时无连接的,但毕竟是基于tcp的,底层还是须要和server建立连接的。对于须要从同一个网站抓取大量网页的程序,应该使用连接池,否则每次抓取都和Web网站建立连接、发送请求、获得响应、释放连接,一方面效率不高,还有一方面稍不小心就会疏忽了某些资源的释放、导致网站拒绝连接(非常多网站会拒绝同一个ip的大量连接、防止DOS攻击)。

连接池的例程例如以下:

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(2);
HttpHost googleResearch = new HttpHost("research.google.com", 80);
HttpHost wikipediaEn = new HttpHost("en.wikipedia.org", 80);
cm.setMaxPerRoute(new HttpRoute(googleResearch), 30);
cm.setMaxPerRoute(new HttpRoute(wikipediaEn), 50);

SchemaRegistry的作用是注冊协议的默认port号。PoolingClientConnectionManager是池化连接管理器,即连接池,setMaxTotal设置连接池的最大连接数,setDefaultMaxPerRoute设置每一个路由(http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e467)上的默认连接个数,setMaxPerRoute则单独为某个网站设置最大连接个数。

从连接池中获取http client也非常方面:

DefaultHttpClient client = new DefaultHttpClient(cm);

2、设置HttpClient參数

HttpClient须要设置合适的參数,才干更好地工作。默认的參数可以应付少量的抓取工作,但找到一组合适的參数往往能改善特定情况下的抓取效果。设置參数的例程例如以下:

		DefaultHttpClient client = new DefaultHttpClient(cm);
Integer socketTimeout = 10000;
Integer connectionTimeout = 10000;
final int retryTime = 3;
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, socketTimeout);
client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout);
client.getParams().setParameter(CoreConnectionPNames.TCP_NODELAY, false);
client.getParams().setParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 1024 * 1024);
HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler()
{
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context)
{
if (executionCount >= retryTime)
{
// Do not retry if over max retry count
return false;
}
if (exception instanceof InterruptedIOException)
{
// Timeout
return false;
}
if (exception instanceof UnknownHostException)
{
// Unknown host
return false;
}
if (exception instanceof ConnectException)
{
// Connection refused
return false;
}
if (exception instanceof SSLException)
{
// SSL handshake exception
return false;
}
HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent)
{
// Retry if the request is considered idempotent
return true;
}
return false;
} };
client.setHttpRequestRetryHandler(myRetryHandler);
5、6行分别设置了Socket最大等待时间、连接最大等待时间(单位都是毫秒)。socket等待时间是指从网站下载页面和数据时,两个数据包之间的最大时间间隔,超过这个时间间隔,httpclient就觉得连接出了故障。连接最大等待时间则是指和网站建立连接时的最大等待时间,超过这个时间网站不给回应,则觉得网站无法连接。第7行设置httpclient不使用NoDelay策略。假设启用了NoDelay策略,httpclient和网站之间数据传输时将会尽可能及时地将发送缓冲区中的数据发送出去、而不考虑网络带宽的利用率,这个策略适合对实时性要求高的场景。而禁用了这个策略之后,数据传输会採用Nagle's
algorithm发送数据,该算法会充分顾及带宽的利用率,而不是传输数据的实时性。第8行设置socket缓冲区的大小(单位为字节),默认是8KB。
HttpRequestRetryHandler是负责处理请求重试的接口。在该接口的内部类中实现RetryRequest方法就可以。当httpclient发送请求之后出现异常时,就会调用这种方法。在该方法中依据已运行请求的次数、请求内容、异常信息推断是否继续重试,若继续重试返回true,否则返回false。

3、设置request header

设置request header也是非常重要的,比方设置User-Agent能够将抓取程序伪装成浏览器,骗过一些站点对爬虫的检查,设置Accept-Encoding为gzip能够建议站点以压缩格式数据传输、节省带宽等等。例程例如以下:
		HttpResponse response = null;
HttpGet get = new HttpGet(url);
get.addHeader("Accept", "text/html");
get.addHeader("Accept-Charset", "utf-8");
get.addHeader("Accept-Encoding", "gzip");
get.addHeader("Accept-Language", "en-US,en");
get.addHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.160 Safari/537.22");
response = client.execute(get);
HttpEntity entity = response.getEntity();
Header header = entity.getContentEncoding();
if (header != null)
{
HeaderElement[] codecs = header.getElements();
for (int i = 0; i < codecs.length; i++)
{
if (codecs[i].getName().equalsIgnoreCase("gzip"))
{
response.setEntity(new GzipDecompressingEntity(entity));
}
}
}
return response;

各个header的含义參考http://kb.cnblogs.com/page/92320/

须要的都设上就好了。假设须要非常多不同的User-Agent轮流使用(同一个User-Agent对一个网站频繁訪问easy被识别为爬虫而杯具),能够去网上找,也能够在自己的chrome浏览器里看或者用抓包软件抓。值得注意的是设置了Accept-Encoding为gzip之后,对网站回复的内容要检查是否是压缩格式的,假设是,则解压缩,如上面例程中第9行之后的代码所看到的。

Java HttpClient使用小结的更多相关文章

  1. java并发包小结(二)

    接上一篇 java并发包小结(一):http://blog.csdn.net/aalansehaiyang52/article/details/8877579 Future 接口Future 接口允许 ...

  2. java IO 流小结

    java IO 流小结 java流类图结构 流的分类 按方向 输入流 输出流 按类型 字节流 字符流 结论:只要是处理纯文本数据,就优先考虑使用字符流. 除此之外都使用字节流.

  3. java单向加密算法小结(2)--MD5哈希算法

    上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...

  4. java Http编程小结

    1:什么是HTTP? 超文本传输协议(HyperText Transfer Protocol -- HTTP)是一个设计来使客户端和服务器顺利进行通讯的协议. HTTP在客户端和服务器之间以reque ...

  5. java httpclient发送json 请求 ,go服务端接收

    /***java客户端发送http请求*/package com.xx.httptest; /** * Created by yq on 16/6/27. */ import java.io.IOEx ...

  6. [Java] HttpClient有个古怪的stalecheck选项

    打开stale check会让每次http请求额外消耗15毫秒.而且stalecheck选项缺省是打开的. 这有必要吗???? 在局域网里面调用web api service的时候会死人的. http ...

  7. Java HttpClient伪造请求之简易封装满足HTTP以及HTTPS请求

    HttpClient简介 HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 JDK 的 jav ...

  8. java HttpClient 忽略证书的信任的实现 MySSLProtocolSocketFactory

    当不需要任何证书访问https时,java中先实现一个MySSLProtocolSocketFactory类忽略证书的信任 package com.tgb.mq.producer.utils; imp ...

  9. java httpclient post xml demo

    jar archive: http://archive.apache.org/dist/httpcomponents/ 基于httpclient 2.0 final的demo(for jdk1.5/1 ...

随机推荐

  1. Android Studio导入项目慢的问题

    在Github下载的项目,导入studio时非常慢,原因是下载的项目中的gradle与当前gradle不匹配,需要更新包. 解决办法:修改下载包中的文件 1. xxx-project/.idea/gr ...

  2. Scalaz(26)- Lens: 函数式不可变对象数据操作方式

    scala中的case class是一种特殊的对象:由编译器(compiler)自动生成字段的getter和setter.如下面的例子: case class City(name:String, pr ...

  3. ASP.NET中后台注册js脚本攻略(转)

    用Page.ClientScript.RegisterClientScriptBlock 和Page.ClientScript.RegisterStartupScript:区别:   1.使用Page ...

  4. Android 微信分享信息

    随着微信越来越火,越来越多的应用要求有分享到微信的功能.虽然有很多平台都帮集成有分享功能,比如友盟.但是个人觉得友盟集成的东西太多了,自己封装得太过分了,很多资源文件也要带进去,所以感觉不是怎么好,所 ...

  5. ORACLE的rownum用法讲解

    如果选择踏足,终有一天你会爱上这条路. 今天讲讲ORACLE中关于ROWNUM的用法: 一.简单介绍一下ROWNUM是什么,可以用来干什么. 答:ROWNUM是一个序列,会根据sql语句自动给你加上一 ...

  6. 【分布式事务】阿里fescar

    一.什么是Fescar FESCAR(Fast & Easy Commit And Rollback) 是一个用于微服务架构的分布式事务解决方案,它的特点是高性能且易于使用,旨在实现简单并快速 ...

  7. 网络嗅探与欺骗(第一二部分)非平台——P201421410029

    中国人民公安大学 Chinese people’ public security university 网络对抗技术 实验报告   实验二 网络嗅探与欺骗     学生姓名 李政浩 年级 2014 区 ...

  8. java传统的文件拷贝 相当于两个大缸需要通过一个勺子(字节数组)一点一点运过去

  9. Redis主从切换

    案例 易车网:http://www.greatops.net/?id=232 redis主从切换:http://www.cnblogs.com/itdragon/p/7932178.htmlhttps ...

  10. Linux的系统引导

    启动引导: 1.主机加电自检,加载BIOS信息 2.读取MBR的引导文件[grub lilo] 3.引导linux内核 4.运行第一个进程init pid=1 5.进入相应的运行级别[0-6] 6.运 ...