最近在做有关自然语言抽取方面的研究,接触到了很多相关的工具包,尤其是关于html中格式文本的抽取,虽然网上有很多相关高效算法,但我只想尽量简单快捷地将我需要的内容从html中抽取出来。因此,我只需要一个轻量级的工具,满足我的需求就行了。之前在网上搜索了一下,主要有Jtidy和HtmlParser这两个工具,都是java的。Jtidy的主页是:http://jtidy.sourceforge.net/。我最早尝试使用的就是Jtidt,由于相关文档较少,中文文档就更少了,我感觉很难上手。于是,我转向了HtmlParse,虽然同样有文档较少的问题,但我发现,这是一个比较容易上手的工具,用了HtmlParse很快就达到了我的需求。HtmlParse的主页地址是:http://htmlparser.sourceforge.net/,最后更新是2006年9月17日,虽然很老,但是应付一般的需求还是可以的。
在这里,我以我抽取某网站上GRE作文为例子,写了一点东西,希望能对正在使用HtmlParse的朋友有所帮助。
这是抽取之前的页面,我抽取的便是它的正文部分。
下面是抽取后的截图:
第一步 首先要实例化一个Parser
HTMLParser的核心模块是org.htmlparser.Parser类,这个类实际完成了对于HTML页面的分析工作。这个类有下面几个构造函数:
public Parser ();
public Parser (Lexer lexer, ParserFeedback fb);
public Parser (URLConnection connection, ParserFeedback fb) throws ParserException;
public Parser (String resource, ParserFeedback feedback) throws ParserException;
public Parser (String resource) throws ParserException;
public Parser (Lexer lexer);
public Parser (URLConnection connection) throws ParserException;
//一个静态类
public static Parser createParser (String html, String charset);
其中用的较多的应该是使用最多的是通过一个URLConnection或者一个保存有网页内容的字符串来初始化Parser,显然用得最多的是最后两个构造函数。在我的例子中,由于我是把几十个网页一起打包下载了下来,因此,在此处我使用的是最后一种静态类的构造方法:
Parser parser = Parser.createParser(str, "utf-8");
其中str是页面内容的字符串,”utf-8”是编码方式。
第二步 观察你需要抽取的内容,建立过滤器
HtmlParse分析和抽取的html文档的原理是将整个html文档解析成一个DOM(Document Object Mode)树,通过遍历树上的所有节点,实现文本的抽取。因此,在使用了filter后,Parser返回的是满足filter条件的节点类(Node)实例的一个集合。在HtmlParse中Node是信息保存的数据类型基础。Node中包含了许多对树的操作的方法,对于具体问题可以去官网上看文档,此处就不再赘述了。
Filter就是对于结果进行过滤,取得需要的内容。HTMLParser在org.htmlparser.filters包之内一共定义了16个不同的Filter,也可以分为几类。
判断类Filter:
TagNameFilter;
HasAttributeFilter;
HasChildFilter;
HasParentFilter;
HasSiblingFilter;
IsEqualFilter;
逻辑运算Filter:
AndFilter;
NotFilter;
OrFilter;
XorFilter;
其他Filter:
NodeClassFilter;
StringFilter;
LinkStringFilter;
LinkRegexFilter;
RegexFilter;
CssSelectorNodeFilter;
所有的Filter类都实现了org.htmlparser.NodeFilter接口。这个接口只有一个主要函数:
boolean accept (Node node);
各个子类分别实现这个函数,用于判断输入的Node是否符合这个Filter的过滤条件,如果符合,返回true,否则返回false。
现在回到我们的例子中,以下是我的代码:
try{
Parser parser = Parser.createParser(str, "utf-8");
NodeFilter filter = new TagNameFilter("p");
NodeList nodes = parser.extractAllNodesThatMatch(filter);
//判断文件是否存在
File file = new File(outpaths);
if(file.exists())
{
file.delete();
}
if(nodes!=null)
{
for(int j = 0;j < nodes.size();j++)
{
if(j < 7)
{
continue;
}
//返回出一个p节点
Node TextNode = (Node)nodes.elementAt(j);
//取出Node的取得纯文本信息。
tmp =TextNode.toPlainTextString();
//此处使用了正则表达式,目的是去除取出的文本中的html的一些空白标记
//如 等
Pattern pattern =Pattern.compile(" {2,}");
Matcher m =pattern.matcher(tmp);
tmp=m.replaceAll("");
Pattern patterns = Pattern.compile(" ");
Matcher mm = patterns.matcher(tmp);
tmp = mm.replaceAll("");
WriteFile(tmp,outpaths);
WriteFile("\r\n",outpaths);
}
}
} catch( Exception e ) {
}
最后写到文件中的字符串tmp就是抽取后的内容了。作者博客: http://www.flyaway-blog.com/%E5%88%A9%E7%94%A8htmlparse%E6%8A%BD%E5%8F%96%E7%BD%91%E9%A1%B5%E6%AD%A3%E6%96%87%E5%86%85%E5%AE%B9.html