`
- 浏览:
41666 次
- 性别:
- 来自:
深圳
-
NekoHTML学习笔记
J. Andrew Clark用Java写了一系列的工具(Java APIs),NekoHTML是其中之一。
NekoHTML是一个简单地HTML扫描器和标签补偿器(tag balancer)
,使得程序能解析HTML文档并用标准的XML接口来访问其中的信息。这个解析器能投扫描HTML文件并“修正”许多作者(人或机器)在编写HTML文档
过程中常犯的错误。NekoHTML能增补缺失的父元素、自动用结束标签关闭相应的元素,以及不匹配的内嵌元素标签。NekoHTML的开发使用了
Xerces Native Interface (XNI),后者是Xerces2的实现基础。
一、运行要求
从NekoHTML主页上下载nekohtml-latest.zip,目前版本是0.8.
NekoHTML要求运行在java1.1或更高版本,Xerces-J
2.0或更高版本。(我在试用时,随便拿了个xerces的包来用,结果例如运行老时不能通过,折腾半天后才发现版本不够所致.
二、使用NekoHTML
1、透明地创建HTML解析器
利用Xerces2.0为基础,应用程序通过JAXP实例化解析器对象时,可以透明地创建HTML解析器,此时只需要将NekoHTML的jar文件,
在CLASSPATH中放在Xerces的jar文件之前即可。nekohtmlXni.jar中的META-INF/services
/org.apache.xerces.xni.parser.XMLParserConfiguration文件会被Xerces的读取并取代标准的设
置文件,此处org.apache.xerces.xni.parser.XMLParserConfiguration文件的内容就是一个字符串
“org.cyberneko.html.HTMLConfiguration”。这种方法的好处是简单透明,缺点是影响了Xerces在其它情况下的使
用。
2、便利的HTML解析器类
要想避免上述的问题,可以使用org.cyberneko.html.parsers包的
DOM和SAX解析器类来创建解析器,这两个类都使用了HTMLConfiguration类。解析器一旦创建之后,就可以解析HTML文件,并用标准的
XML接口来访问文件中的信息,就象面对的是一个XML文件一样。
下面的代码是NekoHTML自带的例程,我改了一下,使其可以显示HTML文件内容,而不显示类的名字。
package sample;
import org.cyberneko.html.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class TestHTMLDOM {
public static void main(String[] argv) throws Exception {
DOMParser parser = new DOMParser();
for (int i = 0; i < argv.length; i++) {
parser.parse(argv[i]);
print(parser.getDocument(), "");
}
}
public static void print(Node node, String indent) {
// System.out.println(indent+node.getClass().getName());
if (node.getNodeValue() != null){
if("".equals(node.getNodeValue().trim())){
}else{
System.out.print(indent);
System.out.println(node.getNodeValue());
??}
}
Node child = node.getFirstChild();
while (child != null) {
print(child, indent+" ");
child = child.getNextSibling();
}
}
}
编译运行如下:
cd $NEKOHTML_HOME
cp build_html.xml build.xml
ant
java -cp
nekohtml.jar;nekohtmlSamples.jar;xmlParserAPIs.jar;xercesImpl.jar
sample.TestHTMLDOM test.html
如果一切正常可以显示HTML的内容了。
3、文档片段解析
除了DOM和SAX类,NekoHTML还提供了一个实验性质的DOMFragmentParser类,用以解析HTML文件的片段。我个人认为,由于
浏览器的强大的容错能力,即使一个片段的HTML文件,也可以正确显示,由此也变相地造成了很多人不再关心的HTML的完整要求了。这个类,也许将是用的
最多的。下面,看看nutch是如何使用nekoHTML的。
package net.nutch.fetcher;
...
import org.cyberneko.html.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import org.w3c.dom.html.*;
import org.apache.html.dom.*;
public class Fetcher {
??....
private DOMFragmentParser parser = new DOMFragmentParser();
??....
private void handleFetch(URL url, FetchListEntry fle, Http.Response
response)
throws IOException, SAXException {
//判断HTTP应答包的类型,只放过html文件
String contentType = response.getHeader("Content-Type");
if (contentType != null &&
!contentType.startsWith("text/html"))
throw new IOException("Unknown content-type: " +
contentType);
//创建文件片段对象
DocumentFragment node = new
HTMLDocumentImpl().createDocumentFragment();
//解析HTML内容
parser.parse(new InputSource(new
ByteArrayInputStream(response.getContent())),node);
//取得全部文本内容
StringBuffer sb = new StringBuffer();
getText(sb, node);
String text = sb.toString();
//取得标题信息
sb.setLength(0);
getTitle(sb, node);
String title = sb.toString().trim();
//取得该页所有的出链
ArrayList l = new ArrayList();
getOutlinks(url, l, node);
//显示结果,存储信息
Outlink[] outlinks = (Outlink[])l.toArray(new
Outlink[l.size()]);
LOG.fine("found " + outlinks.length + " outlinks in " + url);
outputPage(new FetcherOutput(fle,
MD5Hash.digest(response.getContent()),
true, title, outlinks),
new FetcherContent(response.getContent()),
new FetcherText(text));
}
private static void getText(StringBuffer sb, Node node) {
if (node.getNodeType() == Node.TEXT_NODE) {
sb.append(node.getNodeValue());//取得结点值,即开始与结束标签之间的信息
}
NodeList children = node.getChildNodes();
if ( children != null ) {
int len = children.getLength();
for ( int i = 0; i < len; i++ ) {
getText(sb, children.item);//递归遍历DOM树
}
}
}
private static boolean getTitle(StringBuffer sb, Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
if ("title".equalsIgnoreCase(node.getNodeName())) {
getText(sb, node);
return true;
}
}
NodeList children = node.getChildNodes();
if (children != null) {
int len = children.getLength();
for (int i = 0; i < len; i++) {
if (getTitle(sb, children.item)) {
return true;
}
}
}
return false;
}
private static void getOutlinks(URL base, ArrayList outlinks, Node
node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
if ("a".equalsIgnoreCase(node.getNodeName())) {
StringBuffer linkText = new StringBuffer();
getText(linkText, node);
NamedNodeMap attrs = node.getAttributes();
String target= null;
for (int i= 0; i < attrs.getLength(); i++ ) {
if ("href".equalsIgnoreCase(attrs.item.getNodeName())) {
target= attrs.item.getNodeValue();//在DOM树中,属性是一个结点。
break;
}
}
if (target != null)
try {
URL url = new URL(base, target);
outlinks.add(new
Outlink(url.toString(),linkText.toString().trim()));
} catch (MalformedURLException e) {
// don't care
}
}
}
NodeList children = node.getChildNodes();
if ( children != null ) {
int len = children.getLength();
for ( int i = 0; i < len; i++ ) {
getOutlinks(base, outlinks, children.item);//递归遍历DOM树
}
}
}??
....
}
注意,此处传递给解析过程parse的文档片段对象,必须是由org.w3c.dom.html.HTMLDocument类型的DOM文档对象创建,否则有异常。
HTMLConfiguration可以用于创建任何基于XNI解析器,可参考下例
package sample;
import org.apache.xerces.parsers.AbstractSAXParser;
import org.cyberneko.html.HTMLConfiguration;
public class HTMLSAXParser extends AbstractSAXParser {
public HTMLSAXParser() {
super(new HTMLConfiguration());
}
}
三、设置解析器参数
为了更加精确的控制解析的动作,nekohtml提供了相应的设置函数。如下列:
// settings on HTMLConfiguration
org.apache.xerces.xni.parser.XMLParserConfiguration config =
new org.cyberneko.html.HTMLConfiguration();
config.setFeature("http://cyberneko.org/html/features/augmentations",
true);
config.setProperty("http://cyberneko.org/html/properties/names/elems",
"lower");
// settings on DOMParser
org.cyberneko.html.parsers.DOMParser parser =
new org.cyberneko.html.parsers.DOMParser();
parser.setFeature("http://cyberneko.org/html/features/augmentations",
true);
parser.setProperty("http://cyberneko.org/html/properties/names/elems",
"lower");
nekohtml功能(feature)列表
功能 默认值 描述
http://cyberneko.org/html/features/balance-tags True
是否允许增补缺失的标签。如果要以XML方式操作HTML文件,此值必须为真。此处提供设置功能,为了性能的原因。
http://cyberneko.org/html/features/balance-tags/ignore-outside-content
False
是否忽略文档根元素以后的数据。如果为false,<html>和<bod>被忽略,所有的内容都被解析。
http://cyberneko.org/html/features/document-fragment
False
解析HTML片段时是否作标签增补。此功能不要用在DOMParser上,而要用在DOMFragmentParser上。
http://apache.org/xml/features/scanner/notify-char-refs
False 当遇到字符实体引用(如&#x20;)是否将(#x20)报告给相应地文档处理器。
http://apache.org/xml/features/scanner/notify-builtin-refs
False 当遇到XML内建的字符实体引用(如&amp;)是否将(amp)报告给相应地文档处理器。
http://cyberneko.org/html/features/scanner/notify-builtin-refs
False 当遇到HTML内建的字符实体引用(如&copy;)是否将(copy)报告给相应地文档处理器。
http://cyberneko.org/html/features/scanner/script/strip-comment-delims
False
是否剥掉<script>元素中的<!---->等注释符。
http://cyberneko.org/html/features/augmentations False
是否将与HTML事件有关的infoset项包括在解析管道中。
http://cyberneko.org/html/features/report-errors False
是否报告错误。
nekohtml属性列表
属性 默认值 值域 描述
http://cyberneko.org/html/properties/filters null
XMLDocumentFilter[] 在解析管道的最后按数组顺序追加自定义的处理组件(过滤器),必须为数组类型。
http://cyberneko.org/html/properties/default-encoding
Windows-1252 IANA encoding names 默认的HTML文件编码
http://cyberneko.org/html/properties/names/elems upper
upper,lower,match 如果整理识别出的元素名称
http://cyberneko.org/html/properties/names/attrs lower
upper,lower,no-change 如果整理识别出的属性名称
四、管道过滤器
Xerces Native Interface
(XNI)定义了一个解析器配置框架,在那儿一个个解析器以模块化组件的形式组成一个管道。这样一来,通过重新安排已有组件和/或新定制开发的组件,就可
完成一个新的解析器配置工作。由于nekohtml是采用这个配置框架开发的,所以对解析器新增功能就很简单通过在默认的nekohtml解析管道的末端
增加文档过滤器来实现。
要新开发一个过滤器,很简单地实现xerces2的org.apache.xerces.xni.parser包中的
XMLDocumentFilter接口即可。这个接口,一方面使组件成为管道中上一级的事件处理器,另一方面又成为下级的信息源。针对nekohtml
的过滤器开发,只需简单地扩展org.cyberneko.html.filters包中的DefaultFilter类即可。
将自行开发的过滤器加入管道,可参考以下两种办法:
XMLDocumentFilter noop = new DefaultFilter();
XMLDocumentFilter[] filters = { noop };
XMLParserConfiguration parser = new HTMLConfiguration();
parser.setProperty("http://cyberneko.org/html/properties/filters",
filters);
nekohtml的org.cyberneko.html.filters 包中有DefaultFilter、
ElementRemover、Identity、Writer,能实现动态插入内容、删除元素、序列化HTML文档等,不详细述。
转自:http://hedong.3322.org/
分享到:
Global site tag (gtag.js) - Google Analytics
相关推荐
aspose.word 解析word读取及word转pdf、转html;附带文件;需要的下载
xdocreport能解析word转html,但解析出来的是基于word的整套html,往往我们的需求是 按照段落顺序分块解析成一小块的html,并保存数据库,方便我们解决业务上的各种需求。 解决方案: 修改xdocreport源码,按照段落...
javajson转html在线解析代码,本人很高兴能解析出来 哈哈
nodejs 解析html根据标签提取需要合并的js、css,并且更新html # 简介 > 站点页面上js、css外链过多会导致网页的加载速度过慢,通过合并页面的js、css成一个文件,减少http的开销。 读取config.json,解析html根据 ...
C#解析Json数据(.html),C#解析Json数据(.html)(网页链接)
百度地图坐标转换和百度地址逆解析的详细代码js;百
OFD文档转换支持 ...HTML转换: 使用上述SVG矢量图形转换作为显示效果层A,再将OFD文档中的文字(仅)解析为SVG作为文字复制层B,B置于A层之上,文字颜色transparent,无需关心字体,在移动端同样正常显示。
javaEmail html 预览 .eml邮件,直接打印html代码,格式与html邮箱预览一样,附件没有写,自行看javaEmail文档,要求JDK1.7、java EE6 LIbraries
纯javascript解析CSV文件使用并转成HTML表格
JAVA POI Excel转Html,代码和所需的jar都在压缩包,项目在线预览需求,实现后分享下
提供POI编译DEX前的jar包。 提供POI编译DEX前的jar包。 提供POI编译DEX前的jar包。用于Android解析Excel的工程查看
htmlparser(HTML页面解析)例子
POI 解析excel,转成html页面(支持excel03和07)包括style
poi完美word转html,完整操作资料的引用说明
1. docx转html处理 Docx2Html.java (poi jsoup) 2. doc转html处理 Doc2Html.java (poi jsoup) 3. word转pdf处理 Word2Pdf.java (poi itext7) 4. word模板填充 WordUtils.java (poi XWPF) 5. 序列id生成 6. 文件处理...
java利用poi把html网友转换成word文档的小例子,包含程序代码和jar包。
编辑器里表格数据,用js解析为所需json格式,便于后台存储
转换PSD到HTML入门教程。 PSD的设计转换成HTML 这本书籍详细介绍了如何转换
1、itext将静态html转pdf中文显示及换行问题 2、itext将静态html转pdf 字体问题 3、html转pdf 参考我的另外一篇博文https://blog.csdn.net/qq_38616723/article/details/125188407?spm=1001.2014.3001.5502
POI 解析excel,转成html页面(支持excel03和07)包括style