在大规模的网络爬虫编程中,网页编码识别是必不可少的,本文将介绍如何通过C#来自动识别网页的编码。文中会分析几种可行的方法并提供源码,部分源码来源于开源代码改写而来。
网页在传输中为了能够正确识别编码,一般在头部都会声明编码格式,例如:
1 | <meta charset="utf-8"> |
或者像这样:
1 | <meta http-equiv="Content-type" content="text/html; charset=utf-8"> |
因此,很自然的我们想到通过读取这个字段来来识别编码。下面代码中 ResponseStream 是从 HTTP 网络流里读取后转化为 Stream 的流。
1 | string CharsetReg = @"(meta.*?charset=""?(?<Charset>[^\s""'>;]+)""?)|(xml.*?encoding=""?(?<Charset>[^\s"">;]+)""?)"; |
这个方法仅考虑了中文与英文环境下的情况,如果还有其它编码,请自行修改。
当你满心欢喜的以为可以喝杯咖啡打个盹时,运维妹妹发来了乱码的截图。。。这是哪个实习生在网页写的GB2312,实际却是UTF-8的编码。好吧,看在就这一个的情况下,我写个参数配置一下这个网站的编码吧。
一个小时过去了。。。
已经是第7张乱码截图了,看来乱写编码已经成为了反爬虫的招数之一了!再一次打开网站,发现浏览器中并没有乱码,看来是有其它的判断方式。于是,找到了这个库 chardet ,它是mozilla自动字符编码识别程序库,我直接使用了社区中贡献的 .Net 实现版本 Nchardet。链接是我所能搜索到的最早的文章,如果有错误还望指出!
原程序使用了一种通知模式来反馈编码结果,个人感觉与习惯使用的方式不同,于是改成了静态方法,将 HandleData 等用于识别编码的方法增加了编码返回,另外创建了一个 Nchardet 的 Helper 类:
1 | using System; |
为了平衡效率与准确度,RecogCharset 方法提供了一个 maxLength 的参数,用于指定每次识别的最大byte数,如果指定长度的byte数组无法识别出编码,则会循环直至识别出编码或者所有byte都已参与识别。生成环境下测试该值使用 1024 效果较好。
你以为这样就完了,不,没有,竟然还有一个网站头部与正文部分使用不同编码的,为了避嫌,暂时不点名了。还好目前也就发现了这一个网站,好吧,拿回之前删除的指定编码的代码,把编码指定为我们要获取的部分的编码,最终改写后的方法如下:
1 | string CharsetReg = @"(meta.*?charset=""?(?<Charset>[^\s""'>;]+)""?)|(xml.*?encoding=""?(?<Charset>[^\s"">;]+)""?)"; |
所有代码以及里面的一些依赖都已经在 thrinax 库中了,thrinax 的定位是一个使用 .Net 提供网络抓取,信息抽取,自然语言处理的库,其中的大部分代码都会来源于社区或其它开源算法或者论文,该库只是筛选统一方便调用。如果大家有这三方面的好的推荐,可以通过 Issue 或者博客评论发给我!
本文涉及 HttpHelper 与 NChardetHelper,欢迎大家 Star 与 Fork thrinax 库。
本文来自 The NewIdea,作者 Carey Tzou 。
永久地址:https://www.tnidea.com/recog-http-charset-by-dot-net.html
未经授权,拒绝任何全文及摘要转载!