crawler_httpurlconnection_自动编码识别
核心思想:
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_自动编码识别的更多相关文章
- 我的Vim配置(自动补全/树形文件浏览)
配置文件的下载路径在这里 http://files.cnblogs.com/files/oloroso/vim.configure.xz.gz 这实际上是一个 xz 格式的文件,添加的 gz 文件后 ...
- Linux中vi显示中文乱码的问题
由于在windows下默认是gb编码,而我的vim默认是utf-8(gedit默认也是utf-8),所以打开会成乱码.修改了一下配置文件,使vi支持gb编码就好了.$vi ~/.vimrclet &a ...
- 编码自动识别工具 uchardet
本文转自网络 最近在给OpenCC做图形界面,遇到一个问题:OpenCC默认只能转换utf-8文本,其他编码像GB18030,BIG5只能转换成utf-8以后,才能用OpenCC转换.这个问题说大不大 ...
- Vim的行号、语法显示等设置(.vimrc文件的配置)以及乱码解决
在终端下使用vim进行编辑时,默认情况下,编辑的界面上是没有显示行号.语法高亮度显示.智能缩进 等功能的.为了更好的在vim下进行工作,需要手动设置一个配置文件:.vimrc.在启动vim时,当前用户 ...
- VIM 乱码终极解决
原文链接:http://blog.163.com/mageng11@126/blog/static/1408083742012128105645169/ 关于vim乱码,这篇文章讲的很详细,mark一 ...
- vim 如何编辑 GB2312 编码的文件?
vim 如何编辑 GB2312 编码的文件? 彻底搞清楚字符编码: ASCII, ISO_8859, GB2312,UCS, Unicode, U 结合file和iconv命令转换文件的字符编码类型 ...
- cygwin配置个人环境,android模拟器root映象和Babun
零.Windows命令行个人设置 @echo off :: Temporary system path at cmd startup ::set PATH=%PATH%;"C:\Progra ...
- face recognition[翻译][深度人脸识别:综述]
这里翻译下<Deep face recognition: a survey v4>. 1 引言 由于它的非侵入性和自然特征,人脸识别已经成为身份识别中重要的生物认证技术,也已经应用到许多领 ...
- 自动编码(AE)器的简单实现
一.目录 自动编码(AE)器的简单实现 一.目录 二.自动编码器的发展简述 2.1 自动编码器(Auto-Encoders,AE) 2.2 降噪自编码(Denoising Auto-Encoders, ...
随机推荐
- ZOJ 3635 Cinema in Akiba[ 大规模阵列 ]
门户:problemCode=3635">ZOJ 3635 Cinema in Akiba Time Limit: 3 Seconds Memory Limit: 65536 ...
- 我收集的sonar参考资料
sonarQube代码质量管理工具环境筹建笔记 http://www.myexception.cn/open-source/1307345.html 配置sonar.jenkins进行持续审查 htt ...
- hdu3790最短路径问题
题意是这种,给你一个无向图, 每条边有距离和花费, 假设从第一个点到末点的最短路不唯一, 则输出最短路长度以及最少的花费. 否则输出长度和花费即可. 用传说中的链式向前星优化了一下边的存储, 写了个s ...
- Discuz 楼主帖子采集
try { ; i < ; i++) { var html = GetHtmls("http://bbs.fobshanghai.com/viewthread.php?tid=3885 ...
- 《Pro Android Graphics》读第三季度票据
Android Frame Animation: XML, Concepts and Optimization Frame Animation Concepts: Cels, Framerate, a ...
- HDN2048(交错复发)
上帝.神与神 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- Android之Handler的postDelayed()使用方法
这是一种创建多线程信息功能 用法: 1,首先创建一个Handler物 Handler handler=new Handler(); 2.然后创建一个Runnable物 Runnable runnabl ...
- 腾讯2014在广州站实习生offer经验(TEG-开发背景)
研究在过去的一年是linux 什么系统编程和网络编程.比较熟悉的语言c/c++,python只写一些测试client.是后台开发类,比方前面笔面的网易CC(面完hr后挂).大概3月15号就在腾讯 jo ...
- nodejs 递归创建目录
nodejs没有递归创建目录的方法,以前创建的时候是将目录通过path.sep,然后再一步步判断,这个方法在windows下面遇到盘符的时候,然后蛋疼了.今天又用到了这个功能,突然想到了另外一种方法, ...
- WebService之CXF注解报错(一)
WebService之CXF注解 1.详细报错例如以下 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] ...