- 浏览: 284754 次
- 性别:
- 来自: 湖南岳阳
-
最新评论
-
ternus:
兄弟,我用boboBrowse 也遇到了排序的问题,上线了讨论 ...
lucene 分组 bobo-Browse 排序的问题 -
luli0822:
Awesome bookmarks of those guru ...
流行的jQuery信息提示插件(jQuery Tooltip Plugin) -
shenbai:
如果你要在前台运行,你应该run得是ElasticSearch ...
ElasticSearch 源码分析 环境入门 -
cl1154781231:
<s:peroperty value="#at ...
关于Struts2中标签的一些心得 -
RonQi:
转载的吗?http://blog.csdn.net/stray ...
利用bobo-browse 实现lucene的分组统计功能
htmlparser (HTML Parser )是 sourceforge.net 上的一个成熟的 java 项目。它可以解析 HTML 页面,用来抽取或修改其内容,通过过滤器、访问者来访问程序关心的标签(Tag )。
一般使用 htmlparser 来做 HTML 解析后的抽取工作,但对 HTML 内容进行结构化修改则比较少用到。前段有一个对 HTML 抓取后修改其中所有链接地址的需求,使用 htmlparser 将 HTML 页面中附带资源(non html resource)的 URL 地址都做一下转换,包括链接(LinkTag)、图片(ImageTag)、框架页(FrameTag)、表单(FormTag)标签中指定的资源地址, 还包括 head 中的 link(HeaderLinkTag)标签中指定的 CSS/favicon.ico 以及 script(ScriptExTag)标签中指定的 JS 文件资源地址。对于后二者 HeaderLinkTag 和 ScriptExTag 标签的处理功能在 htmlparser 是没有实现的,需要自己通过编写继承于 TagNode/CompositeTag 基类的自定义标签来做匹配、修改逻辑。
OK 言归正传,下面给出在 htmlparser 中修改 HTML 内容的 2 种方法。
首先,第 1 种修改方法可以通过自定义继承 UrlModifyingVisitor 的子类来自定义修改 URL 逻辑,通过 org.htmlparser .Parser 提供的遍历模式来完成修改。 直接上代码。
import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Logger; import org.htmlparser.Tag; import org.htmlparser.Text; import org.htmlparser.tags.FormTag; import org.htmlparser.tags.FrameTag; import org.htmlparser.tags.ImageTag; import org.htmlparser.tags.LinkTag; import org.htmlparser.visitors.UrlModifyingVisitor; import org.lzy.fwswaper.FwswaperServlet; import org.lzy.fwswaper.htmlhandler.HtmlHandlerHelper; import org.lzy.fwswaper.util.ExceptionUtils; public class HtmlparserUrlModifier extends UrlModifyingVisitor { private static final Logger log = Logger.getLogger(HtmlparserUrlModifier.class.getName()); private URL base = null; public HtmlparserUrlModifier(URL base) { super(""); this.setBaseUrl(base); } public void setBaseUrl(URL base) { if (!HtmlHandlerHelper.isHttpLikeProtocolUrl(base)) throw new IllegalArgumentException(String.format( "Base url argument '%s' is not http like protocol. " + "They are not prefix with '%s' or '%s'", this.base.toString(), HtmlHandlerHelper.HttpProtocol, HtmlHandlerHelper.HttpsProtocol)); this.base = base; } public void visitStringNode(Text stringNode) { // MUST override this method. // Super class UrlModifingVistor wrote: 'this.modifiedResult.append (stringNode.toHtml());'. // It will append stringNode.toHtml() conent to outside of <html/> tag if not override it. } public void visitTag(Tag tag) { try { if (tag instanceof LinkTag) { LinkTag link = (LinkTag) tag; log.info(String.format("Found link: '%s' => '%s'.", link.getLinkText(), link.extractLink())); if (link.isHTTPLikeLink()) link.setLink(this.modifying(new URL(base, link.getLink()))); } else if (tag instanceof HeaderLinkTag) { HeaderLinkTag link = (HeaderLinkTag) tag; log.info(String.format("Found head link: '%s' => '%s'.", link.getLinkText(), link.getLink())); URL url = new URL(base, link.getLink()); if (HtmlHandlerHelper.isHttpLikeProtocolUrl(url)) link.setLink(this.modifying(url)); } else if (tag instanceof ScriptExTag) { ScriptExTag script = (ScriptExTag) tag; String src = script.getSrc(); if ((src != null) && (src.length() > 0)) { log.info(String.format("Found script: '%s' => '%s'.", script.getLanguage(), src)); URL url = new URL(base, src); if (HtmlHandlerHelper.isHttpLikeProtocolUrl(url)) script.setSrc(this.modifying(url)); } } else if (tag instanceof ImageTag) { ImageTag img = (ImageTag) tag; log.info(String.format("Found image => '%s'.", img.getImageURL())); URL url = new URL(base, img.getImageURL()); if (HtmlHandlerHelper.isHttpLikeProtocolUrl(url)) img.setImageURL(this.modifying(url)); } else if (tag instanceof FrameTag) { FrameTag frame = (FrameTag) tag; log.info(String.format("Found frame: '%s' => '%s'.", frame.getText(), frame.getFrameLocation())); URL url = new URL(base, frame.getFrameLocation()); if (HtmlHandlerHelper.isHttpLikeProtocolUrl(url)) frame.setFrameLocation(this.modifying(url)); } else if (tag instanceof FormTag) { FormTag form = (FormTag) tag; log.info(String.format("Found form: '%s' => (%s) '%s'.", form.getFormName(), form.getFormMethod(), form.extractFormLocn())); URL url = new URL(base, form.extractFormLocn()); if (HtmlHandlerHelper.isHttpLikeProtocolUrl(url)) form.setFormLocation(this.modifying(url)); } } catch(Exception e) { log.warning(String.format("Modify url failed. Exception message: '%s'.", ExceptionUtils.getStackTrace(e))); } super.visitTag(tag); } protected String modifying(URL url) throws MalformedURLException { // Modifying url and return. return null; } }
PrototypicalNodeFactory factory = new PrototypicalNodeFactory();
factory.registerTag(new HeaderLinkTag());
factory.registerTag(new ScriptExTag());
Parser parser = Parser.createParser(html, charset);
parser.setNodeFactory(factory);
// Match and modify link image and frame tag
url address.
HtmlparserUrlModifier modifier = new HtmlparserUrlModifier(this.base);
parser.visitAllNodesWith(modifier);
String html = modifier.getModifiedResult();
通过上面的 HtmlparserUrlModifier 中的具体处理,并在 org.htmlparser
.PrototypicalNodeFactory 中注册 HeaderLinkTag 和 ScriptExTag 这 2 个要匹配的自定义标签类型,我们就可以对 html 内容进行结构化修改了,实际看了 htmlparser
的源码就会发现根本上最后就是 setAttribute 方法的调用。
这里有两个问题需要说明:
1. 在继承 UrlModifyingVisitor 对它进行扩展时,一定要重载其 visitStringNode 方法,否则会发现在 htmlparser 处理后的结果中,在 html 标签外还会有页面所有的文本内容的副本,这里的文本是指那些用于在浏览器中显示的文字内容。正如上述代码中所示,在我重载的 visitStringNode 方法中没有做任何处理。通过 UrlModifyingVisitor 源码可以看到 visitStringNode 方法默认实现如下。
public void visitStringNode(Text stringNode) { modifiedResult.append (stringNode.toHtml()); }
2. 不能通过 org.htmlparser .Parser 类的 parse 方法在解析过程中对 html 内容进行修改,因为在解析完成后,你会发现必须通过 reset 方法来复位,这样之前的处理结果就全部失效了。
其次,第 2 种方法是通过 org.htmlparser .util.NodeList 保存结构化的 html 内容并对其修改,最后通过它的 toHtml 方法将修改结果导出。 示例代码如下所示。
private String parse(String html, String charset) throws ParserException { Parser parser = Parser.createParser(html, charset); NodeList list = parser.parse(null); String html = recurse(list).toHtml(); System.out.println(html); } private NodeList recurse(NodeList list) { if(list==null) return null; Node node = null; SimpleNodeIterator iterator = list.elements(); while(iterator.hasMoreNodes()) { node = iterator.nextNode(); if(node==null) break; if(node instanceof Tag ) { Tag tag = (Tag )node; // Modifying attributes or something else. recurse(node.getChildren()); } } return null; }
好了,这次要说的就是上面的这 2 个方法,希望能对有需要的兄弟有所帮助。记得上次在问答频道里有人问过这问题。
作者:lzy.je
出处:http://lzy.iteye.com
发表评论
-
Errors running builder 'DeploymentBuilder' on project_java
2014-10-09 11:54 790此问题一般发生在Myeclipse 保存文件并自动部署时候 ... -
MyEclipse的SVN插件的问题
2012-02-27 14:06 1769我的项目都统一使用了UTF-8编码 查看当前版本,还是提 ... -
Eclipse的SVN插件历史版本乱码的问题
2012-02-27 14:04 0我的项目都统一使用了UTF-8编码 查看当前版本,还是提 ... -
java中的io系统详解
2011-09-16 12:09 1162相关读书笔记、心得文章列表 Ja ... -
hibernate表关联注解
2011-08-02 11:39 1432好久就想玩一下hibernate注解了(因为不用hbm文件,维 ... -
TCP/IP传输层,你懂多少?
2011-05-12 17:13 1749你所不知道的传输层 题记:23页的文档上,满满当当的 ... -
关于Struts2中标签的一些心得
2011-05-06 17:21 1748最近在做Struts2+Hibernet的一个项目,在if标签 ... -
This wizard is not available because it requires a valid professional subscripti
2011-04-18 23:05 1878今天用myeclipse学习UML时,打开UML时出现了: ... -
Tomcat内存、连接数等性能参数设置
2011-04-08 09:59 1287默认参数不适合生产环 ... -
Java 垃圾回收策略调优
2011-03-28 17:52 1592JVM参数调优是一个很头 ... -
Eclipse 或 MyEclipse 不能自动编译 class文件(综合)
2011-03-25 11:50 4738有时候用Eclipse或者MyEclipse 的时候,发现不 ... -
AccessController.doPrivileged 小记
2011-03-24 11:43 1073AccessController.doPrivileged ... -
servlet 读取图片
2011-02-17 15:38 1145String path = "F:/wjbo ... -
获取文件长度http,ftp
2011-01-18 16:09 1748ftp: FTPClient ftp = new FTPCl ... -
类的设计原则
2010-12-13 18:14 1096开闭原则 Software entities ... -
收集的网站
2010-12-09 17:12 932NIO.2 入门,第 1 部分: 异步通道 API http ... -
看Hibernate源码 003 - ID Generator
2010-12-09 16:43 1372Hibernate的id生成有N种策略, 可以通过hbm文件或 ... -
看Hibernate源码 001
2010-12-09 10:40 1106我看书的方式一向是&quo ... -
Hibernate Memcached 配置
2010-12-08 15:39 2151官方网址: http://code.google.com/p/ ... -
tomcat如何配置虚拟目录及虚拟主机
2010-12-02 17:54 2193先说说如何用Eclipse来做servlet开发,那些proj ...
相关推荐
API文档是使用HTMLParser的关键,它详尽地解释了库中每个类、方法和接口的用途。通过API文档,开发者可以了解如何初始化解析器,如何遍历HTML元素,以及如何处理各种HTML标签。例如,HTMLParser库可能会提供如`...
在Java开发中,如果你需要处理或分析HTML内容,HTMLParser是一个非常有用的工具。这个库提供了一套API,使得开发者能够方便地遍历、修改或者提取HTML文档中的信息。 在描述中提到的“org.htmlparser.Node”和其他的...
1. **导入库**:在Java项目中,首先需要将`htmlparser.jar`添加到类路径中,以便能够使用其提供的类和方法。 2. **创建解析器**:通过实例化解析器类,如`HtmlParser`,并设置相应的解析模式和配置。 3. **解析HTML*...
- **修改HTML**:支持对解析后的HTML文档进行修改,如替换文本、添加或删除节点等。 - **高性能**:即使面对复杂的HTML结构,也能保持快速稳定的解析性能。 #### 三、HTMLParser的安装与集成 HTMLParser作为一个...
4. 使用示例:在"HTMLParser使用详解-Node内容.doc"中,可能详细介绍了如何创建和配置解析器对象,设置解析事件处理器,以及如何通过遍历节点来提取或修改HTML内容。例如,可以使用`TagStart`事件捕获元素开始,`...
这个库使得开发者能够方便地从HTML中提取数据,处理DOM(文档对象模型),以及与网页内容进行交互。本项目名为"HTMLParser.net源代码HTMLParser.net使用demo",显然是一个包含示例代码的压缩包,用于展示如何在实际...
- **内容清理**:去除HTML中的广告、脚本等不必要内容,以准备进行进一步的处理或存储。 - **网页转换**:将HTML转换为其他格式,如XML或PDF。 - **Web测试**:验证网页的结构是否符合预期,检查HTML标签的正确性。 ...
用户可以通过遍历DOM树来访问和修改HTML内容。 3. **事件驱动解析**:除了DOM模型,HTMLParser还支持事件驱动的解析方式。在这种模式下,解析器会在遇到特定HTML元素或事件时触发回调函数,允许开发者对解析过程...
Winista.Htmlparser.Net是一个基于C#的开源HTML解析库,它为开发者提供了一种高效且灵活的方式来处理HTML文档,尤其在需要从HTML中提取数据或者进行网页抓取时显得尤为重要。本文将深入探讨该库的核心功能、设计原理...
3. **标签处理**:HTMLParser支持对HTML标签进行操作,如查找、替换、删除或修改标签的属性。 4. **内容提取**:能够方便地从HTML文档中提取文本内容,这对于数据抓取或信息提取任务非常有用。 5. **错误处理**:...
例如,如果你想从HTML中获取所有`<a>`标签,可以使用提供的查询方法,该方法接受CSS选择器作为参数,返回匹配的元素列表。然后,你可以进一步访问每个元素的属性,如`href`,以获取链接地址。此外,Winista....
这个库可能包含了一系列的方法和类,帮助开发者在C#环境中高效且准确地解析HTML内容,类似于Java中的Jsoup或者Python的BeautifulSoup。源码的提供使得我们可以深入理解其工作原理,并根据实际需求进行定制化修改。 ...
HTMLParser设计的目的是为了方便地解析、提取或修改HTML内容,适用于网页数据抓取和HTML文档处理。 在使用HTMLParser时,首先需要创建一个`Parser`对象。可以通过传递一个`URLConnection`对象来构造`Parser`,这样...
- 它通常提供API来修改HTML结构,如添加、删除或替换元素,这对于处理动态生成的内容非常有用。 总之,HTMLParser是一个强大的工具,无论是在C#还是Java环境中,都能帮助开发者有效地解析和操作HTML文档,广泛应用...
2. **DOM(Document Object Model)解析**:HTMLParser也能将整个HTML文档转换为DOM树,这使得开发者可以通过DOM API遍历和修改HTML结构。例如,可以查找特定的DOM节点,或者使用XPath表达式来定位信息。 3. **SAX...
在这个示例中,`openFile` 方法用于读取本地 HTML 文件内容,`Parser.createParser` 用于创建解析器,`TextExtractingVisitor` 访问者则用于从解析的 HTML 中提取所有文本。`visitAllNodesWith` 方法调用使解析器...
过滤器在HTML解析中起着重要作用,它们允许开发者根据特定规则筛选或修改HTML内容。例如,你可以创建一个过滤器来删除所有广告元素,或者将某些URL替换为短链接。 `thumbelina.dll`和`sitecapturer.dll`可能与屏幕...
HTMLParser是一款强大的交互式工具,专门设计用于将HTML代码转换为Pug、Jinja2和Blade这三种流行的模板引擎格式。这个工具对于开发者来说,尤其是那些习惯于使用静态HTML,但希望转向更强大、更简洁的模板语言的...
通过阅读这份文档,你可以了解到如何初始化解析器,如何处理HTML元素,以及如何处理HTML中的属性和文本内容。 其次,`HTMLParser-2.0-SNAPSHOT-src.zip`是源代码包,它包含了HTMLParser的源代码。对于开发者来说,...
总之,htmlparser1_6.jar是一个强大的工具,用于解析和操作HTML文档,尤其适合那些需要从HTML中提取信息或者需要对HTML进行结构化处理的Java应用。其灵活性和错误处理能力使其成为处理不规则HTML的可靠选择。