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, ...
随机推荐
- 移动应用开发(IOS/android等一下)在一般图像缓存方案评述(附流程图)
在移动应用开发.我们经常从网络请求到该设备显示遇到的场景图片. 假设多次发动每个请求,废物流.浪费电.: 将图片持久化到磁盘也不失为一种策略:但每次从文件读取图片也存在一定的io开销,就算採用此策略, ...
- MSSQL连接字符串,你真的清楚吗?
原文:MSSQL连接字符串,你真的清楚吗? 几年前当我第一次面试时,考官发现我是个新手于是他让我写个连接字符串,虽然当时就知道X种连接字符串的写法,但是当时却没能写对一个,工作多年后我仍然不能写一个正 ...
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- SpringMVC+Mybatis(SMM)+mybatis-generate
java搭建 SpringMVC+Mybatis(SMM)+mybatis-generate 搭建SSM系统,首先要了解整个过程: 1.创建spring-mvc项目 2.在maven中添加要引用的ja ...
- 最小二乘法拟合非线性函数及其Matlab/Excel 实现(转)
1.最小二乘原理 Matlab直接实现最小二乘法的示例: close x = 1:1:100; a = -1.5; b = -10; y = a*log(x)+b; yrand = y + 0.5*r ...
- MySQL 正則表達式搜索
products表例如以下: 1. 基本字符匹配 使用正則表達式与LIKE的差别,正則表達式是在整个列搜索,仅仅要prod_name中包括了所搜索的字符就能够了,而LIKE假设不用通配符,那么要求pr ...
- 改变,从跨出第一步開始——记海大ITAEM团队首次IT讲座掠影
之前以前写了"行动带来力量,周三(5月7日)晚IT讲座通知",昨晚已经跨出了第一步.让我们还是看举办者骆宏的QQ空间的文字吧.尽管未能到现场助兴,但看着海大学子在不断挑战自己,进而 ...
- ZOJ 3820 2014ACM/ICPC牡丹江司B称号
3797714 2014 - 10 - 12 21:58 : 19 Accepted 3820 C++ 1350 70240 zz_1215 比較麻烦的一道题吧,開始的时候不停的段异常,后面知道是爆栈 ...
- 真实故事:网站遭遇DOS攻击
网站遭遇DOS攻击 一个.事件背景 长假对于IT人员来说是个短暂的休整时期,可IT系统却一时也不能停.越是节假日,越可能出大问题,以下要讲述的就是一起遭受DOS攻击的案例. 春节长假刚过完,小李 ...
- 默认情况下安装的应用程序C盘后提示权限不足,当你开始介意。。。
最近,不少用户抱怨的经销商.正在使用win 7我们的计算机系统上安装软件后,提示权限不够开放系统,无法启动软件. 在xp该系统是没有问题的.原因是,我们会选择在默认安装路径系统C-disk.和win ...