当前位置:文档之家› Java HTMLParser使用详解

Java HTMLParser使用详解

Java HTMLParser使用详解
Java HTMLParser使用详解

声明:本人来自转载

https://www.doczj.com/doc/677875292.html,/

HTMLParser具有小巧,快速的优点,缺点是相关文档比较少(英文的也少),很多功能需要自己摸索。对于初学者还是要费一些功夫的,而一旦上手以后,会发现HTMLParser 的结构设计很巧妙,非常实用,基本你的各种需求都可以满足。

这里我根据自己这几个月来的经验,写了一点入门的东西,希望能对新学习HTMLParser 的朋友们有所帮助。(不过当年高考本人语文只比及格高一分,所以文法方面的问题还希望大家多多担待)

HTMLParser的核心模块是org.htmlparser.Parser类,这个类实际完成了对于HTML页面的分析工作。这个类有下面几个构造函数:

public Parser ();

public Parser (Lexer lexer, ParserFeedback fb);

public Parser (URLConnection connection, ParserFeedback fb) throws ParserException; public Parser (String resource, ParserFeedback feedback) throws ParserException; public Parser (String resource) throws ParserException;

public Parser (Lexer lexer);

public Parser (URLConnection connection) throws ParserException;

和一个静态类

public static Parser createParser (String html, String charset);

对于大多数使用者来说,使用最多的是通过一个URLConnection或者一个保存有网页内容的字符串来初始化Parser,或者使用静态函数来生成一个Parser对象。

ParserFeedback的代码很简单,是针对调试和跟踪分析过程的,一般不需要改变。而使用Lexer则是一个相对比较高级的话题,放到以后再讨论吧。

这里比较有趣的一点是,如果需要设置页面的编码方式的话,不使用Lexer就只有静态函数一个方法了。对于大多数中文页面来说,好像这是应该用得比较多的一个方法。

下面是初始化Parser的例子。

package com.baizeju.htmlparsertester;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.FileInputStream;

import java.io.File;

import https://www.doczj.com/doc/677875292.html,.HttpURLConnection;

import https://www.doczj.com/doc/677875292.html,.URL;

import org.htmlparser.visitors.TextExtractingVisitor;

import org.htmlparser.Parser;

/**

* @author https://www.doczj.com/doc/677875292.html,

*/

public class Main {

private static String ENCODE = "GBK";

private static void message( String szMsg )

{

try

{

System.out.println(new

String(szMsg.getBytes(ENCODE),

System.getProperty("file.encoding")));

}

catch(Exception e )

{}

}

public static String openFile( String szFileName )

{

try {

BufferedReader bis = new BufferedReader

(new InputStreamReader

(new FileInputStream

( new File(szFileName)),

ENCODE) );

String szContent="";

String szTemp;

while ( (szTemp = bis.readLine()) != null)

{

szContent+=szTemp+"\n";

}

bis.close();

return szContent;

}

catch( Exception e )

{

return "";

}

}

public static void main(String[] args)

{

String szContent = openFile( "E:/My Sites/HTMLParserTester.html");

try{

//Parser parser = Parser.createParser(szContent, ENCODE);

//Parser parser = new Parser( szContent );

Parser parser = new Parser( (HttpURLConnection)

(new URL("http://127.0.0.1:8080/HTMLParserTester.html")).openConnection()

);

TextExtractingVisitor visitor = new TextExtractingVisitor();

parser.visitAllNodesWith(visitor);

String textInPage = visitor.getExtractedText();

message(textInPage);

}

catch( Exception e )

{ }

}

}

加重的部分测试了几种不同的初始化方法,后面的显示了结果。大家看到能Parser出内容就可以了,如何操作访问Parser的内容我们在后面讨论。

HTMLParser将解析过的信息保存为一个树的结构。

Node是信息保存的数据类型基础。

请看Node的定义:

public interface Node extends Cloneable;

Node中包含的方法有几类,对于树型结构进行遍历的函数,这些函数最容易理解:

Node getParent():取得父节点

NodeList getChildren():取得子节点的列表

Node getFirstChild ():取得第一个子节点

Node getLastChild():取得最后一个子节点

Node getPreviousSibling ():取得前一个兄弟(不好意思,英文是兄弟姐妹,直译太麻烦而且不符合习惯,对不起女同胞了)

Node getNextSibling():取得下一个兄弟节点

取得Node内容的函数:

String getText():取得文本

String toPlainTextString():取得纯文本信息。

String toHtml() :取得HTML信息(原始HTML)

String toHtml(boolean verbatim):

取得HTML信息(原始HTML)

String toString():取得字符串信息(原始HTML)

Page getPage ():取得这个Node对应的Page对象

int getStartPosition ():取得这个Node在HTML页面中的起始位置

int getEndPosition():取得这个Node在HTML页面中的结束位置

用于Filter过滤的函数:

void collectInto(NodeList list, NodeFilter filter):基于filter的条件对于这个节点进行过滤,符合条件的节点放到list中。

用于Visitor遍历的函数:

void accept(NodeVisitor visitor):对这个Node应用visitor

用于修改内容的函数,这类用得比较少:

void setPage(Page page):设置这个Node对应的Page对象

void setText(String text):设置文本

void setChildren(NodeList children):设置子节点列表

其他函数:

void doSemanticAction():执行这个Node对应的操作(只有少数Tag有对应的操作)Object clone():接口Clone的抽象函数。

实际我们用HTMLParser最多的是处理HTML页面,Filter或Visitor相关的函数是必须的,然后第一类和第二类函数是用得最多的。第一类函数比较容易理解,下面用例子说明一下第二类函数。

下面是用于测试的HTML文件:

"https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd">

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

测试代码:

/**

* @author https://www.doczj.com/doc/677875292.html,

*/

package com.baizeju.htmlparsertester;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.FileInputStream;

import java.io.File;

import https://www.doczj.com/doc/677875292.html,.HttpURLConnection;

import https://www.doczj.com/doc/677875292.html,.URL;

import org.htmlparser.Node;

import org.htmlparser.util.NodeIterator;

import org.htmlparser.Parser;

/**

* @author https://www.doczj.com/doc/677875292.html,

*/

public class Main {

private static String ENCODE = "GBK";

private static void message( String szMsg )

{

try

{

System.out.println(new String(szMsg.getBytes(ENCODE), System.getProperty("f ile.encoding"))); }

catch(Exception e )

{}

}

public static String openFile( String szFileName )

{

try

{

BufferedReader bis = new BufferedReader(new InputStreamReader(new FileInp utStream( new

File(szFileName)), ENCODE) );

String szContent="";

String szTemp;

while ( (szTemp = bis.readLine()) != null)

{

szContent+=szTemp+"\n";

}

bis.close();

return szContent;

}

catch( Exception e )

{

return "";

}

}

public static void main(String[] args)

{

try{

Parser parser = new Parser( (HttpURLConnection) (new

URL("http://127.0.0.1:8080/HTMLParserTester.html")).openConnection() );

for (NodeIterator i = parser.elements (); i.hasMoreNodes();)

{

Node node = i.nextNode();

message("getText:"+node.getText());

message("getPlainText:"+node.toPlainTextString());

message("toHtml:"+node.toHtml());

message("toHtml(true):"+node.toHtml(true));

message("toHtml(false):"+node.toHtml(false));

message("toString:"+node.toString());

message("=================================================");

}

}

catch( Exception e ) {

System.out.println( "Exception:"+e );

}

}

}

输出结果:

getText:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd"

getPlainText:

toHtml:

"https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd">

toHtml(true):

toHtml(false):

toString:Doctype Tag : !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//E N"

"https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd; begins at : 0; ends at : 121 ================================================= getText:

getPlainText:

toHtml:

toHtml(true):

toHtml(false):

toString:Txt (121[0,121],123[1,0]): \n

================================================= getText:head

getPlainText:白泽居https://www.doczj.com/doc/677875292.html,

toHtml:

白泽居https://www.doczj.com/doc/677875292.html,

toHtml(true):

白泽居https://www.doczj.com/doc/677875292.html,

toHtml(false):

白泽居https://www.doczj.com/doc/677875292.html,

toString:HEAD: Tag (123[1,0],129[1,6]): head

Tag (129[1,6],197[1,74]): meta http-equiv="Content-Type" content="text/html; ...

Tag (197[1,74],204[1,81]): title

Txt (204[1,81],223[1,100]): 白泽居https://www.doczj.com/doc/677875292.html,

End (223[1,100],231[1,108]): /title

End (231[1,108],238[1,115]): /head

================================================= getText:

getPlainText:

toHtml:

toHtml(true):

toHtml(false):

toString:Txt (238[1,115],240[2,0]): \n

=================================================

getText:html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml"

getPlainText:

白泽居https://www.doczj.com/doc/677875292.html, 白泽居https://www.doczj.com/doc/677875292.html, 白泽居https://www.doczj.com/doc/677875292.html,

toHtml:

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

toHtml(true):

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

toHtml(false):

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

toString:T ag (240[2,0],283[2,43]): html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml"

Txt (283[2,43],285[3,0]): \n

Tag (285[3,0],292[3,7]): body

Txt (292[3,7],294[4,0]): \n

Tag (294[4,0],313[4,19]): div id="top_main"

Txt (313[4,19],316[5,1]): \n\t

Tag (316[5,1],336[5,21]): div id="logoindex"

Txt (336[5,21],340[6,2]): \n\t\t

Rem (340[6,2],351[6,13]): 这是注释

Txt (351[6,13],376[8,0]): \n\t\t白泽居https://www.doczj.com/doc/677875292.html,\n

Tag (376[8,0],409[8,33]): a href="https://www.doczj.com/doc/677875292.html,"

Txt (409[8,33],428[8,52]): 白泽居https://www.doczj.com/doc/677875292.html,

End (428[8,52],432[8,56]): /a

Txt (432[8,56],435[9,1]): \n\t

End (435[9,1],441[9,7]): /div

Txt (441[9,7],465[11,0]): \n\t白泽居https://www.doczj.com/doc/677875292.html,\n

End (465[11,0],471[11,6]): /div

Txt (471[11,6],473[12,0]): \n

End (473[12,0],480[12,7]): /body

Txt (480[12,7],482[13,0]): \n

End (482[13,0],489[13,7]): /html

================================================= 对于第一个Node的内容,对应的就是第一行,这个比较好理解。

从这个输出结果中,也可以看出内容的树状结构。或者说是树林结构。在Page内容的第一层Tag,如DOCTYPE,head和html,分别形成了一个最高层的Node节点(很多人可能对第二个和第四个Node的内容有点奇怪。实际上这两个Node就是两个换行符号。HTMLParser把HTML页面内容中的所有换行,空格,Tab等都转换成了相应的Tag,所以就出现了这样的Node。虽然内容少但是级别高,呵呵)

getPlainTextString是把用户可以看到的内容都包含了。有趣的有两点,一是标签中的Title内容是在plainText中的,可能在标题中可见的也算可见吧。另外就是象前面说的,HTML内容中的换行符什么的,也都成了plainText,这个逻辑上好像有点问题。

另外可能大家发现toHtml,toHtml(true)和toHtml(false)的结果没什么区别。实际也是这样的,如果跟踪HTMLParser的代码就可以发现,Node的子类是AbstractNode,其中实现了toHtml()的代码,直接调用toHtml(false),而AbstractNode的三个子类RemarkNode,TagNode 和TextNode中,toHtml(boolean verbatim)的实现中,都没有处理verbatim参数,所以三个函数的结果是一模一样的。如果你不需要实现你自己的什么特殊处理,简单使用toHtml就可以了。

HTML的Node类继承关系如下图(这个是从别的文章Copy的):

AbstractNodes是Node的直接子类,也是一个抽象类。它的三个直接子类实现是RemarkNode,用于保存注释。在输出结果的toString部分中可以看到有一个"Rem (345[6,2],356[6,13]): 这是注释",就是一个RemarkNode。TextNode也很简单,就是用户可见的文字信息。TagNode是最复杂的,包含了HTML语言中的所有标签,而且可以扩展(扩展 HTMLParser 对自定义标签的处理能力)。TagNode包含两类,一类是简单的Tag,实际就是不能包含其他Tag的标签,只能做叶子节点。另一类是CompositeTag,就是可以包含其他Tag,是分支节点。

HTMLParser遍历了网页的内容以后,以树(森林)结构保存了结果。HTMLParser访问结果内容的方法有两种。使用Filter和使用Visitor。

(一)Filter类

顾名思义,Filter就是对于结果进行过滤,取得需要的内容。

HTMLParser在org.htmlparser.filters包之内一共定义了16个不同的Filter,也可以分为几类。

判断类

TagNameFilter

HasAttributeFilter

HasChildFilter

HasParentFilter

HasSiblingFilter

IsEqualFilter

逻辑运算Filter:

AndFilter

NotFilter

OrFilter

XorFilter

其他Filter:

NodeClassFilter

StringFilter

LinkStringFilter

LinkRegexFilter

RegexFilter

CssSelectorNodeFilter

所有的Filter类都实现了org.htmlparser.NodeFilter接口。

这个接口只有一个主要函数: boolean accept (Node node);

各个子类分别实现这个函数,用于判断输入的Node是否符合这个Filter的过滤条件,如果符合,返回true,否则返回false。

(二)判断类Filter 2.1 TagNameFilter

TabNameFilter是最容易理解的一个Filter,根据Tag的名字进行过滤。

下面是用于测试的HTML文件:

"https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd">

白泽居https://www.doczj.com/doc/677875292.html,

< /head>

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

白泽居https://www.doczj.com/doc/677875292.html,

测试代码:(这里只列出了Main函数,全部代码请参考 HTMLParser使用入门(2)- Node 内容,自己添加import部分)

public static void main(String[] args) {

try{

Parser parser = new Parser( (HttpURLConnection) (new URL("http://127.0.0.1 :8080/HTMLParserTester.html")).openConnection() );

// 这里是控制测试的部分,后面的例子修改的就是这个地方。

NodeFilter filter = new TagNameFilter ("DIV");

NodeList nodes = parser.extractAllNodesThatMatch(filter);

if(nodes!=null) {

for (int i = 0; i < nodes.size(); i++)

{

Node textnode = (Node) nodes.elementAt(i);

message("getText:"+textnode.getText());

message("=================================================");

}

}

}

catch( Exception e )

{

e.printStackTrace();

}

}

输出结果:

getText:div id="top_main"

================================================= getText:div id="logoindex"

=================================================

可以看出文件中两个Div节点都被取出了。下面可以针对这两个DIV节点进行操作

2.2 HasChildFilter

下面让我们看看HasChildFilter。刚刚看到这个Filter的时候,我想当然地认为这个Filter返回的是有Child的Tag。直接初始化了一个

NodeFilter filter = new HasChildFilter();

结果调用NodeList nodes = parser.extractAllNodesThatMatch(filter);

的时候HasChildFilter内部直接发生NullPointerException。读了一下HasChildFilter的代码,才发现,实际HasChildFilter是返回有符合条件的子节点的节点,需要另外一个Filter作为过滤子节点的参数。缺省的构造函数虽然可以初始化,但是由于子节点的Filter是null,所以使用的时候发生了Exception。从这点来看,

HTMLParser的代码还有很多可以优化的的地方。呵呵。

修改代码:

NodeFilter innerFilter = new TagNameFilter ("DIV");

NodeFilter filter = new HasChildFilter(innerFilter);

NodeList nodes = parser.extractAllNodesThatMatch(filter);

输出结果:

getText:body

================================================= getText:div id="top_main"

=================================================

可以看到,输出的是两个有DIV子Tag的Tag节点。(body有子节点DIV "top_main","top_main"有子节点"logoindex"。

注意HasChildFilter还有一个构造函数:

public HasChildFilter (NodeFilter filter, boolean recursive)

如果recursive是false,则只对第一级子节点进行过滤。比如前面的例子,body和top_main

都是在第一级的子节点里就有DIV节点,所以匹配上了。如果我们用下面的方法调用:NodeFilter filter = new HasChildFilter( innerFilter, true );

输出结果:

getText:html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml"

================================================= getText:body

================================================= getText:div id="top_main"

=================================================

可以看到输出结果中多了一个html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml",这个是整个HTML页面的节点(根节点),虽然这个节点下直接没有DIV节点,但是它的子节点body 下面有DIV节点,所以它也被匹配上了。

2.3 HasAttributeFilter

HasAttributeFilter有3个构造函数:

public HasAttributeFilter ();

public HasAttributeFilter (String attribute);

public HasAttributeFilter (String attribute, String value);

这个Filter可以匹配出包含制定名字的属性,或者制定属性为指定值的节点。还是用例子说明比较容易。

调用方法1:

NodeFilter filter = new HasAttributeFilter();

NodeList nodes = parser.extractAllNodesThatMatch(filter);

输出结果:

什么也没有输出。

调用方法2:

NodeFilter filter = new HasAttributeFilter( "id" );

NodeList nodes = parser.extractAllNodesThatMatch(filter);

输出结果:

getText:div id="top_main"

================================================= getText:div id="logoindex"

=================================================

调用方法3:

NodeFilter filter = new HasAttributeFilter( "id", "logoindex" );

NodeList nodes = parser.extractAllNodesThatMatch(filter);

输出结果:

getText:div id="logoindex"

=================================================

很简单吧。呵呵

2.4 其他判断列Filter

HasParentFilter和HasSiblingFilter的功能与HasChildFilter类似,大家自己试一下就应该了

解了。

IsEqualFilter的构造函数参数是一个Node:

public IsEqualFilter (Node node)

{

mNode = node;

}

accept函数也很简单:

public boolean accept (Node node)

{

return (mNode == node);

}

不需要过多说明了。

(三)逻辑运算Filter

前面介绍的都是简单的Filter,只能针对某种单一类型的条件进行过滤。HTMLParser 支持对于简单类型的Filter进行组合,从而实现复杂的条件。原理和一般编程语言的逻辑运算是一样的。

3.1 AndFilter

AndFilter可以把两种Filter进行组合,只有同时满足条件的Node才会被过滤。

测试代码:

NodeFilter filterID = new HasAttributeFilter( "id" );

NodeFilter filterChild = new HasChildFilter(filterA);

NodeFilter filter = new AndFilter(filterID, filterChild);

输出结果:

getText:div id="logoindex"

=================================================

3.2 OrFilter

把前面的AndFilter换成OrFilter 测试代码:

NodeFilter filterID = new HasAttributeFilter( "id" );

NodeFilter filterChild = new HasChildFilter(filterA);

NodeFilter filter = new OrFilter(filterID, filterChild);

输出结果:

getText:div id="top_main"

=================================================

3.3 NotFilter

把前面的AndFilter换成NotFilter 测试代码:

NodeFilter filterID = new HasAttributeFilter( "id" );

NodeFilter filterChild = new HasChildFilter(filterA);

NodeFilter filter = new NotFilter(new OrFilter(filterID, filterChild));

输出结果:

getText:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd"

================================================= getText:

================================================= getText:head

================================================= getText:meta http-equiv="Content-Type" content="text/html; charset=gb2312" ================================================= getText:title

================================================= getText:白泽居https://www.doczj.com/doc/677875292.html,

================================================= getText:/title

================================================= getText:/head

================================================= getText:

================================================= getText:html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml"

================================================= getText:

================================================= getText:body

================================================= getText:

================================================= getText:

================================================= getText:

================================================= getText:这是注释

================================================= getText:白泽居https://www.doczj.com/doc/677875292.html,

================================================= getText:a href="https://www.doczj.com/doc/677875292.html,"

================================================= getText:白泽居https://www.doczj.com/doc/677875292.html,

================================================= getText:/a

================================================= getText:

================================================= getText:/div

================================================= getText:

白泽居https://www.doczj.com/doc/677875292.html,

================================================= getText:/div

================================================= getText:

================================================= getText:/body

================================================= getText:

================================================= getText:/html

================================================= getText:

=================================================

除了前面3.2中输出的几个Tag,其余的Tag都在这里了。

3.4 XorFilter

把前面的AndFilter换成NotFilter 测试代码:

NodeFilter filterID = new HasAttributeFilter( "id" );

NodeFilter filterChild = new HasChildFilter(filterA);

NodeFilter filter = new XorFilter(filterID, filterChild);

输出结果:

(四)其他Filter:

4.1 NodeClassFilter

这个Filter用于判断节点类型是否是某个特定的Node类型。在HTMLParser使用入门(2)- Node内容中我们已经了解了Node的不同类型,这个Filter就可以针对类型进行过滤。测试代码:

NodeFilter filter = new NodeClassFilter(RemarkNode.class); NodeList nodes = parser.extractAllNodesThatMatch(filter);

输出结果:

getText:这是注释

=================================================

可以看到只有RemarkNode(注释)被输出了。

4.2 StringFilter

这个Filter用于过滤显示字符串中包含制定内容的Tag。注意是可显示的字符串,不可显示的字符串中的内容(例如注释,链接等等)不会被显示。修改一下例子代码:

白泽居https://www.doczj.com/doc/677875292.html,

白泽居-字符串https://www.doczj.com/doc/677875292.html,

白泽居-链接文本https://www.doczj.com/doc/677875292.html,

白泽居-字符串https://www.doczj.com/doc/677875292.html,

测试代码:

NodeFilter filter = new StringFilter("https://www.doczj.com/doc/677875292.html,");

NodeList nodes = parser.extractAllNodesThatMatch(filter);

输出结果:

getText:白泽居https://www.doczj.com/doc/677875292.html,

================================================= getText:

白泽居-字符串https://www.doczj.com/doc/677875292.html,

================================================= getText:白泽居-链接文本https://www.doczj.com/doc/677875292.html,

================================================= getText:

白泽居-字符串https://www.doczj.com/doc/677875292.html,

可以看到包含title,两个内容字符串和链接的文本字符串的Tag都被输出了,但是注释和链接Tag本身没有输出。

4.3 LinkStringFilter

这个Filter用于判断链接中是否包含某个特定的字符串,可以用来过滤出指向某个特定网站的链接。

测试代码:

NodeFilter filter = new LinkStringFilter("https://www.doczj.com/doc/677875292.html,"); NodeList nodes = parser.extractAllNodesThatMatch(filter);

输出结果:

getText:a href="https://www.doczj.com/doc/677875292.html,"

=================================================

4.4 其他几个Filter

其他几个Filter也是根据字符串对不同的域进行判断,与前面这些的区别主要就是支持正则表达式。这个不在本文的讨论范围以内,大家可以自己实验一下。

HTMLParser遍历了网页的内容以后,以树(森林)结构保存了结果。HTMLParser访问结果内容的方法有两种。使用Filter和使用Visitor。

下面介绍使用Visitor访问内容的方法。

4.1 NodeVisitor

从简单方面的理解,Filter是根据某种条件过滤取出需要的Node再进行处理。Visitor则是遍历内容树的每一个节点,对于符合条件的节点进行处理。实际的结果异曲同工,两种不同的

方法可以达到相同的结果。

下面是一个最常见的NodeVisitro的例子。

测试代码:

public static void main(String[] args)

{

try

{

Parser parser = new Parser( (HttpURLConnection) (new URL

("http://127.0.0.1:8080/HTMLParserTester.html")).openConnection() );

NodeVisitor visitor = new NodeVisitor( false, false )

{

public void visitTag(Tag tag)

{

message("This is Tag:"+tag.getText());

}

public void visitStringNode (Text string)

{

message("This is Text:"+string);

}

public void visitRemarkNode (Remark remark)

{

message("This is Remark:"+remark.getText());

}

public void beginParsing ()

{

message("beginParsing");

}

public void visitEndTag (Tag tag)

{

message("visitEndTag:"+tag.getText());

}

public void finishedParsing ()

{

message("finishedParsing");

}

};

parser.visitAllNodesWith(visitor);

}

catch( Exception e )

{

e.printStackTrace();

}

}

输出结果:

beginParsing

This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd"

This is Text:Txt (121[0,121],123[1,0]): \n

This is Text:Txt (244[1,121],246[2,0]): \n

finishedParsing

可以看到,开始遍历所以的节点以前,beginParsing先被调用,然后处理的是中间的Node,最后在结束遍历以前,finishParsing被调用。因为我设置的 recurseChildren和recurseSelf 都是false,所以Visitor没有访问子节点也没有访问根节点的内容。中间输出的两个\n就是我们在HTMLParser使用详解(1)- 初始化Parser 中讨论过的最高层的那两个换行。

我们先把recurseSelf设置成true,看看会发生什么。

NodeVisitor visitor = new NodeVisitor( false, true) {

输出结果:

beginParsing

This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd"

This is Text:Txt (121[0,121],123[1,0]): \n

This is Tag:head

This is Text:Txt (244[1,121],246[2,0]): \n

This is Tag:html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml"

finishedParsing

可以看到,HTML页面的第一层节点都被调用了。

我们再用下面的方法调用看看:

NodeVisitor visitor = new NodeVisitor( true, false) {

输出结果:

beginParsing

This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd"

This is Text:Txt (121[0,121],123[1,0]): \n

This is Tag:meta http-equiv="Content-Type" content="text/html; charset=gb2312" This is Text:Txt (204[1,81],229[1,106]): 白泽居https://www.doczj.com/doc/677875292.html, visitEndTag:/title

visitEndTag:/head

This is Text:Txt (244[1,121],246[2,0]): \n

This is Text:Txt (289[2,43],291[3,0]): \n

This is Text:Txt (298[3,7],300[4,0]): \n

This is Text:Txt (319[4,19],322[5,1]): \n\t

This is Text:Txt (342[5,21],346[6,2]): \n\t\t

This is Remark:这是注释白泽居https://www.doczj.com/doc/677875292.html,

This is Text:Txt (378[6,34],408[8,0]): \n\t\t白泽居-字符串https://www.doczj.com/doc/677875292.html,\n

This is Text:Txt (441[8,33],465[8,57]): 白泽居-链接文本https://www.doczj.com/doc/677875292.html, visitEndTag:/a

This is Text:Txt (469[8,61],472[9,1]): \n\t

visitEndTag:/div

This is Text:Txt (478[9,7],507[11,0]): \n\t白泽居-字符串https://www.doczj.com/doc/677875292.html,\n visitEndTag:/div

This is Text:Txt (513[11,6],515[12,0]): \n

visitEndTag:/body

This is Text:Txt (522[12,7],524[13,0]): \n

visitEndTag:/html finishedParsing

可以看到,所有的子节点都出现了,除了刚刚例子里面的两个最上层节点

This is Tag:head和This is Tag:html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml"。

想让它们都出来,只需要

NodeVisitor visitor = new NodeVisitor( true, true) {

输出结果:

beginParsing

This is Tag:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.doczj.com/doc/677875292.html,/TR/xhtml1/DTD/xhtml1-transitional.dtd"

This is Text:Txt (121[0,121],123[1,0]): \n

This is Tag:head

This is Tag:meta http-equiv="Content-Type" content="text/html; charset=gb2312" This is Tag:title

This is Text:Txt (204[1,81],229[1,106]): 白泽居https://www.doczj.com/doc/677875292.html, visitEndTag:/title

visitEndTag:/head

This is Text:Txt (244[1,121],246[2,0]): \n

This is Tag:html xmlns="https://www.doczj.com/doc/677875292.html,/1999/xhtml"

This is Text:Txt (289[2,43],291[3,0]): \n

This is Tag:body

This is Text:Txt (298[3,7],300[4,0]): \n

This is Tag:div id="top_main"

This is Text:Txt (319[4,19],322[5,1]): \n\t

This is Tag:div id="logoindex"

This is Text:Txt (342[5,21],346[6,2]): \n\t\t

This is Remark:这是注释白泽居https://www.doczj.com/doc/677875292.html,

This is Text:Txt (378[6,34],408[8,0]): \n\t\t白泽居-字符串https://www.doczj.com/doc/677875292.html,\n This is Tag:a href="https://www.doczj.com/doc/677875292.html,"

This is Text:Txt (441[8,33],465[8,57]): 白泽居-链接文本https://www.doczj.com/doc/677875292.html, visitEndTag:/a

This is Text:Txt (469[8,61],472[9,1]): \n\t

visitEndTag:/div

This is Text:Txt (478[9,7],507[11,0]): \n\t白泽居-字符串https://www.doczj.com/doc/677875292.html,\n visitEndTag:/div

This is Text:Txt (513[11,6],515[12,0]): \n

visitEndTag:/body

This is Text:Txt (522[12,7],524[13,0]): \n

visitEndTag:/html finishedParsing

scifinder使用介绍

6.6.1 内容简介 SciFinder Scholar是美国化学学会所属的化学文摘服务社CAS(Chemical Abstract Service)出版的化学资料电子数据库学术版。它是全世界最大、最全面的化学和科学信息数据库。 《化学文摘》(CA)是涉及学科领域最广、收集文献类型最全、提供检索途径最多、部卷也最为庞大的一部著名的世界性检索工具。CA报道了世界上150多个国家、56种文字出版的20000多种科技期刊、科技报告、会议论文、学位论文、资料汇编、技术报告、新书及视听资料,摘录了世界范围约98%的化学化工文献,所报道的内容几乎涉及化学家感兴趣的所有领域。 CA网络版SciFinder Scholar,整合了Medline医学数据库、欧洲和美国等30几家专利机构的全文专利资料、以及化学文摘1907年至今的所有内容。涵盖的学科包括应用化学、化学工程、普通化学、物理、生物学、生命科学、医学、聚合体学、材料学、地质学、食品科学和农学等诸多领域。 SciFinder Scholar 收集由CAS 出版的数据库的内容以及MEDLINE?数据库,所有的记录都为英文(但如果MEDLINE 没有英文标题的则以出版的文字显示)。 6.6.2 通过 SciFinder Scholar 可以得到的信息:

6.6.3 SciFinder? Scholar? 使用的简单介绍 主要分为Explore 和Browse。如图6.6.1 一、Explore Explore Tool 可获取化学相关的所有信息及结构等,有如下: 1、Chemical Substance or Reaction – Retrieve the corresponding literature 2、By chemical structure 3、By substance identifier 4、By molecular formula

Jsoup解析HTML

jsoup 简介 Java 程序在解析 HTML 文档时,相信大家都接触过 htmlparser 这个开源项目,我曾经在 IBM DW 上发表过两篇关于 htmlparser 的文章,分别是:从 HTML 中攫取你所需的信息和扩展 HTMLParser 对自定义标签的处理能力。但现在我已经不再使用 htmlparser 了,原因是 htmlparser 很少更新,但最重要的是有了jsoup 。 jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。 jsoup 的主要功能如下: 1. 从一个 URL,文件或字符串中解析 HTML; 2. 使用 DOM 或 CSS 选择器来查找、取出数据; 3. 可操作 HTML 元素、属性、文本; jsoup 是基于 MIT 协议发布的,可放心使用于商业项目。 jsoup 的主要类层次结构如图 1 所示: 图 1. jsoup 的类层次结构 接下来我们专门针对几种常见的应用场景举例说明 jsoup 是如何优雅的进行HTML 文档处理的。 回页首

文档输入 jsoup 可以从包括字符串、URL 地址以及本地文件来加载 HTML 文档,并生成Document 对象实例。 下面是相关代码: 清单1 // 直接从字符串中输入 HTML 文档 String html = " 开源中国社区 " + " 这里是 jsoup 项目的相关文章 "; Document doc = Jsoup.parse(html); // 从 URL 直接加载 HTML 文档 Document doc = Jsoup.connect("https://www.doczj.com/doc/677875292.html,/").get(); String title = doc.title(); Document doc = Jsoup.connect("https://www.doczj.com/doc/677875292.html,/") .data("query", "Java") // 请求参数 .userAgent("I ’ m jsoup") // 设置 User-Agent .cookie("auth", "token") // 设置 cookie .timeout(3000) // 设置连接超时时间 .post(); // 使用 POST 方法访问 URL // 从文件中加载 HTML 文档 File input = new File("D:/test.html"); Document doc = Jsoup.parse(input,"UTF-8","https://www.doczj.com/doc/677875292.html,/"); 请大家注意最后一种 HTML 文档输入方式中的 parse 的第三个参数,为什么需要在这里指定一个网址呢(虽然可以不指定,如第一种方法)?因为 HTML 文档中会有很多例如链接、图片以及所引用的外部脚本、css 文件等,而第三个名为baseURL 的参数的意思就是当 HTML 文档使用相对路径方式引用外部文件时,jsoup 会自动为这些 URL 加上一个前缀,也就是这个 baseURL。 例如 开源软件 会被转换成 开源软件 。 回页首

Java集合类知识点总结

Java集合类 Java集合类 (1) 1.Map (3) 1.1.HashMap (3) 1.1.1.底层实现 (3) 1.1.2.特点 (3) 1.1.3.源码分析 (4) 1.1.4.多线程可能出现的问题 (5) 1.2.ConcurrentHashMap (6) 1.2.1.底层实现 (6) 1.2.2.源码分析 (7) 1.3.HashTable (9) 1.3.1.HashTable是线程安全的,因为所有方法上都加了synchronized关键 字。9 1.3.2.HashTable的key和value都不可以为null。 (9) 1.3.3.扩容时,capacity=2*capacity+1 (9) 1.3.4.数组默认大小为11 (9) 1.3.5.查找下标时,没有使用hash&length-1,而是直接进行计算的 (9) 1.4.TreeMap (9) 1.4.1.底层实现为红黑树 (9) 1.4. 2.TreeMap是一个有序的key-value集合,基于红黑树实现。该映射根据 其键的自然顺序进行排序,或者根据创建时提供的Comparator进行排序 (10) 1.4.3.接口实现 (10) 1.4.4.Entry (11) 1.5.LinkedHashMap (11) 1.5.1.底层是数组+链表+红黑树+双向链表 (11) 1.5.2.维护链表顺序和访问顺序 (11) 1.5.3.LinkedHashMap 可以通过构造参数 accessOrder 来指定双向链表是否在 元素被访问后改变其在双向链表中的位置。 (11) 1.5.4.当accessOrder为true时,get方法和put方法都会调用recordAccess 方法使得最近使用的Entry移到双向链表的末尾;当accessOrder为默认值 false时,recordAccess方法什么也不会做。 (11) 1.5.5.LRU实现 (11) 2.Collection (11) 2.1.List (12) 2.1.1.ArrayList (12) 2.1.2.LinkedList (13) 2.1.3.CopyOnWriteArrayList (13) 2.2.Set (14) 2.2.1.HashSet (14)

网页数据抓取分析

1、抓取网页数据通过指定的URL,获得页面信息,进而对页面用DOM进行 NODE分析, 处理得到原始HTML数据,这样做的优势在于,处理某段数据的灵活性高,难点在节算法 需要优化,在页面HTML信息大时,算法不好,会影响处理效率。 2、htmlparser框架,对html页面处理的数据结构,HtmlParser采用了经典的Composite 模式,通过RemarkNode、TextNode、TagNode、AbstractNode和Tag来描述HTML页面 各元素。Htmlparser基本上能够满足垂直搜索引擎页面处理分析的需求,映射HTML标签,可方便获取标签内的HTML CODE。 Htmlparser官方介绍: htmlparser是一个纯的java写的html解析的库,它不依赖于其它的java库文件,主要用于改造或提取html。它能超高速解析html,而且不会出错。现在htmlparser最新版本为2.0。毫不夸张地说,htmlparser就是目前最好的html解析和分析 的工具。 3、nekohtml框架,nekohtml在容错性、性能等方面的口碑上比htmlparser好(包括htmlunit也用的是nekohtml),nokehtml类似XML解析原理,把html标签确析为dom, 对它们对应于DOM树中相应的元素进行处理。 NekoHTML官方介绍:NekoHTML是一个Java语言的HTML扫描器和标签补全器(tag balancer) ,使得程序能解析HTML文档并用标准的XML接口来访问其中的信息。这个解析 器能够扫描HTML文件并“修正”许多作者(人或机器)在编写HTML文档过程中常犯的错误。 NekoHTML能增补缺失的父元素、自动用结束标签关闭相应的元素,以及不匹配的内嵌元 素标签。NekoHTML的开发使用了Xerces Native Interface (XNI),后者是Xerces2的实现基础。由https://www.doczj.com/doc/677875292.html,/整理

运筹学课程设计指导书

运筹学课程设计指导书 一、课程设计目的 1、初步掌握运筹学知识在管理问题中应用的基本方法与步骤; 2、巩固和加深对所学运筹学理论知识及方法的理解与掌握; 3、锻炼从管理实践中发掘、提炼问题,分析问题,选择建立运筹学模型,利用模型求解问题,并对问题的解进行分析与评价的综合应用能力; 4、通过利用运筹学计算机软件求解模型的操作,掌握运筹学计算软件的基本操作方法,并了解计算机在运筹学中的应用; 二、课程设计内容与步骤 第一部分是基本实验,为必做部分;需要每位同学单独完成,并写出相应的实验报告。第二部分是提高部分,题目自选或自拟,锻炼综合应用运筹学知识及软件解决实际问题的能力;可以单独完成,也可以合作完成(最多3人一组),写出相应的报告。 1、基本实验在完成基本实验后,每位同学要按照实验要求完成实验报告,实验报告应包括问题描述、建模、上机求解、结果分析及答辩几方面。实验报告必须是打印稿(word文档等),手写稿无效。请大家按照要求认真完成实验报告,如果两份实验报告雷同,或相差很少,则两份实验报告均为0分,其它抄袭情况,将根据抄袭多少扣分。(约占总分的70%) 2、提高部分根据自己的兴趣或所查找的资料,从实际情况出发,自拟题目;在实验报告中,陈述问题,建立模型,求解,结果分析,此部分应着重突出自己的观点和想法。(此部分按照排名先后给分,约占总分的30%) 三、课程设计要求 1、实验目的 学会建立相应的运筹学模型 学会Excel、Lindo和WinQSB,QM for windows软件的基本使用方法 学会用Excel、Lindo和WinQSB,QM for windows软件得到问题的最优解 2、实验要求 分析问题、建立模型,并阐明建立模型的过程; 说明并显示软件使用和计算的详细过程与结果; 结果分析,将结果返回到实际问题进行分析、评价。 四、题目内容 (一)Excel规划求解基本实验 1、雅致家具厂生产4种小型家具,由于该四种家具具有不同的大小、形状、重量和风格,所以它们所需要的主要原料(木材和玻璃)、制作时间、最大销售量与利润均不相同。该厂每天可提供的木材、玻璃和工人劳动时间分别为600单位、1000单位与400小时,详细的数据资料见下表。问: (1)应如何安排这四种家具的日产量,使得该厂的日利润最大? (2)家具厂是否愿意出10元的加班费,让某工人加班1小时? (3)如果可提供的工人劳动时间变为398小时,该厂的日利润有何变化? (4)该厂应优先考虑购买何种资源?

java集合类总结

1.本讲内容:集合collection (数组和集合90%功能相似,但是最大的区别是,数组在初始化的时候必须确定大小,而集合不用,而且集合是一堆的类,使用起来非常方便。) 讲集合collection之前,我们先分清三个概念: 1colection 集合,可用来存储任何对象的一种数据结构(容器)。 2Collection 集合接口,指的是,是Set、List 和Queue 接口的超类接口 3Collections 集合工具类,指的是类。 SCJP考试要求了解的接口有:Collection , Set , SortedSet , List , Map , SortedMap , Queue , NavigableSet , NavigableMap, 还有一个Iterator 接口也是必须了解的。 SCJP考试要求了解的类有:HashMap , Hashtable ,TreeMap , LinkedHashMap , HashSet , LinkedHashSet ,TreeSet , ArrayList , Vector , LinkedList , PriorityQueuee , Collections , Arrays 下面给出一个集合之间的关系图: 上图中加粗线的ArrayList 和HashMap 是我们重点讲解的对象。下面这张图看起来层级结构更清晰些。 我们这里说的集合指的是小写的collection,集合有4种基本形式,其中前三种的父接口是Collection。 4List 关注事物的索引列表 5Set 关注事物的唯一性 6Queue 关注事物被处理时的顺序 7Map 关注事物的映射和键值的唯一性 一、Collection 接口 Collection接口是Set 、List 和Queue 接口的父接口,提供了多数集合常用的方法声明,包括add()、remove()、contains() 、size() 、iterator() 等。 add(E e) 将指定对象添加到集合中 remove(Object o) 将指定的对象从集合中移除,移除成功返回true,不成功返回false contains(Object o) 查看该集合中是否包含指定的对象,包含返回true,不包含返回flase size() 返回集合中存放的对象的个数。返回值为int clear() 移除该集合中的所有对象,清空该集合。 iterator() 返回一个包含所有对象的iterator对象,用来循环遍历 toArray() 返回一个包含所有对象的数组,类型是Object toArray(T[] t) 返回一个包含所有对象的指定类型的数组 我们在这里只举一个把集合转成数组的例子,因为Collection本身是个接口所以,我们用它的实现类ArrayList做这个例子:例子1: package edu.xjfu;

SciFinder使用说明

SciFinder使用说明 SciFinder简介 SciFinder?由美国化学会(American Chemical Society, ACS)旗下的美国化学文摘社(Chemical Abstracts Service, CAS)出品,是一个研发应用平台,提供全球最大、最权威的化学及相关学科文献、物质和反应信息。SciFinder涵盖了化学及相关领域如化学、生物、医药、工程、农学、物理等多学科、跨学科的科技信息。SciFinder收录的文献类型包括期刊、专利、会议论文、学位论文、图书、技术报告、评论和网络资源等。 通过SciFinder,可以: ?访问由CAS全球科学家构建的全球最大并每日更新的化学物质、反应、专利和期刊数据库,帮助您做出更加明智的决策。 ?获取一系列检索和筛选选项,便于检索、筛选、分析和规划,迅速获得您研究所需的最佳结果,从而节省宝贵的研究时间。 无需担心遗漏关键研究信息,SciFinder收录所有已公开披露、高质量且来自可靠信息源的信息。 通过SciFinder可以获得、检索以下数据库信息:CAplus SM(文献数据库)、CAS REGISTRY SM (物质信息数据库)、CASREACT? (化学反应数据库)、MARPAT?(马库什结构专利信息数据库)、CHEMLIST? (管控化学品信息数据库)、CHEMCATS?(化学品商业信息数据库)、MEDLINE?(美国国家医学图书馆数据库)。 专利工作流程解决方案PatentPak TM已在SciFinder上线,帮助用户在专利全文中快速定位难以查找的化学信息。 SciFinder 注册须知: 读者在使用SciFinder之前必须用学校的email邮箱地址注册,注册后系统将自动发送一个链接到您所填写的email邮箱中,激活此链接即可完成注册。参考“SciFinder注册说明”。

Java中集合类用法总结

帮助 | 留言交? | 登录 首页我的图书馆主题阅读精彩目录精品文苑Tags 会员浏览好书推荐 以文找文 如何对文章标记,添加批注? Java 中集合?用法总结(转载) wade0564 收录于2010-07-08 阅读数:查看 收藏数:7 公众公开 原文来源 tags : java 集合类 欢迎浏览 wade0564 个人图书馆中收藏的文章,想收藏这篇好文章吗,赶快 吧,1分钟拥有自己的个人图书馆! 我也要收藏 举报 Java 中集合?用法总结 收藏 Collection ├List │├LinkedList │├ArrayList (异步,线程不安全,空间用完时自动增长原容量一半)│└Vector (同 步,线程安全,空间用完时自动增长原容量一倍)│ └Stack └Set ├HashSet └TreeSet Map ├Hashtable ├HashMap ├WeakHashMap └TreeMap Map 接口: | + -- WeakHashMap: 以弱键 实现的基于哈希表的 Map 。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条 | 目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为 可终止的,被终 | 止,然后被回收。丢弃某个键时, 其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。此实现 | 不是同步的。 | + -- TreeMap:该映射根据其键的自然顺序进行 排序,或?根据创建映射时提供的 Comparator 进行 排序,具体取决于使用的 | 构造方法。此实现不是同步的。 | + -- HashMap:基于哈希表的 Map 接?的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了 | 非同步和允许 使用 null 之外,HashMap 类与 Hashtable ?致相同。)此类不保证映射的顺序,特别是它不保证该顺 | 序恒久不变。此实现不是同步的。 | +-- SortedMap: 进一步提供关于键的总体排序 的 Map 。该映射是根据其键的自然顺序进 行排序的,或?根据通常在创建有 序映射时提供的 Comparator 进行排序。对有序映射的 collection 视图(由 entrySet 、keySet 和 values 方法返回 )进行迭代时,此顺序就会反映 出来。要采用此排序方式,还需要提供一些其他操作(此接?是 SortedSet 的对应映 射)。 Collection 接口: | 热点推荐 中国经典汤品——广东汤常用多音字汇总 如果你失恋。。。这些话...影响世界的100个管理定律汽车发动机?作过程和原理分析温家宝总理答中外记?问女人味,有多少男人可以读懂?珍稀的白头叶猴(组图)三鹿门事件之——中国,...国家公务员职务与级别当代古筝四美 付娜《渔...生活?秘方 真的很实用...哲理?品:守护梦想聚会时可以玩的?游戏依赖型人格障碍的表现和治疗经典妙语,十分精彩江边施救[贴图]李一男2003年在港湾...电脑速度慢的解决方法 ...重装系统后必须做的10件?事

MATLAB与在运筹学中的应用

MATLAB与在运筹学中的应用 摘要:论文通过MATLAB在运筹学中的应用实例,探讨了MATLAB在运筹学中的应用方法和技巧,初步了解matlab中优化工具箱的使用。 关键字:MATLAB应用运筹学优化计算 引言 运筹学是近代应用数学的一个分支,主要是研究如何将生产、管理等事件中出现的运筹问题加以提炼,然后利用数学方法进行解决的学科。运筹学是应用数学和形式科学的跨领域研究,利用像是统计学、数学模型和算法等方法,去寻找复杂问题中的最佳或近似最佳的解答。运筹学经常用于解决现实生活中的复杂问题,特别是改善或优化现有系统的效率。运筹学中常用的运算工具有Matlab、Mathematica、Maple、SAS 、SPSS、Lindo/Lingo、GAMS、WinQSB、Excel、其他,如SQP、DPS、ORS、Visual Decision、Decision Explore、AIMMS、Crystal等。 Matlab是矩阵实验室(Matrix Laboratory)的简称,是美国MathWorks公司出品的商业数学软件,和Mathematica、Maple并称为三大数学软件。 用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括Matlab和Simulink两大部分。 主要应用于工程计算、控制设计、信号处理与通讯、图像处理、信号检测、金融建模设计与分析等领域。 将matlab用于运筹学的最优化运算可以很好的解决优化问题,而且matlab 还专门有优化工具箱,是处理优化问题更加方便。 一、例:0-1规划(《运筹学》80页例3-9) 求minZ=x1-3*x2+6*x3+2*x4-4*x5 6*x1+2*x2-x3+7*x4+x5<=12 约束条件 x1+4*x2+5*x3-x4+3*x5>=10 Xj=0或1,j=1,2,3,4

Delphi 通过MSHTML实现一个HTML解析类

Delphi 通过MSHTML实现一个HTML解析类 Delphi 通过MSHTML实现一个HTML解析类分类:Delphi编程 2010-01-05 09:14 400人阅读 评论(7) 收藏 举报 最近经常会模拟网页提交返回网页源码,然后获得网页中相应的元素,于是需要常常解析Html中相应的各种元素,网络是个好东西,搜索一番,就找到了 好几个Delphi版本的HtmlParser的类库,试着使用了几个,发现解析起来都不完整,或多或少的回出现一些问题!于是想到了如果界面上有一个浏 览器,我们可以通过WebBrowser的Document接口对网页元素进行操作,很是方便!但是模拟网页提交,界面上是不一定要出现 WebBrowser的,肯定有办法,不通过WebBrowser就直接

解析HTML的,那便是我不要WebBrowser这个外壳,只要他里面的 Document文档接口对象就能实现对Html的解析了,查找了一番MSDN,然后Google一下,果然可行,构建方法如下://创建 IHTMLDocument2接口 CoCreateInstance(CLASS_HTMLDocument, nil, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, FHtmlDoc); 接口创建好了之后就能够对文 档元素进行解析了,很是爽快! 结合了我自己的特有操作,我对Combobox,Table,Frame等一些网页元素做了相应的封装,实现 了一个HTMLParser,大致代码如下: 这里只给出声明,代 码请在最后下载 代码

(* **************************************************** *)(* 得闲工作 室 *)(* 网页元素操作 类库 *)(* *)(* DxHtmlElement Unit *)(* Copyright(c) 2008-2010 不得 闲 *)(* email:appleak46@https://www.doczj.com/doc/677875292.html, QQ:75492895 *)(* **************************************************** *)unit DxHtmlElement;interfaceuses

基于内容相似度的网页正文提取

—102 — 基于内容相似度的网页正文提取 王 利1,刘宗田1,王燕华2,廖 涛1 (1. 上海大学计算机科学与工程学院,上海 200072;2. 上海海洋大学信息学院,上海 201306) 摘 要:提出一种将复杂的网页脚本进行简化并映射成一棵易于操作的树型结构的方法。该方法不依赖于DOM 树,无须用HTMLparser 包进行解析,而是利用文本相似度计算方法,通过计算树节点中文本内容与各级标题的相似度判定小块文本信息的有用性,由此进行网页清洗与正文抽取,获得网页文本信息,实验结果表明,该方法对正文抽取具有较高的通用性与准确率。 关键词:网页正文抽取;网页映射;网页清洗;文本相似度 Web Page Main Text Extraction Based on Content Similarity WANG Li 1, LIU Zong-tian 1, WANG Yan-hua 2, LIAO Tao 1 (1. School of Computer Science and Engineering, Shanghai University, Shanghai 200072; 2. School of Information Technology, Shanghai Fisheries University, Shanghai 201306) 【Abstract 】This paper proposes a method of simplifying complex Web page script and mapping it into tree structure easy to operate. It does not depend on DOM tree, and does not need utilize htmlparser bag to parse. By calculating text similarity, it calculates the similarity between the content of tree node and headings of different levels to determine the usefulness of the text information, cleans the Web page and extracts the content information. Experimental results show that the method has better universal property and accuracy rate in main text extraction. 【Key words 】Web page main text extraction; Web page mapping; Web page cleaning; text similarity 计 算 机 工 程 Computer Engineering 第36卷 第6期 Vol.36 No.6 2010年3月 March 2010 ·软件技术与数据库· 文章编号:1000—3428(2010)06—0102—03 文献标识码:A 中图分类号:TP393 1 概述 随着Internet 的飞速发展,网络上的信息呈爆炸式增长。 网页己经成为Internet 上最重要的信息资源。各种网页为人们提供了大量可供借鉴或参考的信息,成为人们日常工作和生活必不可少的一部分。然而,网页上的信息经常包含大量的噪声,如广告链接、导航条、版权信息等非网页主题信息的内容,页面所要表达的主要信息经常被隐藏在无关的内容和结构中,限制了Web 信息的可利用性。本文主要对网页上的这些噪声进行滤除,并抽取网页正文信息,即网页清洗。它是Web 文本分类、聚类、文本摘要等文本信息处理的基础,网页正文抽取的效果直接影响到文本信息处理的效果。 本文的方法首先抽取出HTML 页面中的title 及各级标题,再对网页进行标准化预处理,然后建立一种新的树型结构,HTML 中的所有正文信息都包含在这棵树的节点中。利用这种树型结构可以方便地清洗网页中的噪声、抽取出网页中的正文信息。在抽取网页正文信息时,较大的文本块根据文本的长度极易抽取出,而对于只有小文本块的节点,由于页面中的title 及各级标题高度概括了该网页的主要内容,因此可以根据各节点内容与title 、各级标题的相似度来判定该节点的信息文本是否为有用文本,只要该小块文本与title 或某个子标题的相似度大于设定阈值,就判定其为有用信息。 2 相关工作 虽然网页正文提取是Web 文本挖掘中的一个重要问题, 但相关研究并不多。目前对网页进行噪声过滤与信息自动抽取的方法主要有两大类:(1)针对单一页面进行处理。根据所处理页面的内容特征、可视信息等应用一些启发性规则去除页面的噪音,抽取出页面内容。这类方法对每一个待处理的网页进行同样的处理,对于抽取通过模板产生的网页集效率较低。(2)针对同一站点中页面的一般模式进行处理。这种方法是基于一个或多个网站中的页面集进行模板检测的,但局限于由同一个模板生成的网页集,直接影响清洗的自适应性。 文献[1]的研究仅限于某些特定站点,在这些站点中根据合并不同页面生成的DOM 树来标记页面中哪些是有用信息哪些是噪声,并通过这些标记达到页面清洗的目的。文献[2]根据HTML 标签生成树,通过分析同一网站下网页之间模板的相似性来识别数据区域。文献[3]基于DOM 规范,提出了基于语义信息的STU-DOM 树模型,将HTML 文档转换为STU-DOM 树,并对其进行基于结构的过滤和基于语义的剪枝,完成了对网页主题信息的抽取。文献[4]采用基于标记窗的方法并利用Levenshtein Distance 公式计算标记窗中字符串与标题词之间的距离,从而判断该字符串是否为正文信息,该方法容易导致很多噪声无法滤除。 通过分析可知,现有的网页清洗方法大多基于DOM 树并用HTMLparser 程序包[5]对其进行解析,这种方法效率不高,而且依赖于第三方包。对此本文提出了一种简单的树型结构,在这棵树中保存了正文信息,同时消除了一些无用信息,并对各节点进行了简化,带来了操作上极大的便利。另外,在这棵树中可以通过深度搜索子节点来消除传统方法中不能处理网页正文部分被存放在多个td 中的情况以及不能处 基金项目:国家自然科学基金资助项目(60575035, 60975033);上海市重点学科建设基金资助项目(J50103);上海大学研究生创新基金资助项目(SHUCX092162) 作者简介:王 利(1984-),男,硕士研究生,主研方向:文本挖掘,事件本体;刘宗田,教授、博士生导师;王燕华,硕士研究生;廖 涛,博士研究生 收稿日期:2009-08-10 E-mail :wonglee07@https://www.doczj.com/doc/677875292.html,

HTMLParser使用详解

声明:本人来自转载 https://www.doczj.com/doc/677875292.html,/ HTMLParser具有小巧,快速的优点,缺点是相关文档比较少(英文的也少),很多功能需要自己摸索。对于初学者还是要费一些功夫的,而一旦上手以后,会发现HTMLParser的结构设计很巧妙,非常实用,基本你的各种需求都可以满足。 这里我根据自己这几个月来的经验,写了一点入门的东西,希望能对新学习HTMLParser的朋友们有所帮助。(不过当年高考本人语文只比及格高一分,所以文法方面的问题还希望大家多多担待) HTMLParser的核心模块是org.htmlparser.Parser类,这个类实际完成了对于HTML页面的分析工作。这个类有下面几个构造函数: public Parser (); public Parser (Lexer lexer, ParserFeedback fb); public Parser (URLConnection connection, ParserFeedback fb) throws ParserException; public Parser (String resource, ParserFeedback feedback) throws ParserException; public Parser (String resource) throws ParserException; public Parser (Lexer lexer); public Parser (URLConnection connection) throws ParserException; 和一个静态类public static Parser createParser (String html, String charset); 对于大多数使用者来说,使用最多的是通过一个URLConnection或者一个保存有网页内容的字符串来初始化Parser,或者使用静态函数来生成一个Parser对象。ParserFeedback的代码很简单,是针对调试和跟踪分析过程的,一般不需要改变。而使用Lexer则是一个相对比较高级的话题,放到以后再讨论吧。 这里比较有趣的一点是,如果需要设置页面的编码方式的话,不使用Lexer就只有静态函数一个方法了。对于大多数中文页面来说,好像这是应该用得比较多的一个方法。 下面是初始化Parser的例子。 package com.baizeju.htmlparsertester; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.FileInputStream; import java.io.File; import https://www.doczj.com/doc/677875292.html,.HttpURLConnection; import https://www.doczj.com/doc/677875292.html,.URL; import org.htmlparser.visitors.TextExtractingVisitor; import org.htmlparser.Parser; /** * @author https://www.doczj.com/doc/677875292.html, */ public class Main { private static String ENCODE = "GBK"; private static void message( String szMsg ) { try{System.out.println(new String(szMsg.getBytes(ENCODE), System.getProperty("file.encoding"))); }

python抓取网页数据的常见方法

https://www.doczj.com/doc/677875292.html, python抓取网页数据的常见方法 很多时候爬虫去抓取数据,其实更多是模拟的人操作,只不过面向网页,我们看到的是html在CSS样式辅助下呈现的样子,但爬虫面对的是带着各类标签的html。下面介绍python抓取网页数据的常见方法。 一、Urllib抓取网页数据 Urllib是python内置的HTTP请求库 包括以下模块:urllib.request 请求模块、urllib.error 异常处理模块、urllib.parse url解析模块、urllib.robotparser robots.txt解析模块urlopen 关于urllib.request.urlopen参数的介绍: urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None) url参数的使用 先写一个简单的例子:

https://www.doczj.com/doc/677875292.html, import urllib.request response = urllib.request.urlopen(' print(response.read().decode('utf-8')) urlopen一般常用的有三个参数,它的参数如下: urllib.requeset.urlopen(url,data,timeout) response.read()可以获取到网页的内容,如果没有read(),将返回如下内容 data参数的使用 上述的例子是通过请求百度的get请求获得百度,下面使用urllib的post请求 这里通过https://www.doczj.com/doc/677875292.html,/post网站演示(该网站可以作为练习使用urllib的一个站点使用,可以 模拟各种请求操作)。 import urllib.parse import urllib.request data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')

浙江大学scifinder使用教程

浙江大学scifinder使用教程 1、输入网址:https://www.doczj.com/doc/677875292.html,/ 如图1,点击继续浏览 图1 2、进入浙大的入口,输入用户名密码(卖家提供) 图2 3、登陆进去是图3这个页面。注意此时会自动安装插件,切记要一路放行。登陆成功的标志是屏幕右上角有个蓝框绿蓝S的LOGO! 如果未出现S,那么请根据图2的手动安装组件,下载安装组件!

图3 4、登陆页面不要覆盖,新标签页打开浙江大学图书馆 https://www.doczj.com/doc/677875292.html,/libweb/点数据库导航,找到scifinder页面,进入 图4

5、点击图5红框中的链接https://www.doczj.com/doc/677875292.html,/cgi-bin/casip,看下IP是不是浙大的IP,一般是61或者210开头,确定是,那就可以输入链接https://https://www.doczj.com/doc/677875292.html,/登陆了 图5 6、scifinder登陆页面输入用户名密码(卖家提供),您就可以使用scifinder啦 图6

常见问题以及解决方法 1.浏览器不支持JavaScript,提示“您的浏览器不支持JavaScript(或它被 禁止了)请确认您的浏览器能支持JavaScript”,请启用“工具- >Internet选项->安全->自定义级别->活动脚本”选项。 2.浏览器不支持Cookie,提示“你的浏览器禁止了Cookie,必须设置为允许 才可以继续使用”,请在“工具->Internet选项->隐私->高级”启用 Cookie支持 3.浏览不支持BHO,提示:"您的浏览器没有启用第三方扩展",关闭IE时无法 自动注销用户。请在 "工具->Internet选项->高级->启用第三方浏览器扩展”前打勾启用! 4.APP服务不可用,可能是控件不是最新的,请您关闭IE,重新登陆VPN 5.IP服务不可用,可能你安装的IP服务控件不是最新的。请点击“程序- >SINFOR SSL VPN->卸载CS应用支持”和“程序->SINFOR SSL VPN->卸载SSL VNIC”,手动卸载IP服务控件,然后再重新登陆VPN。 6.IP服务可能与某些杀毒软件冲突。请在杀毒软件中放行IP服务的客户端程 序,或者在使用时暂时禁用杀毒软件。

htmlparser

htmlparser 源程序代码 我们的C# 程序中经常会产生一些数据,这些数据可以使用Html 表格进行展现。现在让我们开始写相关的C# 程序吧。下面就是HtmlMaker.cs: 01: using System; 02: using System.IO; 03: using https://www.doczj.com/doc/677875292.html,; 04: using System.Data; 05: using System.Drawing; 06: using System.Collections.Generic; 07: 08: namespace Skyiv 09: { 10: public sealed class HtmlMaker 11: { 12: public bool TitleVisible { get; set; } 13: 14: string title; 15: DataView view; 16: IEnumerable<Tuple<string, string>>

info; 17: 18: public HtmlMaker(string title, IEnumerable<Tuple<string, string>> info, DataView view) 19: { 20: this.title = title; 21: https://www.doczj.com/doc/677875292.html, = info; 22: this.view = view; 23: this.TitleVisible = true; 24: } 25: 26: public void Save(string htmlFileName) 27: { 28: using (var writer = new StreamWriter(htmlFileName)) 29: { 30: WriteHead(writer); 31: WriteTitle(writer); 32: WriteInfo(writer); 33: new HtmlTable(view).Write(writer); 34: WriteTail(writer);

java集合-练习题解析

1. 填空 Collection 接口的特点是元素是___无序可重复______; List 接口的特点是元素__有__(有|无)顺序,_可以___(可以|不可以)重复; Set 接口的特点是元素__无___(有|无)顺序,____不可以__(可以|不可以)重复;Map 接口的特点是元素是__key、value映射______,其中__value__可以重复,_key___不可以重复。 2. (List)有如下代码 import java.util.*; public class TestList{ public static void main(String args[]){ List list = new ArrayList(); list.add(“Hello”); list.add(“World”); list.add(1, “Learn”); list.add(1, “Java”); printList(list); } public static void printList(List list){ //1 for(int i = 0; i< list.size();i++){ System.out.println(list.get(i)); } for(Object o : list) { System.out.println(o); } Iterator itor = list.iterator(); while(itor.hasNext()){ System.out.println(itor.next()); } } } 要求: 1) 把//1 处的代码补充完整,要求输出list 中所有元素的内容 2) 写出程序执行的结果Hello Java Learn World 3) 如果要把实现类由ArrayList 换为LinkedList,应该改哪里?ArrayList 和LinkedList 使用上有什么区别?实现上有什么区别? 4) 如果要把实现类由ArrayList 换为Vector,应该改哪里?ArrayList 和Vector 使 用上有什么区别?实现上有什么区别? 3. (List)写出下面程序的运行结果

相关主题
文本预览
相关文档 最新文档