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


    天地连站群可以根据用户输入的初始关键词,获取该关键词搜索引擎的搜索结果,然后逐条获取这些相关文章的内容。这样就需要面对无数网页的各种编码。为了解决这个问题,引入了下面的解决办法:
    在引入编码自动识别前,我们有两种途径获取网页的编码信息:
    其一、通过服务器返回的header里的charset变量获取
    其二、通过页面里的meta 信息获取

    正常情况下,如果服务器或者页面有提供这两个参数,而且参数是正确的,那我们抓取网页时就不存在编码的问题了。

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

    为了尽可能的自动的获取所有网页的编码,所以引入了编码自动识别

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

    所有的浏览器都支持自动识别网页编码,比如IE ,firefox 等
     

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

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

    目前universalchardet支持python java dotnet等,php不知道支持不

    我比较喜欢写C#,因为VS2010 + viemu是我的至爱,所以我使用了C#版;universalchardet的C#移植版本有很多 ,我使用的版本:http://code.google.com/p/nuniversalchardet/


    下面是一段使用的例子,相比其他的C#实现有一点点繁琐:



     
    复制代码
    Stream mystream = res.GetResponseStream();
    MemoryStream msTemp = new MemoryStream();
    int len = 0;
    byte[] buff = new byte[512];

    while ((len = mystream.Read(buff, 0, 512)) > 0)
    {
    msTemp.Write(buff, 0, len);

    }
    res.Close();

    if (msTemp.Length > 0)
    {
    msTemp.Seek(0, SeekOrigin.Begin);
    byte[] PageBytes = new byte[msTemp.Length];
    msTemp.Read(PageBytes, 0, PageBytes.Length);

    msTemp.Seek(0, SeekOrigin.Begin);
    int DetLen = 0;
    byte[] DetectBuff = new byte[4096];
    CharsetListener listener = new CharsetListener();
    UniversalDetector Det = new UniversalDetector(null);
    while ((DetLen = msTemp.Read(DetectBuff, 0, DetectBuff.Length)) > 0 && !Det.IsDone())
    {
    Det.HandleData(DetectBuff, 0, DetectBuff.Length);
    }
    Det.DataEnd();
    if (Det.GetDetectedCharset()!=null)
    {
    CharSetBox.Text = "OK! CharSet=" + Det.GetDetectedCharset();
    PageBox.Text = System.Text.Encoding.GetEncoding(Det.GetDetectedCharset()).GetString(PageBytes);
    }
    }
    复制代码


    上面已经可以识别网页的编码了,看起来很简单,不是吗?如果你以前一直被这个问题困扰,而且有幸看到这个帖子,那么,这一类型的问题就彻底解决了,再也不会因为不知道网页编码,抓取了一堆的?????号回来;嗯,生活从此是那么美好。。。。
    我当时也是这么想的

    上面讲到编码识别是一种概率事件,所以无法保证100%正确识别,因此后来我还是发现了一些因为识别错误导致返回??号的情况,难道这个问题真的没办法完美解决吗?

    世间不会有完美的事情,我深信这点。

    好在我们只要完善的解决方案就可以了:我们要让程序知道什么时候自动识别错误了,如果错误了,就去读取和使用服务器和网页提供的编码信息。

    我开动脑筋想了一下,想出了一个土办法:对于我们中国人来说,存在编码问题的就是中文网页。如果一个中文网页被正确识别了,里面肯定会有中文字符。bingo,我从网上找了出现频度在top N的汉字(比如“的”字),只要网页里包含这个N个汉字之一,则识别成功,否则识别失败。

    这样下来,网页编码识别问题基本上可以轻松解决了。

    后记:
    不知道有没有人对这个感兴趣,有的话,我还想写一篇这个方面的文章,标题也想好了:《网络IO,无处不异步》,这里指的网络IO只的是http request

    天地连站群使用了这个编码识别方法,解决了采集领域一个重大的问题,从此我可以把精力从这个问题里抽出来,研究解决其他的问题了。

  • 相关阅读:
    面向对象:范式与思想
    每个人都应该懂点函数式编程
    Lambda 表达式-即匿名函数----Lambda演算-即匿名函数的等价推演过程-- => define as
    Side effect (computer science)
    系统理论
    参量与变量、指针、函数、对象
    面向对象和结构化程序设计的区别X
    面向对象编程与面向过程编程的区别(翻译版)
    2015 Objective-C 新特性
    Comparison of programming paradigms
  • 原文地址:https://www.cnblogs.com/chenying99/p/2778110.html
Copyright © 2020-2023  润新知