java htmlparser解析读取html使用方法案例

java | 2019-09-13 10:02:39

1.子链接的提取:

做页面子链接提取的基本思路是:

1.用被提取的网页的url实例化一个Parser

2.实例化Filter,设置页面过滤条件——只获取<a>标签与<frame>标签的内容

3.用Parser提取页面中所有通过Filter的结点,得到NodeList

4.遍历NodeList,调用Node的相应方法得到其中的链接,加入子链接的集合

5.返回子链接集合

代码:

package Crawler;
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;
public class HtmlLinkParser {
    //获取子链接,url为网页url,filter是链接过滤器,返回该页面子链接的HashSet
    public static Set<String> extracLinks(String url, LinkFilter filter) {
        Set<String> links = new HashSet<String>();
        try {
            Parser parser = new Parser(url);
            parser.setEncoding("utf-8");
            // 过滤 <frame >标签的 filter,用来提取 frame 标签里的 src 属性所表示的链接
            NodeFilter frameFilter = new NodeFilter() {
                public boolean accept(Node node) {
                    if (node.getText().startsWith("frame src=")) {
                        return true;
                    } else {
                        return false;
                    }
                }
            };
            // OrFilter 接受<a>标签或<frame>标签,注意NodeClassFilter()可用来过滤一类标签,linkTag对应<标签>
            OrFilter linkFilter = new OrFilter(new NodeClassFilter(
                    LinkTag.class), frameFilter);
            // 得到所有经过过滤的标签,结果为NodeList
            NodeList list = parser.extractAllNodesThatMatch(linkFilter);
            for (int i = 0; i < list.size(); i++) {
                Node tag = list.elementAt(i);
                if (tag instanceof LinkTag)// <a> 标签
                {
                    LinkTag link = (LinkTag) tag;
                    String linkUrl = link.getLink();// 调用getLink()方法得到<a>标签中的链接
                    if (filter.accept(linkUrl))//将符合filter过滤条件的链接加入链接表
                        links.add(linkUrl);
                } else{// <frame> 标签
                    // 提取 frame 里 src 属性的链接如 <frame src="test.html"/>
                    String frame = tag.getText();
                    int start = frame.indexOf("src=");
                    frame = frame.substring(start);
                    int end = frame.indexOf(" ");
                    if (end == -1)
                        end = frame.indexOf(">");
                    String frameUrl = frame.substring(5, end - 1);
                    if (filter.accept(frameUrl))
                        links.add(frameUrl);
                }
            }
        } catch (ParserException e) {//捕捉parser的异常
            e.printStackTrace();
        }
        return links;
    }
}

2.解析网页内容:

基本思路:

1.读取html文件,获得页面编码,获得String格式的文件内容

2.用页面编码实例化html文件的Parser

3.对需要提取的结点设置相应的Filter

4.根据给定的Filter,用Parser解析html文件

5.提取结点中的文本内容,进行处理(本例中是关键字匹配,计算主题相关度)

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.tags.HeadingTag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.MetaTag;
import org.htmlparser.tags.ParagraphTag;
import org.htmlparser.tags.TitleTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import java.util.Set;
import multi.patt.match.ac.*;
public class HtmlFileParser {
    String filepath=new String();//html文件路径
    private static String[] keyWords;//关键词列表
    /*static{
        keyWords=read("filePath");//从指定文件中读取关键词列表
    }*/
    public HtmlFileParser(String filepath){
        this.filepath=filepath;
    }
    public String getTitle(){//得到页面标题
        FileAndEnc fae=readHtmlFile();
        int i=0;
        try{
            //实例化一个本地html文件的Parser
            Parser titleParser = Parser.createParser(fae.getFile(),fae.getEnc());
            NodeClassFilter titleFilter =new NodeClassFilter(TitleTag.class);
            NodeList titleList = titleParser.extractAllNodesThatMatch(titleFilter);
            //实际上一个网页应该只有一个<title>标签,但extractAllNodesThatMatch方法返回的只能是一个NodeList
            for (i = 0; i < titleList.size(); i++) {
                TitleTag title_tag = (TitleTag) titleList.elementAt(i);
                return title_tag.getTitle();
            }
        }catch(ParserException e) {
            return null;
        }
        return null;
    }
    public String getEncoding(){//获得页面编码
        FileAndEnc fae=readHtmlFile();
        return fae.getEnc();
    }
    public float getRelatGrade(){//计算网页的主题相关度
        FileAndEnc fae=readHtmlFile();
        String file=fae.getFile();
        String enC=fae.getEnc();
        String curString;
        int curWordWei = 1;//当前关键词权重
        float curTagWei = 0;//当前标签权重
        float totalGra = 0;//总相关度分
        int i;
        AcApply obj = new AcApply();//实例化ac自动机
        Pattern p = null;
        Matcher m = null;
        try{//根据不同标签依次进行相关度计算
            //title tag    <title>
            curTagWei=5;
            Parser titleParser = Parser.createParser(file,enC);
            NodeClassFilter titleFilter =new NodeClassFilter(TitleTag.class);
            NodeList titleList = titleParser.extractAllNodesThatMatch(titleFilter);
            for (i = 0; i < titleList.size(); i++) {
                TitleTag titleTag=(TitleTag)titleList.elementAt(i);
                curString=titleTag.getTitle();
                Set result = obj.findWordsInArray(keyWords, curString);//ac自动机的方法返回匹配的词的表
                totalGra=totalGra+result.size()*curTagWei;//计算相关度
            }
            //meta tag of description and keyword <meta>
            curTagWei=4;
            Parser metaParser = Parser.createParser(file,enC);
            NodeClassFilter metaFilter =new NodeClassFilter(MetaTag.class);
            NodeList metaList = metaParser.extractAllNodesThatMatch(metaFilter);
            p = Pattern.compile("\\b(description|keywords)\\b",Pattern.CASE_INSENSITIVE);
            for (i = 0; i < metaList.size(); i++) {
                MetaTag metaTag=(MetaTag)metaList.elementAt(i);
                curString=metaTag.getMetaTagName();
                if(curString==null){
                    continue;
                }
                m = p.matcher(curString); //正则匹配name是description或keyword的<meta>标签
                if(m.find()){
                    curString=metaTag.getMetaContent();//提取其content
                    Set result = obj.findWordsInArray(keyWords, curString);
                    totalGra=totalGra+result.size()*curTagWei;
                }
                else{
                    curString=metaTag.getMetaContent();
                    Set result = obj.findWordsInArray(keyWords, curString);
                    totalGra=totalGra+result.size()*2;
                }
            }
            //heading tag <h*>
            curTagWei=3;
            Parser headingParser = Parser.createParser(file,enC);
            NodeClassFilter headingFilter =new NodeClassFilter(HeadingTag.class);
            NodeList headingList = headingParser.extractAllNodesThatMatch(headingFilter);
            for (i = 0; i < headingList.size(); i++) {
                HeadingTag headingTag=(HeadingTag)headingList.elementAt(i);
                curString=headingTag.toPlainTextString();//得到<h*>标签中的纯文本
                if(curString==null){
                    continue;
                }
                Set result = obj.findWordsInArray(keyWords, curString);
                totalGra=totalGra+result.size()*curTagWei;
            }
            //paragraph tag <p>
            curTagWei=(float)2.5;
            Parser paraParser = Parser.createParser(file,enC);
            NodeClassFilter paraFilter =new NodeClassFilter(ParagraphTag.class);
            NodeList paraList = paraParser.extractAllNodesThatMatch(paraFilter);
            for (i = 0; i < paraList.size(); i++) {
                ParagraphTag paraTag=(ParagraphTag)paraList.elementAt(i);
                curString=paraTag.toPlainTextString();
                if(curString==null){
                    continue;
                }
                Set result = obj.findWordsInArray(keyWords, curString);
                totalGra=totalGra+result.size()*curTagWei;
            }
            //link tag <a>
            curTagWei=(float)0.25;
            Parser linkParser = Parser.createParser(file,enC);
            NodeClassFilter linkFilter =new NodeClassFilter(LinkTag.class);
            NodeList linkList = linkParser.extractAllNodesThatMatch(linkFilter);
            for (i = 0; i < linkList.size(); i++) {
                LinkTag linkTag=(LinkTag)linkList.elementAt(i);
                curString=linkTag.toPlainTextString();
                if(curString==null){
                    continue;
                }
                Set result = obj.findWordsInArray(keyWords, curString);
                totalGra=totalGra+result.size()*curTagWei;
            }        
        }catch(ParserException e) {
            return 0;
        }
        return totalGra;
    }
    private FileAndEnc readHtmlFile(){//读取html文件,返回字符串格式的文件与其编码
        StringBuffer abstr = new StringBuffer();
        FileAndEnc fae=new FileAndEnc();
        try{
            //实例化默认编码方式的BufferefReader
            BufferedReader enCReader= new BufferedReader(new InputStreamReader(new FileInputStream(filepath),"UTF-8"));
            String temp=null;
            while((temp=enCReader.readLine())!=null){//得到字符串格式的文件
                abstr.append(temp);
                abstr.append("\r\n");
            }
            String result=abstr.toString();
            fae.setFile(result);
            String encoding=getEnc(result);
            fae.setEnc(encoding);//得到页面编码
            //根据得到的编码方式实例化BufferedReader
            BufferedReader reader= new BufferedReader(new InputStreamReader(new FileInputStream(filepath),encoding));
            StringBuffer abstrT = new StringBuffer();
            while((temp=reader.readLine())!=null){
                abstrT.append(temp);
                abstrT.append("\r\n");
            }
            result=abstrT.toString();
            fae.setFile(result);//得到真正的页面内容
        } catch (FileNotFoundException e) {
            System.out.println("file not found");
            fae=null;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            fae=null;
        } finally {
            return fae;
        }
    }
    private String getEnc(String file){//根据正则匹配得到页面编码
        String enC="utf-8";
        Pattern p = Pattern.compile("(charset|Charset|CHARSET)\\s*=\\s*\"?\\s*([-\\w]*?)[^-\\w]"); 
        Matcher m = p.matcher(file);
        if(m.find()){ 
            enC=m.group(2);
        }
        return enC;
    }
}


3.使用Filter从网页中查找获取需要的内容

常用的几个过滤器说明

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

HasChildFilter: 
是返回有符合条件的子节点的节点,需要另外一个Filter作为过滤子节点的参数。

HasAttributeFilter:
可以匹配出包含制定名字的属性,或者制定属性为指定值的节点。HasParentFilter和HasSiblingFilter的功能与HasChildFilter类似。

StringFilter:    
这个Filter用于过滤显示字符串中包含指定内容的标签节点。注意是可显示的字符串,不可显示的字符串中的内容(例如注释,链接等等)不会被显示

RegexFilter :   
根据正则表达式匹配节点.与LinkRegexFilter不同的是,LinkRegexFilter只在LinkTag中寻找匹配

NodeClassFilter: 
根据已定义的标签类获取节点

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

OrFilter:  
是结合几种过滤条件的'或'过滤器

AndFilter:     
是结合几种过滤条件的'与'过滤器



代码:

/**
     * 
     * 过滤页面中的标签信息
     * 
     * @param url        要解析的url页面
     * @param encoding    使用的字符编码
     * @param tagclass    
     *                     要或取得页面标签,如要获取页面中的超链接 值为LinkTag.class,要获取页面中图片链接,值为ImageTag.class
     *                     要传入的标签类为org.htmlparser.tags下的
     */
    public static void nodeFilterTagClass(String url,String encoding,Class tagclass){
        try {
            Parser parser = new Parser();
            parser.setURL(url);
            if(null==encoding){
                parser.setEncoding(parser.getEncoding());
            }else{
                parser.setEncoding(encoding);
            }
            //过滤页面中的链接标签
            NodeFilter filter = new NodeClassFilter(tagclass);
            NodeList list = parser.extractAllNodesThatMatch(filter);
            for(int i=0; i<list.size();i++){
                Node node = (Node)list.elementAt(i);
                System.out.println("link is :" + node.toHtml());
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        
        String url = "http://wenku.baidu.com/search?word=htmlparser&lm=0&od=0&fr=top_home";
        
        //获取页面中的<a href='xxx' [属性]>格式的链接
        nodeFilterTagClass(url, "UTF-8", LinkTag.class);
    
        //或取页面中的<img src='xxx' [属性='属性值']>格式的链接
        nodeFilterTagClass(url, "UTF-8", ImageTag.class);
        
        //或取页面<title>xxxx</title>标题
        nodeFilterTagClass(url, "UTF-8", TitleTag.class);
        
        //获取页面<div [属性='属性值']> xxx</div>
        //nodeFilterTagClass(url, "UTF-8", Div.class);
}





登录后即可回复 登录 | 注册
    
关注编程学问公众号