网络爬虫的乱码处理

摘要:
爬行器乱码有很多不同的问题。这里是对网络爬虫乱码处理的简要总结。这也是为什么很多人在使用框架编写爬虫时无从下手的原因。例如,成熟的Nutch在处理乱码时也相对简单,因此乱码仍然存在。因此,需要二次开发才能真正解决乱码问题。

    关于爬虫乱码有很多群友的各式各样的问题,下边简单总结下关于网络爬虫的乱码处理。注意,这里不仅是中文乱码,还包括一些如日文、韩文 、俄文、藏文之类的乱码处理,因为他们的解决方式 是一致的,故在此统一说明。

    网络爬虫,有两种选择,一是选择nutch、hetriex,二是自写爬虫,两者在处理乱码时,原理是一致的,但前者处理乱码时,要看懂源码后进行修改才可以,所以要废劲一些;而后者更自由方便,可以在编码处理时进行处理。这也是很多人在用框架写爬虫会出现各种各样的乱码时,无从下手的原因了,像比较成熟的nutch在处理乱码时也是比较简单的,所以依然会出现乱码,所以需要二次开发才能真正解决乱码问题。

    1、网络爬虫出现乱码的原因

        源网页编码和爬取下来后的编码转换不一致。如源网页为gbk编码的字节流,而我们抓取下后程序直接使用utf-8进行编码并输出到存储文件中,这必然会引起乱码,即当源网页编码和抓取下来后程序直接使用处理编码一致时,则不会出现乱码,此时再进行统一的字符编码也就不会出现乱码了。注意区分源网编码A、程序直接使用的编码B、统一转换字符的编码C。

        A、就是web page的服务器端编码

        B、抓取到的数据,原始情况为字节数组,它是由A来编码的,只有B=A时,才可以保证不出现乱码,否则当字符集不兼容时,总是会出现乱码,此步骤往往用于测试。

        C、统一转码是指得到网页的原始编码A后,再进行的统一编码,主要是为了将各个网页的数据统一成一类编码,往往选择字符集较大的utf-8为宜。

        每个网页都有自己的编码,像gbk、utf-8、iso8859-1,以及日文的jp系统编码、西欧、俄文等编码各不相同,当进行漫爬时总是会扩展出各种编码,有的爬虫是对web网页进行简单的编码识别再进行统一编码,有的是不做源网页的判断直接统一按utf-8来处理,这显然是会造成乱码情况。

    2、乱码的解决方法

       根据原因来找解决方法,就非常简单了。

       (1) 确定源网页的编码A

          编码A往往在网页中的三个位置,http header的content、网页的meta charset中、网页头中Document定义中。在获取源网页编码时,依次判断下这三部分数据即可,从前往后,优先级亦是如此。

          理论上这样做是对的,但国内一些网站确是很不符合规范,比如写的gbk,实际是utf-8,有的是写的utf-8,但实际是gbk,当然这是很少的一批网站,但确实存在。所以在确定网页编码时,应该对该特殊情况做特别处理,如中文检查、默认编码等策略。

         还有一种情况,是以上三者中均没有编码信息,则一般采用cpdetector等第三方网页编码智能识别工具来做,其原理即为统计字节数组的特征来概率计算得出实际编码,有一定的准确率,但我实际的时候发现,其准确率还是很有限的。

         但综合上述的三种编码确认方式后,几乎可以完全解决中文乱码问题,在我基于nutch1.6二次开发的网络爬虫系统中,编码正确经统计可以达到99.99%,也证明了上述方法策略的可行性。

       (2)程序通过编码B对源网页数据还原

            显然,这里的B是要和A相等的,在java中,如得到的源网页的字节数组为source_byte_array,那么经过转换为String str=new String(source_byte_array,B);即在内存上这些字节数组对应的字符是正确编码和可显示的,此时的打印输出结果是正常的,此步骤往往用于debug或是控制台输出做测试。

       (3) 统一转码

            网络爬虫系统数据来源很多,不可能使用数据时,再转化为其原始的数据,假使这样做是很废事的。所以一般的爬虫系统都要对抓取下来的结果进行统一编码,从而在使用时做到一致对外,方便使用。此时即是在(2)的基础上,做一个统一的编码转换即可,在java中的实现如下

         源网页的字节数组为source_byte_array        

         转换为正常的字符串:  String normal_source_str=new String(source_byte_array,C),此时可以用java api直接存储,但往往不直接写入字符串,因为一般的爬虫存储都是多个源网页存储到一个文件中,所以要记录字节偏移量,故下一步。

         再将得到的str转换为统一的编码C格式的字节数组,则byte[] new_byte_array=normal_source_str.getBytes(C)即可,此时即可用java io api将数组写入文件,并记录相应的字节数组偏移量等,待真正使用时,直接io读取即可。

免责声明:文章转载自《网络爬虫的乱码处理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇R语言自然语言处理:关键词提取(TF-IDF)DoS攻击技术下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

GB2312编码(为什么要加2020H、8080H,外码→内码→交换码→字形码)

为什么要加上2020H和8080H? 区位码、内码、国标码怎么转换非常简单,但是令人迷惑的是为什么要那么转换?这种转换不可能平白无故地那样转换! 我搜索很多资料,找到最好的解释,总结如下: 首先,注意到一点,GB2312虽说是对中文编码,但是里面有对26个英文字母和一些特殊符号的编码,按理说这和ASCII重合的部分应该无需设置,沿用ASCII中不就行了?但...

laravel 导出插件

转发:https://blog.csdn.net/gu_wen_jie/article/details/79296470 版本:laravel5           php 5.6 安装步骤: 一、安装插件 ①、首先在Laravel项目根目录下使用Composer安装依赖: composer require "maatwebsite/excel:~2.1....

python3对文件编码的转换处理

  前言:   公司同事邀我一起给SQLSERVER 2008导数, 数据来源有高斯和ORACLE, 数据文件保存格式有UTF-8和GBK。   当我在做测试导入的时候发现SQLSERVER 2008数据库的WITH选项不支持CODEPAGE='65001', 即UTF-8文件编码格式导入。 所以需要把UTF-8编码的文件 统一转换成GBK, 代码如下。...

java中String编码转换 UTF-8转GBK

1.GB2312等都可以用GBK代替.2.new String(row.getBytes("GB2312"), "UTF8") 这种写法是不对的, 中文仍然会乱码. 方案:解决GBK字符转UTF-8乱码问题: https://www.cnblogs.com/xijin-wu/p/5884822.html 彻底搞懂编码 GBK 和 UTF8:https:/...

字节流和字符流转换

任何数据的持久化和网络传输都是以字节形式进行的,所以字节流和字符流之间必然存在转换问题。字符转字节是编码过程,字节转字符是解码过程。io包中提供了InputStreamReader和OutputStreamWriter用于字符和字节的转换。 来看一个小例子: char[] charArr = new char[1]; StringBuffer sb...

ThinkPHP的连贯操作方法中field方法

1 ThinkPHP的连贯操作方法中field方法有很多的使用技巧,field方法主要目的是标识要返回或者操作的字段,下面详细道来。 2 3 1、用于查询 4 在查询操作中field方法是使用最频繁的。 5 6 $Model->field('id,title,content')->select(); 7 这里使用field方法...