网络爬虫的乱码处理

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

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

    一、网络爬虫出现乱码的缘由api

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

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

        B、抓取到的数据,原始状况为字节数组,它是由A来编码的,只有B=A时,才能够保证不出现乱码,不然当字符集不兼容时,老是会出现乱码,此步骤每每用于测试。网络

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

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

    二、乱码的解决方法测试

       根据缘由来找解决方法,就很是简单了。网站

       (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读取便可。

相关文章
相关标签/搜索