- 浏览: 162758 次
- 性别:
- 来自: 北京
最新评论
-
tanliwei:
Mr-su 写道行业(xingye),why?行是个多音字。
...
利用Java开源库把汉字转拼音 -
u148:
java.io.IOException: Stream clo ...
自己封装的一个编码转换工具类 -
Mr-su:
行业(xingye),why?
利用Java开源库把汉字转拼音 -
364902709:
此意悠悠 写道不可能的,java反射刚出来,最差的时候是正常编 ...
测试Java反射效率 -
此意悠悠:
不可能的,java反射刚出来,最差的时候是正常编程的10倍时间 ...
测试Java反射效率
手动解析HTML是一件很崩溃的事情,sun的swing里也有解析HTML的东东,不过已经是古董了,实在不好拿出来丢Java的人了。
今天要用的是Apache的一个开源项目,html parser。
它的强大不用多说,且看它提供的几个sample吧。
首先去htmlparser.sourceforge.net上去下载,在解压开之后目录里有几个目录,分别存放着src,jars,javadoc之类的,其中bin里有好几个xxx.cmd,用命令行运行那几个脚本,参数就加某个网页的地址就行了。
主意不要拿javaeye的网页做测试哦,不行的,因为sample里的HTTP客户端是用的sun的URLConnection,请求javaeye的话响应的内容是一个空文档,这只是URLConnection的众多bug之一,建议大家不要用哦,如果你只是测试的话那到无所谓咯。
其中stringextractor.cmd是解析出网页内的纯文本内容的,linkextractor.cmd是解析网页里的连接的,非常有用哦。
接下来就要开始编程了,如何使用这个好工具捏?貌似官方并米有详细的文档说明,就这几个sample就已经大致说清楚如何用了。我们找到这几个cmd文件,打开找到其中调用的是那个类,因为它的sample并没有单独拿出来,得要我们自己去它的source里去找。我的建议是在Eclipse的工程里添加那个jar文件,然后把jar文件设置src,这样代码看起来爽一些啦。
小研究一下那几个sample是如何实现的,然后想想你自己的需求,借题发挥吧,这是java程序员的强项了。
上面提到了那几个脚本的参数是网页地址,它的代码里也是在构建Parser对象的时候用的也是url字符串作为参数的,其实如果你想用URLConnection之外的其他Http客户端组件来代替html parser的内置请求方式,也不用担心,因为Parser对象同样提供了html内容作为参数的构建方式:Parser p = Parser.createParser(String html, String charser);
下面是我在项目中用的两个小method,模仿了sample里的代码
/** * 用来抽取html里的连接地址,并转换了相对地址为绝对地址 */ private void extractLinks(URL pageURL, Parser parser) { Map<String, String> links = new HashMap<String, String>(); try { NodeFilter filter = new NodeClassFilter(LinkTag.class); NodeList list = parser.extractAllNodesThatMatch(filter); for (int i = 0; i < list.size(); i++) { LinkTag n = (LinkTag) list.elementAt(i); String link = n.getLink(); if (!n.isHTTPLink()) { continue; } if (link.startsWith("http://")) { try { link = new URL(link).toString(); links.put(HashUtil.md5(link), link); } catch (MalformedURLException e) { continue; } } else { try { link = new URL(pageURL, link).toString(); links.put(HashUtil.md5(link), link); } catch (MalformedURLException e) { continue; } } } } catch (ParserException e) { // TODO 处理异常 e.printStackTrace(); } catch (RuntimeException e) { // TODO 处理异常 e.printStackTrace(); } doc.setDocs(createDoc(links)); }
/** * 抽取html里的文本内容,里面使用了一个自定义的节点访问器,TextExtractVisitor,下面一段有定义 */ private Map<String, Object> extractText(Parser parser) { try { TextExtractVistor textExtractor = new TextExtractVistor(); parser.visitAllNodesWith(textExtractor); doc.getText().setText(textExtractor.getText()); doc.getText().setDigest(textExtractor.getDigest()); doc.getText().setKeywords(textExtractor.getKeywords()); doc.getText().setTitle(textExtractor.getTitle()); return textExtractor.getHashedTextTags(); } catch (ParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }
/** * 用来抽取html里文本等相关内容的节点访问器 */ public class TextExtractVistor extends NodeVisitor { StringBuilder textBuf = new StringBuilder(4096); private boolean mIsScript; private boolean mIsStyle; private boolean mIsPre; protected int mCollapseState; private final String NEWLINE = System.getProperty("line.separator"); private final int NEWLINE_SIZE = NEWLINE.length(); private boolean mIsMeta; private boolean mIsH; private boolean isStrong; private StringBuilder digest = new StringBuilder(512); private StringBuilder keywords = new StringBuilder(100); private boolean isTtitle; private String title; private Map<String, Object> textTags = new HashMap<String, Object>(); protected void carriageReturn() { int length; length = textBuf.length(); if ((0 != length) && ((NEWLINE_SIZE <= length) && (!textBuf.substring( length - NEWLINE_SIZE, length).equals(NEWLINE)))) textBuf.append(NEWLINE); mCollapseState = 0; } public void visitStringNode(Text string) { if (!mIsScript && !mIsStyle) { String text = string.getText(); textTags.put(HashUtil.md5(text), null); if (!mIsPre) { text = Translate.decode(text); text = text.replace('\u00a0', ' '); collapse(textBuf, text); } else { textBuf.append(text); if(mIsMeta){ keywords.append(text); }else if(mIsH || isStrong){ digest.append(text); }else if(isTtitle){ title = text; } } } } public void visitTag(Tag tag) { String name = tag.getTagName(); if (name.equalsIgnoreCase("PRE")) mIsPre = true; else if (name.equalsIgnoreCase("SCRIPT")) mIsScript = true; else if (name.equalsIgnoreCase("STYLE")) mIsStyle = true; else if (name.equalsIgnoreCase("META")) mIsMeta = true; else if (name.startsWith("[H|h]")) mIsH = true; else if (name.equalsIgnoreCase("STRONG")) isStrong = true; else if (name.equalsIgnoreCase("TITLE")) isTtitle = true; if (tag.breaksFlow()) carriageReturn(); } public void visitEndTag(Tag tag) { String name; name = tag.getTagName(); if (name.equalsIgnoreCase("PRE")) mIsPre = false; else if (name.equalsIgnoreCase("SCRIPT")) mIsScript = false; else if (name.equalsIgnoreCase("STYLE")) mIsStyle = false; else if (name.equalsIgnoreCase("META")) mIsMeta = false; else if (name.startsWith("[H|h]")) mIsH = false; else if (name.equalsIgnoreCase("STRONG")) isStrong = false; else if (name.equalsIgnoreCase("TITLE")) isTtitle = false; } public String getText() { return textBuf.toString(); } public String getDigest(){ return digest.toString(); } public String getKeywords(){ return keywords.toString(); } public String getTitle(){ return title; } public Map<String, Object> getHashedTextTags(){ return textTags; } protected void collapse(StringBuilder buffer, String string) { int chars; char character; chars = string.length(); if (0 != chars) { for (int i = 0; i < chars; i++) { character = string.charAt(i); switch (character) { // see HTML specification section 9.1 White space // http://www.w3.org/TR/html4/struct/text.html#h-9.1 case '\u0020': case '\u0009': case '\u000C': case '\u200B': case '\r': case '\n': if (0 != mCollapseState) mCollapseState = 1; break; default: if (1 == mCollapseState) buffer.append(' '); mCollapseState = 2; buffer.append(character); } } } } }
评论
额 java搞个html parse 也弄那么麻烦...还是ruby好..
我正准备改行搞ruby捏
发表评论
-
管中窥豹,结合多线程,对于tomcat中servlet加载的一点试探
2010-05-18 23:58 3157对于Servlet自己的生命周 ... -
测试Java反射效率
2010-05-15 23:58 6302测试分为3个方面:1. 实例化效率;2. 方法调用效率;3. ... -
传一本书里的代码
2010-04-13 22:24 1354RT 我把编译产生的bin删了,小了很多 -
想想我們大學都教了啥, 差距呀
2010-03-27 01:02 1109昨天还发现了一个新的概念,叫OAuth,OpenSSO ... -
我也說說OpenSSO
2010-03-24 22:24 1500昨天看到Oracle要關閉OpenSSO的消息,還說要 ... -
考慮用g4j實現一個gmail客戶端
2010-03-20 20:37 1031公司考慮信息安全,所以圖允許我們在公司里使用gmail ... -
Gmailer api for java
2010-03-19 16:43 1020今天研究了一下子g4j,這個東西,沒弄完,因為公司里面不能隨便 ... -
网站莫名其妙老是挂,原来是线程数太小
2009-11-04 07:54 3285昨天下午我们那个网站忽然变得很慢,我登上去看了下,没发现什么异 ... -
我设计的权限管理方案
2009-06-15 00:34 1845这是给我们学校的某管 ... -
自己做的简单的web服务器
2009-06-14 20:39 2427我最近修的电子商务概论的课程,老师布置的作业,是要做个简单的w ... -
(两年前初学JAVA时写过的一篇文章,发现给我们班同学看还挺有用的)
2009-06-04 04:02 1236最近装了 fedora 7感觉满好,虽然许多人都推崇ubunt ... -
记两次服务器不能启动大原因
2009-05-25 22:44 1141遇到这种很诡异的情况,tomcat无缘无故不能启动,一直处于s ... -
利用Java开源库把汉字转拼音
2009-05-21 02:52 35310最近做的项目,因为下拉框中的项目太多,需要有个过滤的方法。我想 ... -
java 预申请磁盘空间处理大文件
2009-05-09 03:40 1587熟悉电驴和bt的你可能经常看到这些软件可以在下载文件之初就先在 ... -
自己封装的一个编码转换工具类
2009-05-01 23:34 2045java做编码转换有两中方法 1.基于流的编码转换 I ... -
用httpclient模仿firefox发送http请求
2009-04-10 12:18 7164最近需要做爬虫,研究了一下进行做http客户端的东 ... -
在Java中实现伪静态页面
2009-02-18 14:58 3500在Java中做这个事情好像有很多中方案,比较简单的方法是使用U ... -
关于Hibernate懒加载问题的最终解决方案
2009-02-18 14:40 12487Hibernate的强大之处之一是懒加载功能,可以有效的降低数 ...
相关推荐
1. **DOMParser的基本使用**: 使用DOMParser解析XML文档,首先需要创建一个DOMParser实例,然后调用其`parseFromString()`方法,传入XML字符串作为参数。例如: ```javascript let parser = new DOMParser(); ...
2. **基本语法**:使用`logparser "query" -i:input_format -o:output_format -d:database_file`命令,其中`query`是SQL查询语句,`input_format`指定输入数据格式,`output_format`设定输出格式,`database_file`为...
这个压缩包中的内容可能包含了一系列使用JavaParser进行代码分析的示例或工具,特别是关于方法调用链的分析。这种方法调用链分析在软件工程中具有重要的应用价值,比如代码审查、性能优化、依赖关系理解以及重构等。...
5. **使用方法** 使用SQLParser时,首先需要引入相应的库,然后调用解析函数,传入SQL字符串,得到AST。接着,可以通过遍历树结构,提取所需信息或者修改节点来实现自定义逻辑。此外,有些SQLParser还支持将AST再...
下面我们将深入探讨`arg_parser`的核心概念、功能、使用方法以及源码中的关键部分。 1. **命令行参数解析** 命令行参数是程序启动时在操作系统命令行界面中传递的额外信息,如`./program -v --input file.txt`。`...
例如,Parser()构造函数用于创建一个新的Parser对象,而Parser(URLConnection connection)构造函数则用于创建一个Parser对象,并使用指定的URLConnection对象。 方法 Parser类提供了多种方法用于解析HTML网页。...
首先,我们需要了解XMLParser的基本工作原理。XMLParser遵循SAX(Simple API for XML)模型,即事件驱动的解析方式。在解析过程中,XMLParser会逐行读取XML文档,每当遇到一个开始标签、结束标签、文本节点等元素时...
通过研究这个示例,开发者可以快速了解MP4 Parser的用法,以便在自己的项目中应用。 在学习和使用MP4 Parser时,以下几个关键概念是必须掌握的: - **Box(框)**:MP4文件由一系列的Box组成,每个Box都包含特定的...
1. **读取源文件**:使用mp4parser的`IsoFile`类加载MP4文件,该类提供了对Box的访问。 2. **定位切割点**:通过遍历`Track`对象,找到需要切割的时间点对应的Sample。 3. **创建新文件**:创建一个新的`IsoFile`...
首先,你需要理解LogParser的基本用法和语法,包括如何指定输入源(如IIS日志)、选择查询字段以及使用各种聚合函数。 1. **基本用法**: 使用LogParser时,你需要在命令行中提供一系列参数,包括输入源(如-I参数...
本文将深入探讨SQLParser的基本概念、工作原理以及在实际开发中的应用。 SQLParser的核心功能在于解析SQL语句,将其转换为易于理解的数据结构,如抽象语法树(AST)。这样,开发者可以对SQL语句进行分析、验证、...
使用PullParser的基本步骤如下: 1. **获取Parser实例**:使用`XmlPullParserFactory`工厂类创建`XmlPullParser`实例,设置解析模式和属性。 2. **设置输入源**:调用`setInput()`方法,传入XML数据的输入流或字符...
以下是一个简单的例子,展示如何使用PHP-Parser进行基本的代码分析: ```php use PhpParser\ParserFactory; use PhpParser\PrettyPrinter\Standard; $parser = (new ParserFactory)->create(ParserFactory::PREFER...
本文将详细介绍apk-parser的使用方法和核心功能。 apk-parser是一个高效且全面的APK解析库,它的主要目标是帮助开发者和安全研究人员快速获取APK的详细信息。通过这个库,我们可以轻松地获取到APK的以下几个关键...
使用C# SQLParser时,开发者首先需要实例化解析器对象,然后调用其方法对SQL语句进行分析。例如,如果要添加`WHERE`条件,可以找到对应的表和列,并插入条件表达式。同样,添加`ORDER BY`语句则需要指定排序的字段和...
本文将深入探讨这个库的功能、使用方法及其在实际项目中的应用。 首先,filesize-parser的核心功能在于将文件大小的字节值转化为用户友好的字符串。在计算机世界里,文件大小通常以字节(Byte)为单位,但面对KB、...
教程通常会涵盖安装步骤、基本用法、常见问题以及可能的自定义扩展。通过学习这篇教程,开发者不仅可以掌握"emoji-parser"的基本使用,还能了解到更多关于表情解析的原理和技术细节。 总的来说,"emoji-parser"为小...
总之,"Parser微信小程序富文本转换附使用方法.rar"提供了一种有效的方法,帮助开发者解决微信小程序中处理富文本的难题。通过学习和使用Parser,你可以更灵活地展示和交互富文本内容,提升用户在小程序内的体验。