近日在做爬虫功能,爬取网页内容,然后对内容进行语义分析,最后对网页打标签,从而判断访问该网页的用户的属性。

在爬取内容时,遇到乱码问题。故需对网页内容编码格式做判断,方式大体分为三种:一、从header标签中获取Content-Type=#Charset;二、从meta标签中获取Content-Type=#Charset;三、根据页面内容分析编码格式。

其中一/二方式并不能准确指示该页面的具体编码方式,周全考虑,加入第三种方式。

第三种方式引入开源jar包info.monitorenter.cpdetector,可以从github上面下载(https://github.com/onilton/cpdetector-maven-repo/tree/master/info/monitorenter/cpdetector/1.0.10)下载。

package com.mobivans.encoding;

import info.monitorenter.cpdetector.io.ASCIIDetector;
import info.monitorenter.cpdetector.io.ByteOrderMarkDetector;
import info.monitorenter.cpdetector.io.CodepageDetectorProxy;
import info.monitorenter.cpdetector.io.JChardetFacade;
import info.monitorenter.cpdetector.io.ParsingDetector;
import info.monitorenter.cpdetector.io.UnicodeDetector; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map; import org.apache.commons.io.IOUtils; public class PageEncoding {
/** 测试用例
* @param args
*/
public static void main(String[] args) { // String charset = getEncodingByHeader("http://blog.csdn.net/liuzhenwen/article/details/4060922");
// String charset = getEncodingByMeta("http://blog.csdn.net/liuzhenwen/article/details/4060922");
String charset = getEncodingByContentStream("http://blog.csdn.net/liuzhenwen/article/details/5930910"); System.out.println(charset);
} /**
* 从header中获取页面编码
* @param strUrl
* @return
*/
public static String getEncodingByHeader(String strUrl){
String charset = null;
try {
URLConnection urlConn = new URL(strUrl).openConnection();
// 获取链接的header
Map<String, List<String>> headerFields = urlConn.getHeaderFields();
// 判断headers中是否存在Content-Type
if(headerFields.containsKey("Content-Type")){
//拿到header 中的 Content-Type :[text/html; charset=utf-8]
List<String> attrs = headerFields.get("Content-Type");
String[] as = attrs.get(0).split(";");
for (String att : as) {
if(att.contains("charset")){
// System.out.println(att.split("=")[1]);
charset = att.split("=")[1];
}
}
}
return charset;
} catch (MalformedURLException e) {
e.printStackTrace();
return charset;
} catch (IOException e) {
e.printStackTrace();
return charset;
}
} /**
* 从meta中获取页面编码
* @param strUrl
* @return
*/
public static String getEncodingByMeta(String strUrl){
String charset = null;
try {
URLConnection urlConn = new URL(strUrl).openConnection();
//避免被拒绝
urlConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36");
// 将html读取成行,放入list
List<String> lines = IOUtils.readLines(urlConn.getInputStream());
for (String line : lines) {
if(line.contains("http-equiv") && line.contains("charset")){
// System.out.println(line);
String tmp = line.split(";")[1];
charset = tmp.substring(tmp.indexOf("=")+1, tmp.indexOf("\""));
}else{
continue;
}
}
return charset;
} catch (MalformedURLException e) {
e.printStackTrace();
return charset;
} catch (IOException e) {
e.printStackTrace();
return charset;
}
} /**
* 根据网页内容获取页面编码
* case : 适用于可以直接读取网页的情况(例外情况:一些博客网站禁止不带User-Agent信息的访问请求)
* @param url
* @return
*/
public static String getEncodingByContentUrl(String url) {
CodepageDetectorProxy cdp = CodepageDetectorProxy.getInstance();
cdp.add(JChardetFacade.getInstance());// 依赖jar包 :antlr.jar & chardet.jar
cdp.add(ASCIIDetector.getInstance());
cdp.add(UnicodeDetector.getInstance());
cdp.add(new ParsingDetector(false));
cdp.add(new ByteOrderMarkDetector()); Charset charset = null;
try {
charset = cdp.detectCodepage(new URL(url));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(charset);
return charset == null ? null : charset.name().toLowerCase();
} /**
* 根据网页内容获取页面编码
* case : 适用于不可以直接读取网页的情况,通过将该网页转换为支持mark的输入流,然后解析编码
* @param strUrl
* @return
*/
public static String getEncodingByContentStream(String strUrl) {
Charset charset = null;
try {
URLConnection urlConn = new URL(strUrl).openConnection();
//打开链接,加上User-Agent,避免被拒绝
urlConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"); //解析页面内容
CodepageDetectorProxy cdp = CodepageDetectorProxy.getInstance();
cdp.add(JChardetFacade.getInstance());// 依赖jar包 :antlr.jar & chardet.jar
cdp.add(ASCIIDetector.getInstance());
cdp.add(UnicodeDetector.getInstance());
cdp.add(new ParsingDetector(false));
cdp.add(new ByteOrderMarkDetector()); InputStream in = urlConn.getInputStream();
ByteArrayInputStream bais = new ByteArrayInputStream(IOUtils.toByteArray(in));
// detectCodepage(InputStream in, int length) 只支持可以mark的InputStream
charset = cdp.detectCodepage(bais, 2147483647);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return charset == null ? null : charset.name().toLowerCase();
}
}

注意的点:

1.info.monitorenter.cpdetector未在mvn-repository中开源,因而无法从mvn-repository中下载,需要将该jar下到本地,然后手动导入到本地repository,mvn命令如下:

mvn install:install-file -Dfile=jar包的位置 -DgroupId=该jar的groupId -DartifactId=该jar的artifactId -Dversion=该jar的version -Dpackaging=jar

然后在pom.xml中添加该jar的依赖

<!-- charset detector -->
<dependency>
<groupId>info.monitorenter.cpdetector</groupId>
<artifactId>cpdetector</artifactId>
<version>1.0.10</version>
</dependency>

2.JChardetFacade.getInstance()在引入antlr.jar和chardet.jar之前会报异常,在pom.xml中添加这两个jar的dependency:

<!-- antlr -->
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
<version>2.7.7</version>
</dependency>
<!-- ChardetFacade -->
<dependency>
<groupId>net.sourceforge.jchardet</groupId>
<artifactId>jchardet</artifactId>
<version>1.0</version>
</dependency>

如果是普通项目则无需关心pom.xml,直接把这三个jar包下载下来然后添加到该项目的环境中即可

java爬虫爬取网页内容前,对网页内容的编码格式进行判断的方式的更多相关文章

  1. Java爬虫爬取网站电影下载链接

    之前有看过一段时间爬虫,了解了爬虫的原理,以及一些实现的方法,本项目完成于半年前,一直放在那里,现在和大家分享出来. 网络爬虫简单的原理就是把程序想象成为一个小虫子,一旦进去了一个大门,这个小虫子就像 ...

  2. java爬虫爬取资源,小白必须会的入门代码块

    java作为目前最火的语言之一,他的实用性也在被无数的java语言爱好者逐渐的开发,目前比较流行的爬取资源,用java来做也更简单一些,下面是爬取网页上所有手机型号,参数等极为简便的数据 packag ...

  3. 一个简单java爬虫爬取网页中邮箱并保存

    此代码为一十分简单网络爬虫,仅供娱乐之用. java代码如下: package tool; import java.io.BufferedReader; import java.io.File; im ...

  4. java爬虫爬取的html内容中空格(&nbsp;)变为问号“?”的解决方法

    用java编写的爬虫,使用xpath爬取内容后,发现网页源码中的 全部显示为?(问号),但是使用字符串的replace("?", ""),并不能替换,网上找了一 ...

  5. 用Java爬虫爬取凤凰财经提供的沪深A股所有股票代号名称

    要爬取的凤凰财经网址:http://app.finance.ifeng.com/list/stock.php?t=hs 本作主要采用的技术是jsoup,相关介绍网页:https://www.jians ...

  6. java爬虫爬取https协议的网站时,SSL报错, java.lang.IllegalArgumentException TSLv1.2 报错

    目前在广州一家小公司实习,这里的学习环境还是挺好的,今天公司从业十几年的大佬让我检查一下几年前的爬虫程序是否还能使用…… 我从myeclipse上check out了大佬的程序,放到workspace ...

  7. Java爬虫爬取京东商品信息

    以下内容转载于<https://www.cnblogs.com/zhuangbiing/p/9194994.html>,在此仅供学习借鉴只用. Maven地址 <dependency ...

  8. Python爬虫 - 爬取百度html代码前200行

    Python爬虫 - 爬取百度html代码前200行 - 改进版,  增加了对字符串的.strip()处理 源代码如下: # 改进版, 增加了 .strip()方法的使用 # coding=utf-8 ...

  9. Python爬虫爬取数据的步骤

    爬虫: 网络爬虫是捜索引擎抓取系统(Baidu.Google等)的重要组成部分.主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份. 步骤: 第一步:获取网页链接 1.观察需要爬取的多 ...

随机推荐

  1. Django基础之form操作

    Form表单的功能 自动生成HTML表单元素 检查表单数据的合法性 如果验证错误,重新显示表单(数据不会重置) 数据类型转换(字符类型的数据转换成相应的Python类型) Form相关的对象包括 Wi ...

  2. 了解 Azure VM 的系统重启

    有时 Azure 虚拟机 (VM) 可能重启,即使没有明显原因,也没有证据表明用户发起重启操作. 本文列出了可导致 VM 重启的操作和事件,并针对如何避免意外重启问题或减少该问题影响提供见解. 配置 ...

  3. ASP.net Substitution 页面缓存而部分不缓存的实现方法

    在ASP.NET中要实现部分内容非缓存,而其它的都需要缓存输出,可以使用Substitution控件实现. <%@ Page Language="C#" AutoEventW ...

  4. CSV输入输出

    读取csv文件: import csv cf = open('D:\pywe.csv','rb') cf.readline() #读取标题行,光标移动到下一行(相当于调过标题行) for l in c ...

  5. 转移RMS模拟器

    在PowerShell中识别当前 RMS 模拟器 get-SCOMRMSemulator ?移至另一个管理服务器 –首先将一个新的RMS模拟器管理指定为一个变量 $MS = get-scommanag ...

  6. Python简介及编码

    首先Python是一种语言,因此根据其实现的不同,有Cpython, Jython, IronPython, Pypy等. Python执行流程 $ python /home/hello.py     ...

  7. VC 6.0 MFC关闭对话框在win7出现崩溃的情况

    Ctrl + W 掉出来class管理 添加OnDestory方法 void CPackUpItemToSetDlg::OnDestroy() { exit(1); CDialog::OnDestro ...

  8. [EffectiveC++]item07:declare destructors virtual in polymorphic base class

  9. scala当中的类型参数

    类型参数主要就是研究scala当中的类或者scala当中的方法的泛型 1.scala当中的类的泛型         object Demo8 {          def main(args: Arr ...

  10. redis连接被拒绝

    1,服务未启动: 执行:lsof -i :6379 isof-i命令查看是否开启进程 结果如下,证明开启 COMMAND     PID USER   FD   TYPE DEVICE SIZE/OF ...