网页采集器的自动识别算法(天地连站群引入编码自动识别前,我们有两种途径获取网页的编码信息)
优采云 发布时间: 2021-10-03 04:22网页采集器的自动识别算法(天地连站群引入编码自动识别前,我们有两种途径获取网页的编码信息)
天地联站群可以根据用户初始输入的关键词获取关键词搜索引擎的搜索结果,然后一一获取相关的文章内容。这样,就要面对无数网页的各种编码。为了解决这个问题,介绍了以下解决方案:
在引入自动编码识别之前,我们有两种方式获取网页的编码信息:
它的一、是通过服务端返回的header中的charset变量获取的
它的二、是通过页面上的元信息获取的
一般情况下,如果服务器或者页面提供了这两个参数,并且参数正确,那么我们抓取网页的时候就没有编码问题了。
然而,现实对我们程序员来说总是很艰难。在抓取网页时,经常会出现以下情况:
1. 缺少这两个参数
2. 虽然提供了两个参数,但是不一致
3. 提供了这两个参数,但与网页的实际编码不一致
为了尽可能自动获取所有网页的编码,引入了自动编码识别
我记得PHP中有一个mb_detect函数,貌似可以识别字符串编码,但是它的准确性不好说,因为自动识别编码是一个概率事件,只有当识别的字符串长度很大时足够(例如,超过 300 个单词)可以更可靠。
所有浏览器都支持自动识别网页编码,如IE、firefox等。
我用的是mozzila提供的universalchardet模块,据说比IE自带的识别模块准确很多
Universalchardet 项目地址为:
目前universalchardet支持python java dotnet等,php不知道是否支持
我比较喜欢写C#,因为VS2010+viemu是我的最爱,所以我用的是C#版本;有许多 C# 移植版本的 Universalchardet,我使用的版本:
下面是一个使用示例,与其他C#实现相比,有点繁琐:
Stream mystream = res.GetResponseStream();<br /> MemoryStream msTemp = new MemoryStream();<br />int len = 0;<br />byte[] buff = new byte[512];<br /><br />while ((len = mystream.Read(buff, 0, 512)) > 0)<br /> {<br /> msTemp.Write(buff, 0, len);<br /><br /> }<br /> res.Close();<br /><br />if (msTemp.Length > 0)<br /> {<br /> msTemp.Seek(0, SeekOrigin.Begin);<br />byte[] PageBytes = new byte[msTemp.Length];<br /> msTemp.Read(PageBytes, 0, PageBytes.Length);<br /><br /> msTemp.Seek(0, SeekOrigin.Begin);<br />int DetLen = 0;<br />byte[] DetectBuff = new byte[4096];<br /> CharsetListener listener = new CharsetListener();<br /> UniversalDetector Det = new UniversalDetector(null);<br />while ((DetLen = msTemp.Read(DetectBuff, 0, DetectBuff.Length)) > 0 && !Det.IsDone())<br /> {<br /> Det.HandleData(DetectBuff, 0, DetectBuff.Length);<br /> }<br /> Det.DataEnd();<br />if (Det.GetDetectedCharset()!=null)<br /> {<br /> CharSetBox.Text = "OK! CharSet=" + Det.GetDetectedCharset();<br /> PageBox.Text = System.Text.Encoding.GetEncoding(Det.GetDetectedCharset()).GetString(PageBytes);<br /> }<br /> }
上面可以识别网页的编码,看起来很简单是不是?如果你之前也被这个问题困扰过,并且有幸看到这篇文章,那么这类问题就彻底解决了,你永远不会因为不懂网页编码而抓到一堆?? ? ? ? 号回;好吧,从此生活就变得如此美好。. . .
我也是这么想的
如上所述,代码识别是一个概率事件,所以不能保证100%正确识别,所以后来我还是发现了一些识别错误导致返回?? 在数的情况下,真的没有办法完美解决这个问题吗?
世界上不可能有完美的事情,我深信这一点。
幸运的是,我们只需要一个完美的解决方案:我们需要让程序知道什么时候自动识别错误,如果错误,读取并使用服务器和网页提供的编码信息。
我绞尽脑汁,想出了一个原生方法:对我们中国人来说,就是有编码问题的中文网页。如果一个中文网页被正确识别,里面肯定会有汉字。Bingo,我从网上找了前N个汉字(比如“的”)。只要网页收录这N个汉字中的一个,则识别成功,否则识别失败。
这样,网页编码识别的问题就基本可以轻松解决了。
后记:
不知道有没有人对这个感兴趣。如果是这样,我想写一篇关于这个主题的文章。标题也是想出来的:《网络IO,到处都是异步》,这里指的是网络IO Only http请求
天地联站群使用这种代码识别方法解决了采集领域的一个重大问题。从那时起,我可以从这个问题中提取我的精力,研究和解决其他问题。