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, ...
随机推荐
- OWIN 为WebAPI
OWIN 为WebAPI 宿主 跨平台 OWIN是什么? OWIN的英文全称是Open Web Interface for .NET. 如果仅从名称上解析,可以得出这样的信息:OWIN是针对.NET平 ...
- 单链表的实现---SingleLinkedList
单链表的实现,定义为SingleLinkedList class Node<AnyType>{ //结点Node类 public AnyType data; public Node< ...
- jquery 判断当前上传文件大小限制上传格式 搭配thinkphp实现上传即预览(模拟异步上传)
在web开发中,最纠结的一项就是文件上传,最近由于项目需要前后摸索了四天在这里分享给大家.如有不足,望指出!! 前台:jquery.easyui.html 后台:thinkphp 主要涉及语言:jqu ...
- UVA 1411 - Ants(二分图完美匹配)
UVA 1411 - Ants 题目链接 题意:给定一些黑点白点,要求一个黑点连接一个白点,而且全部线段都不相交 思路:二分图完美匹配,权值存负的欧几里得距离,这种话,相交肯定比不相交权值小,所以做一 ...
- Oracle 11g 的PL/SQL函数结果缓存
模拟Oracle性能诊断艺术做了两个试验样品.书上说的不承担RELIES_ON.果缓存的失效操作(result_cache RELIES_ON(test1,test2)).试验证明不正确,函数f1() ...
- iOS编程之前
iOS编程之前 更新:帖子已经重新被更新过,以便能更好的兼容Xcode 5和iOS 7. 至今为止,已经超过6000位读者加入了这个iOS免费教程.首先,我要感谢这些加入我们社区的朋友.在 ...
- 开源通讯组件ec
跨平台开源通讯组件elastic communication elastic communication是基于c#开发支持.net和mono的通讯组件(简称EC),EC的主要目的简化mono和.net ...
- 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 ...
- 复制(6)——分发者(Distributor)
如简介中提到,分发者(Distributor)是SQLServer 复制过程的核心组件.因为它是控制和执行实际的数据移动的过程,并且存放了发布(Publications)和订阅(Subscriptio ...
- ios save image to album
- (void)savePhotoToAlbum { ZoomScrollView *zoomScrollView = (ZoomScrollView*)[self.scrollView viewWi ...