JavaScript-如何高效、准确、自动识别网页编码

发布于 2017-02-26 16:20:24 字数 367 浏览 1315 评论 4

我知道的有两种途径获取网页的编码信息:
其一、通过服务器返回的header里的charset变量获取
其二、通过页面里的meta 信息获取

正常情况下,如果服务器或者页面有提供这两个参数,而且参数是正确的。

但是现实抓取网页时,经常会出现以下几种情况:
1.这两个参数缺失了
2.这两个参数虽然都提供了,但是不一致
3.这两个参数提供了,但是与网页实际的编码不一致

我现在通过php里面有个mb_detect函数,貌似识别字符串编码,但他的准确率就不好说了,因为编码的自动识别是一个概率事件,只有当被识别的字符串的长度足够大( 比如超过300个字)时,才能比较可靠。

除了这个之外,还有其它方式可以实现吗?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浮生未歇 2017-07-22 18:40:10

希望这两个函数能对你有点帮助:

判断是否是utf8编码

function is_utf8($word)
{
return (preg_match("/^([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}/",$word) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}$/",$word) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){2,}/",$word) == true);
}

判断是否是gb2312编码

function is_gb2312($str)
{
for($i=0; $i<strlen($str); $i++) {
$v = ord( $str[$i] );
if( $v > 127) {
if( ($v >= 228) && ($v <= 233) )
{
if( ($i+2) >= (strlen($str) - 1)) return true; // not enough characters
$v1 = ord( $str[$i+1] );
$v2 = ord( $str[$i+2] );
if( ($v1 >= 128) && ($v1 <=191) && ($v2 >=128) && ($v2 <= 191) ) // utf编码
return false;
else
return true;
}
}
}
return true;
}

晚风撩人 2017-07-16 13:39:34

使用由mozzila提供的universalchardet模块,据说比IE自带的识别模块准确率高很多。

universalchardet项目的地址在:http://www-archive.mozilla.org/projects/intl/chardet.html

目前universalchardet支持python java dotnet等
C#版本:
http://code.google.com/p/nuniversalchardet/

具体参考这篇文章:
http://www.cnblogs.com/tdlian/archive/2011/11/25/2263054.html

这篇文章提供了各种语言的移植,遗憾的是没有发现PHP的移植:
http://www.byvoid.com/blog/tag/universalchardet/

晚风撩人 2017-05-16 09:23:57

我说下原理哈,我们知道如何HTTP协议中如果没有指定编码的情况下,这时候浏览器所用的方法是统计,统计其实就是猜,每种情况去取一定的字符数,对每种的编码都做统计,概率性高的就命中,不过为了提高统计速度,统计应该先从几种常用的字符串开始ANSIIC、UTF8、UNICODE,除了这个之外服务器在抓取网页内容时,可以先通过IP猜测所属的国家,然后根据国家找到对应的编码,这样效率会提高很多。

夜无邪 2017-03-06 03:55:41

java使用cpdetector进行编码自动识别,识别率比较高

下载链接:http://sourceforge.net/projects/cpdetector/files/?source=navbar

使用实例:

 import info.monitorenter.cpdetector.io.ASCIIDetector;
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.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.Charset;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EncodingDetector {

private static final Logger log = LoggerFactory .getLogger(EncodingDetector.class);

private static final CodepageDetectorProxy detector = CodepageDetectorProxy .getInstance();

static {
/*-------------------------------------------------------------------------
ParsingDetector可用于检查HTML、XML等文件或字符流的编码,构造方法中的参数用于
指示是否显示探测过程的详细信息,为false不显示。
---------------------------------------------------------------------------*/
detector.add(new ParsingDetector(false));
/*--------------------------------------------------------------------------
JChardetFacade封装了由Mozilla组织提供的JChardet,它可以完成大多数文件的编码
测定。所以,一般有了这个探测器就可满足大多数项目的要求,如果你还不放心,可以
再多加几个探测器,比如下面的ASCIIDetector、UnicodeDetector等。
---------------------------------------------------------------------------*/
detector.add(JChardetFacade.getInstance());
// ASCIIDetector用于ASCII编码测定
detector.add(ASCIIDetector.getInstance());
// UnicodeDetector用于Unicode家族编码的测定
detector.add(UnicodeDetector.getInstance());
}

public static String getCharset(File file) {
Charset charset = null;
try {
charset = detector.detectCodepage(new BufferedInputStream(new FileInputStream(file)),1000);
log.info("file [{}] > charset:{}", file, null != charset ? charset.name() : null);
} catch (Exception e) {
log.info("file [{}] error > ", file, e);
}
return null != charset ? charset.name() : null;
}

public static String getCharset(InputStream is) {
Charset charset = null;
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(is);
charset = detector.detectCodepage(bufferedInputStream,1000);
bufferedInputStream.reset();
} catch (Exception e) {
}
return null != charset ? charset.name() : null;
}

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文