最近一直在学习搜索引擎的相关知识,在对于原始的HTML网页的处理是其中非常重要的一个环节,也就是所说的“去噪”,比如去掉相关的标签和不需要的JS代码等等,HTMLParser(http://htmlparser.sourceforge.net/)是一个对现有的HTML进行分析的快速实时的解析工具。它是一个开源的项目,通过它可以准确高效地对HTML文本中的格式、数据进行处理。利用它可以很容易地对网页的内容进行分析、过滤和抓取。它的主要功能分为以下几个部分:
文本信息抽取:提取网页中的文字。
链接提取:提取网页中的链接信息和锚文本。
资源提取:网页中图片、声音的处理。
链接检查:用于检查HTML中的链接是否有效。
内容检查:可以用来过滤网页上一些令人不愉快的字词。
HTMLParser最核心的模块是Parser类,这个类实际完成了对于HTML页面的分析工作,构造函数如下:
public Parser (); API链接地址:http://htmlparser.sourceforge.net/javadoc/index.html
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;
我们通常使用的是通过一个URLConnection或者一个保存有网页内容的字符串来初始化Parser,或者使用静态函数来生成一个Parser对象。
下面我们给出两个简单的初始化的例子。
1.下面是通过传递保存有网页内容的字符串来初始化Parser和通过Parser静态函数来生成Parser对象
import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.plaf.metal.MetalFileChooserUI; 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.nodes.TextNode; import org.htmlparser.tags.JspTag; import org.htmlparser.tags.LinkTag; import org.htmlparser.tags.MetaTag; import org.htmlparser.tags.TableTag; import org.htmlparser.tags.TitleTag; import org.htmlparser.util.NodeList; import org.htmlparser.util.ParserException; public class t { /** * @param args * @throws IOException */ public final static String testFilePath="C:"+File.separator+"glose - 博客园.htm"; public final static String urlName="http://www.cnblogs.com/dlutxm/"; public static String readFile(String fileName) throws IOException{ //读本地文件内容 FileInputStream fin=new FileInputStream(fileName); InputStreamReader inReader=new InputStreamReader(fin,"utf-8"); BufferedReader bReader=new BufferedReader(inReader); StringBuffer content=new StringBuffer(); String line=null; while((line=bReader.readLine())!=null){ content.append(line); content.append("\n"); } bReader.close(); inReader.close(); fin.close(); //System.out.println(content); return content.toString(); } public static void parser(String content) throws ParserException{ Parser parser=Parser.createParser(content, "utf-8"); //Parser parser=new Parser(content); NodeList nodeList=null; // 注册特定标签的类 或者说某个特定的节点 NodeFilter titleFilter=new NodeClassFilter(TitleTag.class); NodeFilter metaFilter=new NodeClassFilter(MetaTag.class); NodeFilter textFilter=new NodeClassFilter(TextNode.class); NodeFilter tableFilter=new NodeClassFilter(TableTag.class); NodeFilter linkFilter=new NodeClassFilter(LinkTag.class); NodeFilter jspFilter=new NodeClassFilter(JspTag.class); //OrFilter类可以得到其参数中设置的任何节点类型,节点之间是或的关系 具体实现方法为setPredicates() OrFilter lastFilter=new OrFilter(); lastFilter.setPredicates(new NodeFilter[]{titleFilter,metaFilter,textFilter,tableFilter,linkFilter,jspFilter}); nodeList=parser.parse(lastFilter); Node [] nodes=nodeList.toNodeArray(); String line=""; for(int i=0;i<nodes.length;i++){ Node node=nodes[i]; if(node instanceof TitleTag){ //得到网页的标题 TitleTag titlenode=(TitleTag)node; line=titlenode.getTitle(); //System.out.println(line); } else if(node instanceof MetaTag) { //得到meta中的content内容,包括网页的关键字、编码、描述信息等。 MetaTag metaTag=(MetaTag)node; line=metaTag.getAttribute("content"); //System.out.println(line); } else if(node instanceof TextNode){ //得到文本内容 TextNode textNode=(TextNode)node; line=textNode.getText(); //System.out.println(line); } else if(node instanceof TableTag){ TableTag tableTag=(TableTag)node; line=tableTag.toPlainTextString(); //得到表格的内容 //System.out.println(line); String width=tableTag.getAttribute("width"); String height=tableTag.getAttribute("height"); //System.out.println(width); } else if(node instanceof LinkTag){ //得到网页中的链接和链接文本 LinkTag linknode=(LinkTag)node; String linkText=linknode.getLinkText(); String link=linknode.getLink(); System.out.println(linkText); System.out.println(link); } else if(node instanceof JspTag){ //解析网页中的Javas,ASP等动态的代码 JspTag jspTag=(JspTag)node; line=jspTag.toString(); System.out.println(line); } } } public static void main(String[] args) throws IOException, ParserException { // TODO Auto-generated method stub String content=readFile(testFilePath); parser(content); } }
2.下面是通过一个URLConnection来初始化Parser
import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; 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.TitleTag; import org.htmlparser.util.NodeList; import org.htmlparser.util.ParserException; public class urlTest { /** * @param args * @throws IOException * @throws MalformedURLException * @throws ParserException */ public static void parser(String url) throws MalformedURLException, IOException, ParserException{ HttpURLConnection urlConnection=(HttpURLConnection) (new URL(url)).openConnection(); Parser parser=new Parser(urlConnection); NodeFilter titleFilter=new NodeClassFilter(TitleTag.class); NodeList nodeList=null; OrFilter lasFilter=new OrFilter(); lasFilter.setPredicates(new NodeFilter[]{titleFilter}); nodeList=parser.parse(lasFilter); Node []nodes=nodeList.toNodeArray(); for(int i=0;i<nodes.length;i++){ if(nodes[i] instanceof TitleTag){ TitleTag titleTag=(TitleTag)nodes[i]; String title=titleTag.getTitle(); System.out.println(title); } } } public static void main(String[] args) throws MalformedURLException, ParserException, IOException { // TODO Auto-generated method stub String url="http://www.baidu.com"; parser(url); } }
3.下面是对相关的Parser对象构造函数进行了很好的封装和测试。常用的构造Parser对象的方法有以下几种:
import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; 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.http.ConnectionManager; import org.htmlparser.lexer.Page; import org.htmlparser.tags.TitleTag; import org.htmlparser.util.NodeList; import org.htmlparser.util.ParserException; public class IteratorNode { /** * @param args */ public static Parser getParserWithUrlStr(String urlStr,String encoding) throws ParserException{ Parser parser=new Parser(); parser.setURL(urlStr); parser.setEncoding(encoding); return parser; } public static Parser getParserWithUrlConn(String urlStr,String encoding) throws IOException, ParserException{ URL url=new URL(urlStr); HttpURLConnection urlConnection=(HttpURLConnection) url.openConnection(); Parser parser=new Parser(urlConnection); parser.setEncoding(encoding); return parser; } public static Parser getParserWithUrlConn2(String urlStr,String encoding) throws ParserException{ ConnectionManager manager=Page.getConnectionManager(); Parser parser=new Parser(manager.openConnection(urlStr)); parser.setEncoding(encoding); return parser; } public static Parser createParser(String htmlContent,String encoding){ //读取本地文件 Parser parser=Parser.createParser(htmlContent, encoding); return parser; } public static void main(String[] args) throws ParserException, IOException { // TODO Auto-generated method stub Parser parser1=getParserWithUrlStr("http://www.baidu.com", "utf-8"); Parser parser2=getParserWithUrlConn("http://www.baidu.com", "utf-8"); Parser parser=getParserWithUrlConn2("http://www.baidu.com", "utf-8"); NodeFilter titleFilter=new NodeClassFilter(TitleTag.class); NodeList nodeList=null; OrFilter lasFilter=new OrFilter(); lasFilter.setPredicates(new NodeFilter[]{titleFilter}); nodeList=parser.parse(lasFilter); Node []nodes=nodeList.toNodeArray(); for(int i=0;i<nodes.length;i++){ if(nodes[i] instanceof TitleTag){ TitleTag titleTag=(TitleTag)nodes[i]; String title=titleTag.getTitle(); System.out.println(title); } } } }