`
hujin1979
  • 浏览: 78785 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

打造一个全能的解析器好像是比较困难的事情

阅读更多

  我们尝试用org.cyberneko.html.parsers.DOMParser来全面细致的分析互联网上的网站,但事实上由于各种技术流派的盛行导致了千变万化的网站技术,也导致了我们想细致分析每个页面成了一种理想状态的事情。
  但是,我们在能里和了解范围内还是希望把工作做得更周到,页面解析的类我写在一个叫ParseDocument.java的文件中,目前它能做到事情就是把取得的HTML代码进行分析,获取我们希望获得的数据并保存在对象中以供使用。我们还是先看看代码。 

import java.io.StringReader; 
import java.lang.reflect.Constructor; 
import java.util.ArrayList; 
import java.util.HashMap; 

import org.cyberneko.html.parsers.DOMParser; 
import org.w3c.dom.NamedNodeMap; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 
import org.xml.sax.InputSource; 

import com.ue.browser.Browser; 
import com.ue.browser.core.ElementCode; 
import com.ue.browser.core.HTMLElement; 
import com.ue.browser.Frame; 
import com.ue.browser.Iframe; 

public class ParseDocument { 
private ArrayList<HTMLElement> elements = new ArrayList<HTMLElement>(); 
private Browser browser; 
private HTMLElement element; 
private String text; 
private InputSource source; 
private static DOMParser parser = new DOMParser(); 

public boolean haveIframe = false; 
public boolean haveFrame = false; 

public ParseDocument(Browser browser) { 
super(); 
this.browser = browser; 
} 

public ArrayList<HTMLElement> getElements() { 
return elements; 
} 

public void setElements(ArrayList<HTMLElement> elements) { 
this.elements = elements; 
} 

public Browser getBrowser() { 
return browser; 
} 

public void setBrowser(Browser browser) { 
this.browser = browser; 
} 

public HTMLElement getElement() { 
return element; 
} 

public void setElement(HTMLElement element) { 
this.element = element; 
} 


   
private static HashMap<String, String> elementMap = ElementCode.getElements(); 
private static String thePack = "com.ue.browser.html."; 

public void parse(String body){ 
try{ 
source = new InputSource(new StringReader(body)); 
//是否允许命名空间 
parser.setFeature("http://xml.org/sax/features/namespaces", false); 
//是否允许增补缺失的标签。如果要以XML方式操作HTML文件,此值必须为真 
parser.setFeature("http://cyberneko.org/html/features/balance-tags", true); 
//是否剥掉<script>元素中的<!-- -->等注释符 
parser.setFeature("http://cyberneko.org/html/features/scanner/script/strip-comment-delims", true); 
parser.setFeature("http://cyberneko.org/html/features/augmentations", true); 
parser.setProperty("http://cyberneko.org/html/properties/names/elems", "lower"); 

//解析HTML片段时是否作标签增补,此功能不要用在DOMParser上,而要用在DOMFragmentParser上 
//parser.setFeature("http://cyberneko.org/features/document-fragment",true); 
//添加管道过滤器 
/*XMLDocumentFilter noop = new DefaultFilter(); 
XMLDocumentFilter[] filters = { noop }; 
parser.setProperty("http://cyberneko.org/html/properties/filters", filters);*/ 

parser.parse(source); 

//cyberneko解析:将httpclien读取的数据source解析成w3c的Document对象 
this.buildElements(parser.getDocument()); 
}catch(Exception e){ 
e.printStackTrace(); 
} 
} 

    //从w3c的Document节点对象中获取节点的属性放入对应的类中 
public void buildElements(Node node){ 
int type = node.getNodeType(); 
switch (type) { 
// print the document element 
case Node.DOCUMENT_NODE: { 
this.buildElements(((org.w3c.dom.Document) node).getDocumentElement()); 
break; 
} 

// print element with attributes 
case Node.ELEMENT_NODE: { 
String name = node.getNodeName(); 
String clazz = elementMap.get(name); 
try{ 
if(clazz!=null){ 
Class<?> tt = Class.forName(thePack+clazz); 
            Constructor<?> c = tt.getConstructor(Browser.class); 
            element = (HTMLElement)c.newInstance(this.getBrowser()); 
            NamedNodeMap attrs = node.getAttributes(); 
for (int i = 0; i < attrs.getLength(); i++) { 
Node attr = attrs.item(i); 
element.setAttribute(attr.getNodeName(), attr.getNodeValue()); 
} 
                elements.add(element); 
} 
}catch(Exception e){ 
e.printStackTrace(); 
} 

//查询子节点表,并构建子节点属性 
NodeList children = node.getChildNodes(); 
if (children != null) { 
int len = children.getLength(); 
for (int i = 0; i < len; i++) 
this.buildElements(children.item(i)); 
} 
break; 
} 

// handle entity reference nodes 
case Node.ENTITY_REFERENCE_NODE: { 
break; 
} 

// print cdata sections 
case Node.CDATA_SECTION_NODE: { 
break; 
} 

// print text 
case Node.TEXT_NODE: { 
text = node.getNodeValue(); 
break; 
} 

/*//print script 注释节点<!--   -->   
case Node.COMMENT_NODE: { 
script = node.getNodeValue(); 
System.out.println(script); 
break; 
}*/ 

// print processing instruction 
case Node.PROCESSING_INSTRUCTION_NODE: { 
break; 
} 
} 

    if (type == Node.ELEMENT_NODE) { 
   if(node.getNodeName().equals("TEXTAREA")){ 
element.setAttribute("value", text); 
} 

if (type == Node.ELEMENT_NODE) { 
if(node.getNodeName().equals("IFRAME")){ 
//如果有IFRAME节点,进行IFRAME处理 
haveIframe = true; 
} 
} 

if (type == Node.ELEMENT_NODE) { 
if(node.getNodeName().equals("FRAME")){ 
                  //如果有FRAME节点,进行FRAME处理 
haveFrame = true; 
} 
} 

    if(node.getNodeName().equals("SCRIPT")){ 
if(text!=null){ 
element.setAttribute("daima", text); 
} 
} 
} 
} 

//获得当前节点的父节点名称 
public String getParentNodeName(Node node){ 
Node parent = node.getParentNode(); 
String name = parent.getNodeName(); 
return name; 
} 

public boolean isHaveFrame() { 
return haveFrame; 
} 

public void setHaveFrame(boolean haveFrame) { 
this.haveFrame = haveFrame; 
} 

public boolean isHaveIframe() { 
return haveIframe; 
} 

public void setHaveIframe(boolean haveIframe) { 
this.haveIframe = haveIframe; 
  } 
}  

 
  重要的部分我都有中文注释,其实我觉得我还只能用中文注释会比较准确,英文对我来说,可能还不能把我想表达的意思正确告诉中国程序员。
  Class<?> tt = Class.forName(thePack+clazz);
  Constructor<?> c = tt.getConstructor(Browser.class);
  element = (HTMLElement)c.newInstance(this.getBrowser());
  可能这里对刚开始用java写程序的人来说要费劲理解一下,大家可以好好了解java的型别控制机制,然后对照实际的代码进行思考,这种设计模式其实在java应用中到处都在使用。

 

分享到:
评论
1 楼 记忆无泪 2009-12-26  
com.ue.browser.Browser;

这个是你自己写的还是网上有jar包了 我找不到 我是一个Java初学者 烦指教

相关推荐

Global site tag (gtag.js) - Google Analytics