httpclient对url编码的处理方式

HttpClient是Apache基金下jakarta commons项目中的一个小项目,该项目封装了对远程地址下载的一些功能,最新版本为3.0。该项目地址:http://jakarta.apache.org/commons/httpclient

最近在编写Spider的时候就用到了HttpClient。在使用过程中发现一个有趣现象:有些URL的编码方式是utf-8,有些URL的编码方式是gbk。他总能够正确识别,但是有些他又不能识别(抓取回来后是乱码)。调用的是:httpMethod.getResponseBodyAsString(); 方法。

在进行进一步分析时,发现他对在http头信息中有charset描述的就正确正常识别。如:

HTTP/1.1 200 OK
Connection: close
Content-Type: text/html; charset=utf-8
Set-Cookie: _session_id=066875c3c0530c06c0204b96db403560; domain=iteye.com; path=/
Vary: Accept-Encoding
Cache-Control: no-cache
Content-Encoding: gzip
Content-Length: 8512
Date: Fri, 16 Mar 2007 09:02:52 GMT
Server: lighttpd/1.4.13

而没有charset描述信息时,就会是乱码。再查看相关文档时,可以指定URL的编码方式。如:HttpClientParams.setContentCharset("gbk");,指定了编码后,就能够正确识别对应编码的URL了。问题出现了,因URL编码不一样,Spider不可能把URL的编码方式写死。并且只有在抓取回来后才知道编码是否正确。于是再仔细研究一下httpclient的源代码,发现他使用编码的顺序是:http头信息的charset,如果头信息中没有charset,则查找HttpClientParams的contentCharset,如果没有指定编码,则是ISO-8859-1。

/**
* Returns the character set from the Content-Type header.
*
* @param contentheader The content header.
* @return String The character set.
*/
protected String getContentCharSet(Header contentheader) {
LOG.trace("enter getContentCharSet( Header contentheader )");
String charset = null;
if (contentheader != null) {
HeaderElement values[] = contentheader.getElements();
// I expect only one header element to be there
// No more. no less
if (values.length == 1) {
NameValuePair param = values[0].getParameterByName("charset");
if (param != null) {
// If I get anything "funny"
// UnsupportedEncondingException will result
charset = param.getValue();
}
}
}
if (charset == null) {
charset = getParams().getContentCharset();
if (LOG.isDebugEnabled()) {
LOG.debug("Default charset used: " + charset);
}
}
return charset;
}


/**
* Returns the default charset to be used for writing content body,
* when no charset explicitly specified.
* @return The charset
*/
public String getContentCharset() {
String charset = (String) getParameter(HTTP_CONTENT_CHARSET);
if (charset == null) {
LOG.warn("Default content charset not configured, using ISO-8859-1");
charset = "ISO-8859-1";
}
return charset;
}
这个该死的iso-8859-1害了多少人啊(Tomcat对提交的数据处理默认也是iso-8859-1)!!

经过仔细思考后,决定httpclient再封装一次,思路如下:

先不设定HttpClientParams的charset;
executemethod后,再检查http头信息中的charset是否存在;
如果charset存在,返回httpMethod.getResponseBodyAsString(); ;
如果charset不存在,则先调用httpMethod.getResponseBodyAsString();得到html后,再分析html head的meta的charset <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">;
从meta中分析出charset后,设置到HttpClientParams的contentCharset;
再调用httpMethod.getResponseBodyAsString(),并返回该值。
经过以上思路处理后,发现抓回来的URL再也没有乱码了。爽!

以上步骤中,就是第四步稍微麻烦一些,不过,也可以利用第三方的html paser工具来分析meta的charset!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值