`
tuoxie007
  • 浏览: 162758 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

http parser 基本用法

    博客分类:
  • 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);
				}
			}
		}
	}
}
 
分享到:
评论
2 楼 tuoxie007 2009-05-02  
Hooopo 写道

额 java搞个html parse 也弄那么麻烦...还是ruby好..

我正准备改行搞ruby捏
1 楼 Hooopo 2009-05-02  
额 java搞个html parse 也弄那么麻烦...还是ruby好..

相关推荐

    DOMParser解析xml

    1. **DOMParser的基本使用**: 使用DOMParser解析XML文档,首先需要创建一个DOMParser实例,然后调用其`parseFromString()`方法,传入XML字符串作为参数。例如: ```javascript let parser = new DOMParser(); ...

    LogParser IIS分析工具以及使用教程

    2. **基本语法**:使用`logparser "query" -i:input_format -o:output_format -d:database_file`命令,其中`query`是SQL查询语句,`input_format`指定输入数据格式,`output_format`设定输出格式,`database_file`为...

    基于JavaParser的代码调用链分析,可以用于分析Java代码的方法调用链.zip

    这个压缩包中的内容可能包含了一系列使用JavaParser进行代码分析的示例或工具,特别是关于方法调用链的分析。这种方法调用链分析在软件工程中具有重要的应用价值,比如代码审查、性能优化、依赖关系理解以及重构等。...

    SQL Parser

    5. **使用方法** 使用SQLParser时,首先需要引入相应的库,然后调用解析函数,传入SQL字符串,得到AST。接着,可以通过遍历树结构,提取所需信息或者修改节点来实现自定义逻辑。此外,有些SQLParser还支持将AST再...

    arg_parser 源码

    下面我们将深入探讨`arg_parser`的核心概念、功能、使用方法以及源码中的关键部分。 1. **命令行参数解析** 命令行参数是程序启动时在操作系统命令行界面中传递的额外信息,如`./program -v --input file.txt`。`...

    parser中文API以及示例.pdf

    例如,Parser()构造函数用于创建一个新的Parser对象,而Parser(URLConnection connection)构造函数则用于创建一个Parser对象,并使用指定的URLConnection对象。 方法 Parser类提供了多种方法用于解析HTML网页。...

    XMLParser iphone

    首先,我们需要了解XMLParser的基本工作原理。XMLParser遵循SAX(Simple API for XML)模型,即事件驱动的解析方式。在解析过程中,XMLParser会逐行读取XML文档,每当遇到一个开始标签、结束标签、文本节点等元素时...

    视频编辑MP4 Parser代码与jar包

    通过研究这个示例,开发者可以快速了解MP4 Parser的用法,以便在自己的项目中应用。 在学习和使用MP4 Parser时,以下几个关键概念是必须掌握的: - **Box(框)**:MP4文件由一系列的Box组成,每个Box都包含特定的...

    mp4parser实现视频切割拼接方法

    1. **读取源文件**:使用mp4parser的`IsoFile`类加载MP4文件,该类提供了对Box的访问。 2. **定位切割点**:通过遍历`Track`对象,找到需要切割的时间点对应的Sample。 3. **创建新文件**:创建一个新的`IsoFile`...

    LogParser导入log数据至数据库

    首先,你需要理解LogParser的基本用法和语法,包括如何指定输入源(如IIS日志)、选择查询字段以及使用各种聚合函数。 1. **基本用法**: 使用LogParser时,你需要在命令行中提供一系列参数,包括输入源(如-I参数...

    Fundamentals.SQLParser.4.0.01

    本文将深入探讨SQLParser的基本概念、工作原理以及在实际开发中的应用。 SQLParser的核心功能在于解析SQL语句,将其转换为易于理解的数据结构,如抽象语法树(AST)。这样,开发者可以对SQL语句进行分析、验证、...

    pullparser的jar包.rar

    使用PullParser的基本步骤如下: 1. **获取Parser实例**:使用`XmlPullParserFactory`工厂类创建`XmlPullParser`实例,设置解析模式和属性。 2. **设置输入源**:调用`setInput()`方法,传入XML数据的输入流或字符...

    PHP-Parser-master.zip

    以下是一个简单的例子,展示如何使用PHP-Parser进行基本的代码分析: ```php use PhpParser\ParserFactory; use PhpParser\PrettyPrinter\Standard; $parser = (new ParserFactory)-&gt;create(ParserFactory::PREFER...

    apk-parser-2.6.9包文件.zip

    本文将详细介绍apk-parser的使用方法和核心功能。 apk-parser是一个高效且全面的APK解析库,它的主要目标是帮助开发者和安全研究人员快速获取APK的详细信息。通过这个库,我们可以轻松地获取到APK的以下几个关键...

    c# sqlparser

    使用C# SQLParser时,开发者首先需要实例化解析器对象,然后调用其方法对SQL语句进行分析。例如,如果要添加`WHERE`条件,可以找到对应的表和列,并插入条件表达式。同样,添加`ORDER BY`语句则需要指定排序的字段和...

    前端开源库-filesize-parser

    本文将深入探讨这个库的功能、使用方法及其在实际项目中的应用。 首先,filesize-parser的核心功能在于将文件大小的字节值转化为用户友好的字符串。在计算机世界里,文件大小通常以字节(Byte)为单位,但面对KB、...

    emoji-parser.zip

    教程通常会涵盖安装步骤、基本用法、常见问题以及可能的自定义扩展。通过学习这篇教程,开发者不仅可以掌握"emoji-parser"的基本使用,还能了解到更多关于表情解析的原理和技术细节。 总的来说,"emoji-parser"为小...

    Parser微信小程序富文本转换附使用方法.rar

    总之,"Parser微信小程序富文本转换附使用方法.rar"提供了一种有效的方法,帮助开发者解决微信小程序中处理富文本的难题。通过学习和使用Parser,你可以更灵活地展示和交互富文本内容,提升用户在小程序内的体验。

Global site tag (gtag.js) - Google Analytics