• 【搜索引擎Jediael开发笔记3】使用HtmlParser提取网页中的链接



    关于HtmpParser的基本内容请见 HtmlParser基础教程


    本文示例用于提取HTML文件中的链接

    package org.ljh.search.html;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.htmlparser.Node;
    import org.htmlparser.NodeFilter;
    import org.htmlparser.Parser;
    import org.htmlparser.filters.NodeClassFilter;
    import org.htmlparser.filters.OrFilter;
    import org.htmlparser.tags.LinkTag;
    import org.htmlparser.util.NodeList;
    import org.htmlparser.util.ParserException;
    
    //本类创建用于HTML文件解释工具
    public class HtmlParserTool {
    
    	// 本方法用于提取某个html文档中内嵌的链接
    	public static Set<String> extractLinks(String url, LinkFilter filter) {
    		Set<String> links = new HashSet<String>();
    		try {
    			// 1、构造一个Parser,并设置相关的属性
    			Parser parser = new Parser(url);
    			parser.setEncoding("gb2312");
    
    			// 2.1、自定义一个Filter,用于过滤<Frame >标签,然后取得标签中的src属性值
    			NodeFilter frameNodeFilter = new NodeFilter() {
    				@Override
    				public boolean accept(Node node) {
    					if (node.getText().startsWith("frame src=")) {
    						return true;
    					} else {
    						return false;
    					}
    				}
    			};
    			
    			//2.2、创建第二个Filter,过滤<a>标签
    			NodeFilter aNodeFilter = new NodeClassFilter(LinkTag.class);
    			
    			//2.3、净土上述2个Filter形成一个组合逻辑Filter。
    			OrFilter linkFilter = new OrFilter(frameNodeFilter, aNodeFilter);
    			
    			//3、使用parser根据filter来取得所有符合条件的节点
    			NodeList nodeList = parser.extractAllNodesThatMatch(linkFilter);
    			
    			//4、对取得的Node进行处理
    			for(int i = 0; i<nodeList.size();i++){
    				Node node = nodeList.elementAt(i);
    				String linkURL = "";
    				//如果链接类型为<a />
    				if(node instanceof LinkTag){
    					LinkTag link = (LinkTag)node;
    					linkURL= link.getLink();
    				}else{
    					//如果类型为<frame />
    					String nodeText = node.getText();
    					int beginPosition = nodeText.indexOf("src=");
    					nodeText = nodeText.substring(beginPosition);
    					int endPosition = nodeText.indexOf(" ");
    					if(endPosition == -1){
    						endPosition = nodeText.indexOf(">");
    					}
    					linkURL = nodeText.substring(5, endPosition - 1);
    				}
    				//判断是否属于本次搜索范围的url
    				if(filter.accept(linkURL)){
    					links.add(linkURL);
    				}
    			}
    			
    		} catch (ParserException e) {
    			e.printStackTrace();
    		}
    		return links;
    	}
    }
    


    程序中的一些说明:

    (1)通过Node#getText()取得节点的String。

    (2)node instanceof TagLink,即<a/>节点,其它还有很多的类似节点,如tableTag等,基本上每个常见的html标签均会对应一个tag。官方文档说明如下:

    org.htmlparser.nodes The nodes package has the concrete node implementations.
    org.htmlparser.tags The tags package contains specific tags.
    因此可以通过此方法直接判断一个节点是否某个标签内容。


    其中用到的LinkFilter接口定义如下:

    package org.ljh.search.html;
    
    //本接口所定义的过滤器,用于判断url是否属于本次搜索范围。
    public interface LinkFilter {
    	public boolean accept(String url);
    }


    测试程序如下:

    package org.ljh.search.html;
    
    import java.util.Iterator;
    import java.util.Set;
    
    import org.junit.Test;
    
    public class HtmlParserToolTest {
    
    	@Test
    	public void testExtractLinks() {
    		String url = "http://www.baidu.com";
    		LinkFilter linkFilter = new LinkFilter(){
    			@Override
    			public boolean accept(String url) {
    				if(url.contains("baidu")){
    					return true;
    				}else{
    					return false;
    				}
    			}
    			
    		};
    		Set<String> urlSet = HtmlParserTool.extractLinks(url, linkFilter);
    		
    		Iterator<String> it = urlSet.iterator();
    		while(it.hasNext()){
    			System.out.println(it.next());
    		}
    	}
    
    }
    


    输出结果如下:

    http://www.hao123.com
    http://www.baidu.com/
    http://www.baidu.com/duty/
    http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&word=
    http://music.baidu.com
    http://ir.baidu.com
    http://www.baidu.com/gaoji/preferences.html
    http://news.baidu.com
    http://map.baidu.com
    http://music.baidu.com/search?fr=ps&key=
    http://image.baidu.com
    http://zhidao.baidu.com
    http://image.baidu.com/i?tn=baiduimage&ct=201326592&lm=-1&cl=2&nc=1&word=
    http://www.baidu.com/more/
    http://shouji.baidu.com/baidusearch/mobisearch.html?ref=pcjg&from=1000139w
    http://wenku.baidu.com
    http://news.baidu.com/ns?cl=2&rn=20&tn=news&word=
    https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F
    http://www.baidu.com/cache/sethelp/index.html
    http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&word=&fr=wwwt
    http://tieba.baidu.com/f?kw=&fr=wwwt
    http://home.baidu.com
    https://passport.baidu.com/v2/?reg&regType=1&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F
    http://v.baidu.com
    http://e.baidu.com/?refer=888
    ;
    http://tieba.baidu.com
    http://baike.baidu.com
    http://wenku.baidu.com/search?word=&lm=0&od=0
    http://top.baidu.com
    http://map.baidu.com/m?word=&fr=ps01000




  • 相关阅读:
    最长上升子序列
    盒子与小球之三
    盒子与小球之二
    《深入理解计算机网络》读后小记 2
    《深入理解计算机网络》读后小记 1
    想成为Java高手的25个学习目标
    POI中设置Excel单元格格式
    如何用jar命令对java工程进行打包
    【网络流】有源汇上下界最大流
    【网络流】网络流基本概念
  • 原文地址:https://www.cnblogs.com/eaglegeek/p/4557935.html
Copyright © 2020-2023  润新知