zoukankan      html  css  js  c++  java
  • WebSpider的编码问题(乱码)浅析

    这两天看到几篇关于WebSpider的文章。其中关于抓取网页出现的编码格式问题大家都比较感兴趣,以前在参与帮看网的开发时也遇到过。不过那时候忙于ITDB的BBS开发,没有时间去研究。今天看到解决网爬工具爬取页面信息出现乱码的问题 ,刚好最近离职赋闲在家。所以又挑起了我研究学习的兴趣。现在把我的“研究成果”和大家探讨下:
      下面我按照我解决问题的思路来行文
       1,要根本解决编码问题,先要从编码的理论入手。
       2,计算机是一门实践的科学,多动手尝试吧。

    一,和编码相关的理论知识:
     
    中文编码处理(1) -- 编码与字符集,我摘录几句:
      如果我们读不同编码的文件 到程序内部处理再保存程另一个文件 涉及到三次编码问题
      1 读入文件使用什么编码
      2 程序中使用什么编码
      3 写出文件使用什么编码
      看到这里。可以知道如果自以为先用某种格式把数据从流中读取出来,然后判断,再转换的方式处理编码问题,那么方法本身就错了。结果自然就是不可预期的。当然上面的话并不代表权威。仅仅做为一种分析的参考。

    二,http协议和html的规范关于如何得到一个页面的字符编码三种方法:
    1.An HTTP "charset" parameter in a "Content-Type" field.
    example:
    Content-Type: text/html; charset=EUC-JP

    2.A META declaration with "http-equiv" set to "Content-Type" and a value set for "charset".
    example:
    <META http-equiv="Content-Type" content="text/html; charset=EUC-JP">

    3.The charset attribute set on an element that designates an external resource.
    example:
    <A href="
    http://www.w3.org/" charset="ISO-8859-1">W3C Web site</A>

      现在先贴一段常见的抓取网页的代码,方便后续的讨论:

    WebRequest webRequest = WebRequest.Create(url);
    WebResponse webResponse 
    =
     webRequest.GetResponse();
     Stream stream 
    =
     webResponse.GetResponseStream();

     StreamReader sr 
    = new
     StreamReader(stream, Encoding.Default);
     
    string html =
     sr.ReadToEnd();
     
    return
     html;

    常见的识别编码格式都是要么从HttpWebResponse的ContentEncoding和CharacterSet去分析,要么从提取的网页里的分析(二列出的三种方法),现在的问题就出在既然HttpWebResponse的ContentEncoding和CharacterSet并不可靠。而要从流读数据必须指定编码,但现在并不能可靠的确定数据源的正确编码,而尝试用一种编码格式读然后转又会遭遇上叙一所说的问题。这让我想起了我以前写过的“由一道面试题引起的疑问与思考”里关于XML编码格式问题,里面谈到BOM(字节顺序标记)的问题,转其中的几句话:
     W3C定义了三条XML解析器如何正确读取XML文件的编码的规则:
     1,如果文挡有BOM(字节顺序标记,一般来说,如果保存为unicode格式,则包含BOM,ANSI则无),就定义了文件编码
     2,如果没有BOM,就查看XML声明的编码属性
     3,如果上述两个都没有,就假定XML文挡采用UTF-8编码

    其实网页也是一种文本格式的东西,其规则也应该类似,我搜索了下,找到更详细的资料:
     1,如果流中是以0xef, 0xbb, 0xbf开头的话,可以确定编码格式utf-8的
     2,如果流中是以0xff,0xfe开头的话,可以确定编码格式是utf-16的

    如果仅仅按照上面所列两种情况去判断的,还显然不够严谨,但是到目前为止,我还没找到更详细的关于各种编码的BOM的更多资料。
    写到这里,我不得不告诉你,上面的一切探索对于.net来说都是徒劳的,因为.net已经内置了这样的判断方法:
      StreamReader sr = new StreamReader(stream, Encoding.Default,true);
    就多加一个true,ms帮你完成BOM的检测。具体的你可以看MSDN的帮助文挡。

    我在开篇说到计算机是一门实践的科学,我测试了几个网页都没发现乱码问题。当然这并不表示就完全没有问题,只是一时没找到让它乱码的网页,如果你发现了,请你一定要告诉我。我们一起来研究下。

    最后,我想推翻我刚才的结论:上面的一切探索对于.net来说都是徒劳的;因为我看到下面的代码的时候,我知道why,而不仅仅是how !
    Reflector出来的StreamReader关于通过BOM检测编码格式的代码:

    DetectEncoding


    水平有限,不妥之处,欢迎指正。
     

  • 相关阅读:
    crontab 定时任务设置
    kafka如何保证消息得顺序性
    Spark Streaming和Kafka整合是如何保证数据零丢失
    docker学习之路(安装、使用)
    linux根文件系统 /etc/resolv.conf 文件详解
    Navicat Premium 12连接MySQL数据库出现Authentication plugin 'caching_sha2_password' cannot be loaded的解决方案
    window10 安装Mysql 8.0.17以及忘记密码重置密码
    ubantu安装mysql (解决配置密码问题)
    Navicat Premium 12 connection is being used以及查询sql文件保存位置
    离线安装PM2
  • 原文地址:https://www.cnblogs.com/kwklover/p/627173.html
Copyright © 2011-2022 走看看