核心思想:

   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. Android 它们的定义ContentProvider和ContentObserver充分利用

    在他们的定义ContentProvider结合ContentObserver一起使用时,自己写的ContentProvider,在运行完insert.delete和update后,要手动地调用getC ...

  2. Windows 8实例教程系列 - 布局控制

    原文:Windows 8实例教程系列 - 布局控制 与传统应用类似,Windows store应用允许开发人员通过布局控件管理应用UI. 本篇将讨论Windows8布局设计控制. Windows 8布 ...

  3. * 类描写叙述:字符串工具类 类名称:String_U

    /****************************************** * 类描写叙述:字符串工具类 类名称:String_U * ************************** ...

  4. 2013成都邀请赛J称号||HDU4725 The Shortest Path in Nya Graph(spfa+slf最短的优化)

    职务地址:HDU 4725 这题卡了好长时间了,建图倒是会建,可是不会最短路的算法优化,本以为都须要堆去优化的,打算学了堆之后再来优化.可是昨晚CF的一道题..(那题也是不优化过不了..)然后我就知道 ...

  5. 【Android基础】AndroidManifest常用权限permission整理

    android.permission.ACCESS_COARSE_LOCATION 通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米 android.permi ...

  6. hadoop出现namenode running as process 18472. Stop it first.

    hadoop出现namenode running as process 18472. Stop it first.等等,类别似几个的出现. namenode running as process 32 ...

  7. 12本最优秀的Android开发电子书强力推荐

    如今已经是手机互联网时代,手机应用越来越普及.Android作为基本的手机操作系统.吸引了众多开发人员開始为Android系统开发应用. 假设你正在开发或者准备进行Android的开发,我们今天推荐的 ...

  8. GoldenGate组态(四)它veridata组态

    GoldenGate组态(四)它veridata组态 环境: Item Source System Target System Platform Red Hat Enterprise Linux Se ...

  9. 鸟哥Linux私房菜 基础学习篇读书笔记(10):Linux磁盘和文件系统管理(3)

    本文总结了Linux操作系统来管理我们的硬盘和文件系统需要使用命令.当我们在系统中增加一个硬盘驱动器.什么是我们需要去通过这个硬盘就可以真正使用步骤?下面步骤: (1)对磁盘进行分区,新建能够使用的分 ...

  10. 他们控制的定义-DragButton

    一个.叙述性说明 可拖动Button 两.无图无真相 这是用在实际工程效果图.和demo不太一样. 三.源代码 https://github.com/mentor811/Demo_DragButton ...