核心思想:

   1:从响应头中读取 【命中解流准确率最高】

   2:如果响应头中没有,打开流从源码中读取,【取舍,如果有一般在前30行会有,前100行中寻找】

3:如果还没有,根据字节码code位置,字符识别。【前三个字符揣测】

   4:最终依旧没有命中采用,大陆国标编码【概率接近于0 ,gb2312】

综合效果,尚无测试到编码有问题的站点。

 /**
* @declare:下载 自动识别编码
* @param url
* @return
* @author cphmvp
*/
public static StringBuffer downloadHtmlAutoCode(String url) {
StringBuffer sb = new StringBuffer();
BufferedReader bufferReader = null;
InputStream inputStream = null;
BufferedInputStream bufferedInputStream = null;
int tryNum = 0;
while (true) {
try {
if (tryNum > 1) {
String ecodingUrl = encodParamters(url);
urlModel = new URL(ecodingUrl);
} else {
urlModel = new URL(url);
}
httpURLConnection = (HttpURLConnection) urlModel
.openConnection();
httpURLConnection.setConnectTimeout(connectTimeout);
httpURLConnection.setReadTimeout(readTimeout);
// httpURLConnection.setInstanceFollowRedirects(false);
// httpURLConnection.setFollowRedirects(true);
httpURLConnection
.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)");
String redirectUrl = httpURLConnection.getURL().toString();
if (!redirectUrl.equals(url)) {
LOG.info(url + "重定向后为" + redirectUrl);
}
// 得到响应流
inputStream = httpURLConnection.getInputStream();
if (null == inputStream)
continue;
String charSetHeader = httpURLConnection
.getHeaderField("Content-Type");
bufferedInputStream = new BufferedInputStream(inputStream);
String charSet = null;
// 第一步先从响应头header判断
if (charSetHeader != null) {
Pattern p = Pattern.compile("charset=[\"']?(.*)['\"]?");
Matcher m = p.matcher(charSetHeader);
if (m.find()) {
charSet = m.group(1).trim();
}
}
// System.out.println(bufferedInputStream.available() > 0);
// System.out.println(bufferedInputStream.markSupported());
// 第二步 从源码中【meta http-equiv="content-type" 】判断
// if (null == charSet) {
// charSet = getEncode(bufferedInputStream);
// System.out.println("---->charSet: 读流识别出来的编码" + charSet);
// } // 排除非html格式 只有一两行的状况
if (null == charSet
&& charSetHeader.toLowerCase().contains("html")) {
// 缓冲区设置大些, read走的信息小于 这个值,就能reset 回来。
bufferedInputStream.mark(102400);
bufferReader = new BufferedReader(new InputStreamReader(
bufferedInputStream));
int lineNum = 1;
String inputLine;
// reset 在读至流的末尾是无法生效,故限制前100行找,找不到 放弃
while ((inputLine = bufferReader.readLine()) != null
&& lineNum < 100) {
if (inputLine.toLowerCase().contains("charset")) {
charSet = RegexUtils.getString(inputLine,
"charset=[\"']?(.*?)[\"']", 1);
LOG.info("自动识别出编码:" + charSet);
// 第一次匹配到后 ,不再往下判断,减少判断行数,及误判概率
break;
}
lineNum++;
inputLine = null;
}
// 第三步奏 穿插补录步奏
if (null == charSet) {
byte[] head = new byte[3];
bufferedInputStream.read(head);
if (head[0] == -1 && head[1] == -2)
charSet = "UTF-16";
if (head[0] == -2 && head[1] == -1)
charSet = "Unicode";
if (head[0] == -17 && head[1] == -69 && head[2] == -65)
charSet = "UTF-8";
} // 通道回溯
bufferedInputStream.reset();
} // 第四步奏指向默认 utf-8
charSet = (charSet == null ? defaultEncoding : charSet);
// 第五步奏按照正确编码解码响应流
bufferReader = new BufferedReader(new InputStreamReader(
bufferedInputStream, charSet));
String inputLine;
while ((inputLine = bufferReader.readLine()) != null) {
sb.append(inputLine + "\n");
inputLine = null;
}
if (bufferReader != null)
try {
bufferReader.close();
} catch (IOException e) {
LOG.error(e);
}
if (httpURLConnection != null)
httpURLConnection.disconnect();
break;
} catch (Exception e) {
if (tryNum++ == 3) {
LOG.error("download page error [ " + urlModel + " ] ");
return null;
}
LOG.warn(tryNum + "次下载失败");
}
}
return sb; }

crawler_httpurlconnection_自动编码识别的更多相关文章

  1. 我的Vim配置(自动补全/树形文件浏览)

    配置文件的下载路径在这里  http://files.cnblogs.com/files/oloroso/vim.configure.xz.gz 这实际上是一个 xz 格式的文件,添加的 gz 文件后 ...

  2. Linux中vi显示中文乱码的问题

    由于在windows下默认是gb编码,而我的vim默认是utf-8(gedit默认也是utf-8),所以打开会成乱码.修改了一下配置文件,使vi支持gb编码就好了.$vi ~/.vimrclet &a ...

  3. 编码自动识别工具 uchardet

    本文转自网络 最近在给OpenCC做图形界面,遇到一个问题:OpenCC默认只能转换utf-8文本,其他编码像GB18030,BIG5只能转换成utf-8以后,才能用OpenCC转换.这个问题说大不大 ...

  4. Vim的行号、语法显示等设置(.vimrc文件的配置)以及乱码解决

    在终端下使用vim进行编辑时,默认情况下,编辑的界面上是没有显示行号.语法高亮度显示.智能缩进 等功能的.为了更好的在vim下进行工作,需要手动设置一个配置文件:.vimrc.在启动vim时,当前用户 ...

  5. VIM 乱码终极解决

    原文链接:http://blog.163.com/mageng11@126/blog/static/1408083742012128105645169/ 关于vim乱码,这篇文章讲的很详细,mark一 ...

  6. vim 如何编辑 GB2312 编码的文件?

    vim 如何编辑 GB2312 编码的文件? 彻底搞清楚字符编码: ASCII, ISO_8859, GB2312,UCS, Unicode, U 结合file和iconv命令转换文件的字符编码类型 ...

  7. cygwin配置个人环境,android模拟器root映象和Babun

    零.Windows命令行个人设置 @echo off :: Temporary system path at cmd startup ::set PATH=%PATH%;"C:\Progra ...

  8. face recognition[翻译][深度人脸识别:综述]

    这里翻译下<Deep face recognition: a survey v4>. 1 引言 由于它的非侵入性和自然特征,人脸识别已经成为身份识别中重要的生物认证技术,也已经应用到许多领 ...

  9. 自动编码(AE)器的简单实现

    一.目录 自动编码(AE)器的简单实现 一.目录 二.自动编码器的发展简述 2.1 自动编码器(Auto-Encoders,AE) 2.2 降噪自编码(Denoising Auto-Encoders, ...

随机推荐

  1. OWIN 为WebAPI

    OWIN 为WebAPI 宿主 跨平台 OWIN是什么? OWIN的英文全称是Open Web Interface for .NET. 如果仅从名称上解析,可以得出这样的信息:OWIN是针对.NET平 ...

  2. 单链表的实现---SingleLinkedList

    单链表的实现,定义为SingleLinkedList class Node<AnyType>{ //结点Node类 public AnyType data; public Node< ...

  3. jquery 判断当前上传文件大小限制上传格式 搭配thinkphp实现上传即预览(模拟异步上传)

    在web开发中,最纠结的一项就是文件上传,最近由于项目需要前后摸索了四天在这里分享给大家.如有不足,望指出!! 前台:jquery.easyui.html 后台:thinkphp 主要涉及语言:jqu ...

  4. UVA 1411 - Ants(二分图完美匹配)

    UVA 1411 - Ants 题目链接 题意:给定一些黑点白点,要求一个黑点连接一个白点,而且全部线段都不相交 思路:二分图完美匹配,权值存负的欧几里得距离,这种话,相交肯定比不相交权值小,所以做一 ...

  5. Oracle 11g 的PL/SQL函数结果缓存

    模拟Oracle性能诊断艺术做了两个试验样品.书上说的不承担RELIES_ON.果缓存的失效操作(result_cache RELIES_ON(test1,test2)).试验证明不正确,函数f1() ...

  6. iOS编程之前

    iOS编程之前 更新:帖子已经重新被更新过,以便能更好的兼容Xcode 5和iOS 7.       至今为止,已经超过6000位读者加入了这个iOS免费教程.首先,我要感谢这些加入我们社区的朋友.在 ...

  7. 开源通讯组件ec

    跨平台开源通讯组件elastic communication elastic communication是基于c#开发支持.net和mono的通讯组件(简称EC),EC的主要目的简化mono和.net ...

  8. RH033读书笔记(14)-Lab 15 Switching Users and Setting a Umask

    Lab 15 Switching Users and Setting a Umask Goal: Become familiar with the use of several essential c ...

  9. 复制(6)——分发者(Distributor)

    如简介中提到,分发者(Distributor)是SQLServer 复制过程的核心组件.因为它是控制和执行实际的数据移动的过程,并且存放了发布(Publications)和订阅(Subscriptio ...

  10. ios save image to album

    - (void)savePhotoToAlbum { ZoomScrollView *zoomScrollView = (ZoomScrollView*)[self.scrollView viewWi ...