日期:2014-05-17  浏览次数:20676 次

使用HtmlParser提取HTML文本块

听人介绍说HtmlParser(Java版本)在网页预处理方面做得不错,于是最近几日就研究了一番,虽说没有什么大的收获,但是难得能够让我一个对html标签一无所知的人,认识了其树状结构的玄机,并实现了通过文件目录提取html的标题,关键词,摘要信息,链接及其锚文本,以及主题型网页的正文部分。

以下仅就提取正文部分做个简单拙劣的介绍。在提取网页正文时,对于不同类型的网页应当采用不同的提取策略,而网页又可以分成几种类型呢?粗略地讲,网页就分成两种类型:主题型(topic)和hub型,这种分类有一个明显的差别,即主题型相对hub型网页正文要占可视文本的绝大多数。比如,baidu空间,这种博客类型的网页,多数情况下都是大段大段的文本块,而又如新华网首页,经过分析提取出来1,000多的出链,打开网页映入我们眼帘实际上是这些链接的锚文本。锚文本与正文文本块一个明显的差别就是短小,而门户网站的锚文本又多了一个性质:种类庞杂,条目众多。

基于这种分析,我们在提取网页正文之前,至少在代码中应该定义一个用于判别网页类型的方法/函数,目的就是针对每种类型,采取一种独特的正文提取策略。至于这个功能函数如何实现这种判别,可以参考相关的文献和网络资料具体深入的研究。当然有一种被很多人推崇的版本,那就是计算文本的信噪比,但是这种方法从概念上就足以让人望而却步,更甭提具体实现了,但我觉得可能这种方法也许并没有乍看那么困难吧!先夸下海口,但我还没有抽出足够的时间了解它,以后慢慢地研究吧。我在程序中就采取了一种十分粗糙简化的判别,即通过为网页出链的数目设置一个阈值,当出链数目超出这个阈值时,即可认为该网页属于hub型;低于这个阈值,即被归入主题型网页。明显地,这是一种低级的,没有任何技术含量的假设,还有待我们细化。

网页类型分析出来了,采取什么策略来提取正文呢?还是简化的方式:针对主题型,提取的是主体的大块文本段落;而对hub型,由于其大量的出链和锚文本,我们就直接忽略掉这个提取。说了大半天,竟然没有提取。话虽如此,实际上,hub型网页的文本内容都被我们通过锚文本的形式提取出来了,这也就是我采用HtmlParser提取正文的原因,一方面它可以实现针对性的提取链接,同时跳过script、style、remark标签,过滤掉迷惑性的图片链接等其他链接,单单提取txt/html类型的所有链接,重要的是还能够同时提取相应的锚文本,并能够保存其标签的起始位置。一个让人着迷的实现,从技术上来看,实际上也还是使用我们万能的正则表达式匹配功能实现的,从我来讲,这种匹配只是被包装起来了。其实,我们还是可以让他们pk一下的,比如过滤掉html中的无用标签对以及文本内容,如惹人厌烦的script和style、remark标签:

<1>使用简单的正则表达式匹配:

?public String cleanHtml(String html){
??String regex="<script[\\s\\S]*?</script>" +
????"|<style[\\s\\S]*?</style>"+
????"|<![\\s\\S]*?>";
??Pattern pattern=Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
??Matcher match=pattern.matcher(html);
??html=match.replaceAll("");
??return html;
?}

输入的是原始的html字符串,输出的结果就将以上垃圾信息过滤掉了 :)

<2>使用HtmlParser过滤script和style标签信息以及文本信息:

?public String htmlInit(String htmlStr){
??NodeFilter scriptFilter=new NodeClassFilter(ScriptTag.class);
??NodeFilter styleFilter=new NodeClassFilter(StyleTag.class);
??NodeFilter[] filter={scriptFilter,styleFilter};
??OrFilter orFilter=new OrFilter(filter);
??try {