須要作一個垂直搜索引擎,比較了nekohtml和htmlparser 的功能,儘管nekohtml在容錯性、性能等方面的口碑好像比htmlparser好(htmlunit也用的是nekohtml),但感受 nekohtml的測試用例和文檔都比htmlparser都少,並且htmlparser基本上可以知足垂直搜索引擎頁面處理分析的需求,所以先研究一 下htmlparser的使用,有空再研究nekohtml和mozilla html parser的使用。
html的功能仍是官方說得最爲清楚,
引用
HTML Parser is a Java library used to parse HTML in either a linear or nested fashion. Primarily used for transformation or extraction, it features filters, visitors, custom tags and easy to use JavaBeans. It is a fast, robust and well tested package.
The two fundamental use-cases that are handled by the parser are extraction and transformation (the syntheses use-case, where HTML pages are created from scratch, is better handled by other tools closer to the source of data). While prior versions concentrated on data extraction from web pages, Version 1.4 of the HTMLParser has substantial improvements in the area of transforming web pages, with simplified tag creation and editing, and verbatim toHtml() method output.
研究的重點仍是extraction的使用,有空再研究transformation的使用。
一、htmlparser對html頁面處理的數據結構
如圖所示,HtmlParser採用了經典的Composite模式,經過RemarkNode、TextNode、TagNode、AbstractNode和Tag來描述HTML頁面各元素。
* org.htmlparser.Node:
Node接口定義了進行樹形結構節點操做的各類典型操做方法,包括:
節點到html文本、text文本的方法:toPlainTextString、toHtml
典型樹形結構遍歷的方法:getParent、getChildren、getFirstChild、getLastChild、getPreviousSibling、getNextSibling、getText
獲取節點對應的樹形結構結構的頂級節點Page對象方法:getPage
獲取節點起始位置的方法:getStartPosition、getEndPosition
Visitor方法遍歷節點時候方法:accept (NodeVisitor visitor)
Filter方法:collectInto (NodeList list, NodeFilter filter)
Object方法:toString、clone
* org.htmlparser.nodes.AbstractNode:
AbstractNode是造成HTML樹形結構抽象基類,實現了Node接口。
在htmlparser中,Node分紅三類:
RemarkNode:表明Html中的註釋
TagNode:標籤節點。
TextNode:文本節點
這三類節點都繼承AbstractNode。
* org.htmlparser.nodes.TagNode:
TagNode包含了對HTML處理的核心的各個類,是全部TAG的基類,其中有分爲包含其餘TAG的複合節點ComositeTag和不包含其餘TAG的葉子節點Tag。
複合節點CompositeTag:
AppletTag,BodyTag,Bullet,BulletList,DefinitionList,DefinitionListBullet,Div,FormTag,FrameSetTag,HeadingTag,
HeadTag,Html,LabelTag,LinkTag,ObjectTag,ParagraphTag,ScriptTag,SelectTag,Span,StyleTag,TableColumn,
TableHeader,TableRow,TableTag,TextareaTag,TitleTag
葉子節點TAG:
BaseHrefTag,DoctypeTag,FrameTag,ImageTag,InputTag,JspTag,MetaTag,ProcessingInstructionTag,
二、htmlparser對html頁面處理的算法
主要是以下幾種方式
引用
HTML Parser is a Java library used to parse HTML in either a linear or nested fashion. Primarily used for transformation or extraction, it features filters, visitors, custom tags and easy to use JavaBeans. It is a fast, robust and well tested package.
The two fundamental use-cases that are handled by the parser are extraction and transformation (the syntheses use-case, where HTML pages are created from scratch, is better handled by other tools closer to the source of data). While prior versions concentrated on data extraction from web pages, Version 1.4 of the HTMLParser has substantial improvements in the area of transforming web pages, with simplified tag creation and editing, and verbatim toHtml() method output.
研究的重點仍是extraction的使用,有空再研究transformation的使用。
一、htmlparser對html頁面處理的數據結構
- * 採用Visitor方式訪問Html
-
- try {
- Parser parser = new Parser();
- parser.setURL(」http:
- parser.setEncoding(parser.getEncoding());
- NodeVisitor visitor = new NodeVisitor() {
- public void visitTag(Tag tag) {
- logger.fatal(」testVisitorAll() Tag name is :」
- + tag.getTagName() + 」 \n Class is :」
- + tag.getClass());
- }
-
- };
-
- parser.visitAllNodesWith(visitor);
- } catch (ParserException e) {
- e.printStackTrace();
- }
-
- * 採用Filter方式訪問html
-
- try {
-
- NodeFilter filter = new NodeClassFilter(LinkTag.class);
- Parser parser = new Parser();
- parser.setURL(」http:
- parser.setEncoding(parser.getEncoding());
- NodeList list = parser.extractAllNodesThatMatch(filter);
- for (int i = 0; i < list.size(); i++) {
- LinkTag node = (LinkTag) list.elementAt(i);
- logger.fatal(」testLinkTag() Link is :」 + node.extractLink());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- * 採用org.htmlparser.beans方式
-
- 另外htmlparser 還在org.htmlparser.beans中對一些經常使用的方法進行了封裝,以簡化操做,例如:
-
- Parser parser = new Parser();
-
- LinkBean linkBean = new LinkBean();
- linkBean.setURL(」http:
- URL[] urls = linkBean.getLinks();
-
- for (int i = 0; i < urls.length; i++) {
- URL url = urls[i];
- logger.fatal(」testLinkBean() -url is :」 + url);
- }
-
-
- 3、htmlparser關鍵包結構說明
-
- htmlparser其實核心代碼並很少,好好研究一下其代碼,彌補文檔不足的問題。同時htmlparser的代碼註釋和單元測試用例仍是很齊全的,也有助於瞭解htmlparser的用法。
-
-
- 3.1、org.htmlparser
-
- 定義了htmlparser的一些基礎類。其中最爲重要的是Parser類。
-
- Parser是htmlparser的最核心的 類,其構造函數提供瞭如 下:Parser.createParser (String html, String charset)、 Parser ()、 Parser (Lexer lexer, ParserFeedback fb)、 Parser (URLConnection connection, ParserFeedback fb)、 Parser (String resource, ParserFeedback feedback)、 Parser (String resource)
-
- 各構造函數的具體用法及含義能夠查看其代碼,很容易理解。
-
- Parser經常使用的幾個方法:
-
- * elements獲取元素
-
- Parser parser = new Parser (」http:
- for (NodeIterator i = parser.elements (); i.hasMoreElements (); )
- processMyNodes (i.nextNode ());
-
- * parse (NodeFilter filter):經過NodeFilter方式獲取
- * visitAllNodesWith (NodeVisitor visitor):經過Nodevisitor方式
- * extractAllNodesThatMatch (NodeFilter filter):經過NodeFilter方式
-
- 3.2、org.htmlparser.beans
-
- 對Visitor和Filter的方法進行了封裝,定義了針對一些經常使用html元素操做的bean,簡化對經常使用元素的提取操做。
-
- 包括:FilterBean、HTMLLinkBean、HTMLTextBean、LinkBean、StringBean、BeanyBaby等。
- 3.3、org.htmlparser.nodes
-
- 定義了基礎的node,包括:AbstractNode、RemarkNode、TagNode、TextNode等。
- 3.4、org.htmlparser.tags
-
- 定義了htmlparser的各類tag。
- 3.5、org.htmlparser.filters
-
- 定義了htmlparser所提供的各類 filter,主要經過extractAllNodesThatMatch (NodeFilter filter)來對html頁面指定類型的元素進行 過濾,包括:AndFilter、CssSelectorNodeFilter、 HasAttributeFilter、 HasChildFilter、HasParentFilter、HasSiblingFilter、 IsEqualFilter、 LinkRegexFilter、LinkStringFilter、NodeClassFilter、 NotFilter、OrFilter、 RegexFilter、StringFilter、TagNameFilter、XorFilter
- 3.6、org.htmlparser.visitors
-
- 定義了htmlparser所提供的各類 visitor,主要經過visitAllNodesWith (NodeVisitor visitor)來對html頁面元素進行遍歷,包 括:HtmlPage、LinkFindingVisitor、NodeVisitor、 ObjectFindingVisitor、 StringFindingVisitor、TagFindingVisitor、 TextExtractingVisitor、 UrlModifyingVisitor
-
-
- 3.7、org.htmlparser.parserapplications
-
- 定義了一些實用的工具,包括LinkExtractor、SiteCapturer、StringExtractor、WikiCapturer,這幾個類也能夠做爲htmlparser使用樣例。
- 3.8、org.htmlparser.tests
-
- 對各類功能的單元測試用例,也能夠做爲htmlparser使用的樣例。
-
-
- 4、htmlparser的使用樣例
-
-
-
- import java.net.URL;
-
- import junit.framework.TestCase;
-
- import org.apache.log4j.Logger;
- import org.htmlparser.Node;
- import org.htmlparser.NodeFilter;
- import org.htmlparser.Parser;
- import org.htmlparser.Tag;
- import org.htmlparser.beans.LinkBean;
- import org.htmlparser.filters.NodeClassFilter;
- import org.htmlparser.filters.OrFilter;
- import org.htmlparser.filters.TagNameFilter;
- import org.htmlparser.tags.HeadTag;
- import org.htmlparser.tags.ImageTag;
- import org.htmlparser.tags.InputTag;
- import org.htmlparser.tags.LinkTag;
- import org.htmlparser.tags.OptionTag;
- import org.htmlparser.tags.SelectTag;
- import org.htmlparser.tags.TableColumn;
- import org.htmlparser.tags.TableRow;
- import org.htmlparser.tags.TableTag;
- import org.htmlparser.tags.TitleTag;
- import org.htmlparser.util.NodeIterator;
- import org.htmlparser.util.NodeList;
- import org.htmlparser.util.ParserException;
- import org.htmlparser.visitors.HtmlPage;
- import org.htmlparser.visitors.NodeVisitor;
- import org.htmlparser.visitors.ObjectFindingVisitor;
-
- public class ParserTestCase extends TestCase {
-
- private static final Logger logger = Logger.getLogger(ParserTestCase.class);
-
- public ParserTestCase(String name) {
- super(name);
- }
-
-
-
- public void testImageVisitor() {
- try {
- ImageTag imgLink;
- ObjectFindingVisitor visitor = new ObjectFindingVisitor(
- ImageTag.class);
- Parser parser = new Parser();
- parser.setURL(」http:
- parser.setEncoding(parser.getEncoding());
- parser.visitAllNodesWith(visitor);
- Node[] nodes = visitor.getTags();
- for (int i = 0; i < nodes.length; i++) {
- imgLink = (ImageTag) nodes[i];
- logger.fatal(」testImageVisitor() ImageURL = 「
- + imgLink.getImageURL());
- logger.fatal(」testImageVisitor() ImageLocation = 「
- + imgLink.extractImageLocn());
- logger.fatal(」testImageVisitor() SRC = 「
- + imgLink.getAttribute(」SRC」));
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-
-
- public void testNodeFilter() {
- try {
- NodeFilter filter = new TagNameFilter(」IMG」);
- Parser parser = new Parser();
- parser.setURL(」http:
- parser.setEncoding(parser.getEncoding());
- NodeList list = parser.extractAllNodesThatMatch(filter);
- for (int i = 0; i < list.size(); i++) {
- logger.fatal(」testNodeFilter() 」 + list.elementAt(i).toHtml());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
-
-
- public void testLinkTag() {
- try {
-
- NodeFilter filter = new NodeClassFilter(LinkTag.class);
- Parser parser = new Parser();
- parser.setURL(」http:
- parser.setEncoding(parser.getEncoding());
- NodeList list = parser.extractAllNodesThatMatch(filter);
- for (int i = 0; i < list.size(); i++) {
- LinkTag node = (LinkTag) list.elementAt(i);
- logger.fatal(」testLinkTag() Link is :」 + node.extractLink());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
-
-
- public void testLinkCSS() {
- try {
-
- Parser parser = new Parser();
- parser
- .setInputHTML(」<head><title>Link Test</title>」
- + 「<link href=’/test01/css.css’ text=’text/css’ rel=’stylesheet’ />」
- + 「<link href=’/test02/css.css’ text=’text/css’ rel=’stylesheet’ />」
- + 「</head>」 + 「<body>」);
- parser.setEncoding(parser.getEncoding());
- NodeList nodeList = null;
-
- for (NodeIterator e = parser.elements(); e.hasMoreNodes();) {
- Node node = e.nextNode();
- logger
- .fatal(」testLinkCSS()」 + node.getText()
- + node.getClass());
-
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-
-
- public void testOrFilter() {
- NodeFilter inputFilter = new NodeClassFilter(InputTag.class);
- NodeFilter selectFilter = new NodeClassFilter(SelectTag.class);
- Parser myParser;
- NodeList nodeList = null;
-
- try {
- Parser parser = new Parser();
- parser
- .setInputHTML(」<head><title>OrFilter Test</title>」
- + 「<link href=’/test01/css.css’ text=’text/css’ rel=’stylesheet’ />」
- + 「<link href=’/test02/css.css’ text=’text/css’ rel=’stylesheet’ />」
- + 「</head>」
- + 「<body>」
- + 「<input type=’text’ value=’text1′ name=’text1′/>」
- + 「<input type=’text’ value=’text2′ name=’text2′/>」
- + 「<select><option id=’1′>1</option><option id=’2′>2</option><option id=’3′></option></select>」
- + 「<a href=’http:
- + 「</body>」);
-
- parser.setEncoding(parser.getEncoding());
- OrFilter lastFilter = new OrFilter();
- lastFilter.setPredicates(new NodeFilter[] { selectFilter,
- inputFilter });
- nodeList = parser.parse(lastFilter);
- for (int i = 0; i <= nodeList.size(); i++) {
- if (nodeList.elementAt(i) instanceof InputTag) {
- InputTag tag = (InputTag) nodeList.elementAt(i);
- logger.fatal(」OrFilter tag name is :」 + tag.getTagName()
- + 」 ,tag value is:」 + tag.getAttribute(」value」));
- }
- if (nodeList.elementAt(i) instanceof SelectTag) {
- SelectTag tag = (SelectTag) nodeList.elementAt(i);
- NodeList list = tag.getChildren();
-
- for (int j = 0; j < list.size(); j++) {
- OptionTag option = (OptionTag) list.elementAt(j);
- logger
- .fatal(」OrFilter Option」
- + option.getOptionText());
- }
-
- }
- }
-
- } catch (ParserException e) {
- e.printStackTrace();
- }
- }
-
-
-
- public void testTable() {
- Parser myParser;
- NodeList nodeList = null;
- myParser = Parser.createParser(」<body> 」 + 「<table id=’table1′ >」
- + 「<tr><td>1-11</td><td>1-12</td><td>1-13</td>」
- + 「<tr><td>1-21</td><td>1-22</td><td>1-23</td>」
- + 「<tr><td>1-31</td><td>1-32</td><td>1-33</td></table>」
- + 「<table id=’table2′ >」
- + 「<tr><td>2-11</td><td>2-12</td><td>2-13</td>」
- + 「<tr><td>2-21</td><td>2-22</td><td>2-23</td>」
- + 「<tr><td>2-31</td><td>2-32</td><td>2-33</td></table>」
- + 「</body>」, 「GBK」);
- NodeFilter tableFilter = new NodeClassFilter(TableTag.class);
- OrFilter lastFilter = new OrFilter();
- lastFilter.setPredicates(new NodeFilter[] { tableFilter });
//轉自:[url]http://hao861002.javaeye.com/blog/290985[/url]