• 【转载】HtmlParser的使用 和 HttpClient 实现简易爬虫


     1 package parser;
     2 
     3 import java.io.BufferedReader;
     4 
     5 import java.io.BufferedWriter;
     6 
     7 import java.io.FileWriter;
     8 
     9 import java.io.IOException;
    10 
    11 import java.io.InputStream;
    12 
    13 import java.io.InputStreamReader;
    14 
    15 import java.net.MalformedURLException;
    16 
    17 import java.net.URL;
    18 
    19 /**
    20 
    21  * 基本能实现网页抓取,不过要手动输入URL 将整个html内容保存到指定文件
    22 
    23  * 
    24 
    25  * @author chenguoyong
    26 
    27  * 
    28 
    29  */
    30 
    31 public class ScrubSelectedWeb {
    32 
    33 private final static String CRLF = System.getProperty("line.separator");
    34 
    35 /**
    36 
    37  * @param args
    38 
    39  */
    40 
    41 public static void main(String[] args) {
    42 
    43 try {
    44 
    45 URL ur = new URL("http://10.249.187.199:8083/injs100/");
    46 
    47 InputStream instr = ur.openStream();
    48 
    49 String s, str;
    50 
    51 BufferedReader in = new BufferedReader(new InputStreamReader(instr));
    52 
    53 StringBuffer sb = new StringBuffer();
    54 
    55 BufferedWriter out = new BufferedWriter(new FileWriter(
    56 
    57 "D:/outPut.txt"));
    58 
    59 while ((s = in.readLine()) != null) {
    60 
    61 sb.append(s + CRLF);
    62 
    63 }
    64 
    65 System.out.println(sb);
    66 
    67 str = new String(sb);
    68 
    69 out.write(str);
    70 
    71 out.close();
    72 
    73 in.close();
    74 
    75 } catch (MalformedURLException e) {
    76 
    77 e.printStackTrace();
    78 
    79 } catch (IOException e) {
    80 
    81 e.printStackTrace();
    82 
    83 }
    84 
    85 }
    86 
    87 }

    基本能实现网页抓取,不过要手动输入URL,此外没有重构。只是一个简单的思路。

    1.htmlparser 使用

    htmlparser是一个纯的java写的html解析的库,htmlparser不依赖于其它的java库,htmlparser主要用于改造 或提取html。htmlparser能超高速解析html,而且不会出错。毫不夸张地说,htmlparser就是目前最好的html解 析和分析的工具。无论你是想抓取网页数据还是改造html的内容,用了htmlparser绝对会忍不住称赞。由于htmlparser 结构设计精良,所以扩展htmlparser 非常便利。

    Htmlparser中文论坛.  http://bbs.hexiao.cn/thread.php?fid=6

    Constructor Summary

    Parser() 

    Parser(URLConnection connection) 
              Construct a parser using the provided URLConnection.

    Method:

    static Parser createParser(String html, String charset) 
              Creates the parser on an input string.

     void visitAllNodesWith(NodeVisitor visitor) 
              Apply the given visitor to the current page.

    HtmlPage(Parser parser)

     NodeList

    getBody() 
               

     TableTag[]

    getTables() 
               

     String

    getTitle() 
               

     void

    setTitle(String title) 
               

     void

    visitTag(Tag tag) 
              Called for each Tag visited.

    Constructor Summary

    NodeList() 
               

    NodeList(Node node) 
              Create a one element node list.

      NodeList extractAllNodesThatMatch(NodeFilter filter) 
              Filter the list with the given filter non-recursively.  

    NodeList extractAllNodesThatMatch(NodeFilter filter, boolean recursive) 
              Filter the list with the given filter.

     Node elementAt(int i)

    1. html代码里面所有的链接地址和链接名称

      1 package parser;
      2 
      3 import org.htmlparser.Parser;
      4 
      5 import org.htmlparser.Node;
      6 
      7 import org.htmlparser.NodeFilter;
      8 
      9 import org.htmlparser.Parser;
     10 
     11 import org.htmlparser.filters.TagNameFilter;
     12 
     13 import org.htmlparser.tags.LinkTag;
     14 
     15 import org.htmlparser.tags.TableTag;
     16 
     17 import org.htmlparser.util.NodeList;
     18 
     19 import org.htmlparser.util.ParserException;
     20 
     21 import org.htmlparser.visitors.HtmlPage;
     22 
     23 /**
     24 
     25  * htmlparser取得一段html代码里面所有的链接地址和链接名称
     26 
     27  * 
     28 
     29  * @author chenguoyong
     30 
     31  * 
     32 
     33  */
     34 
     35 public class Testhtmlparser {
     36 
     37 /**
     38 
     39  * @param args
     40 
     41  */
     42 
     43 public static void main(String[] args) {
     44 
     45 String htmlcode = "<HTML><HEAD><TITLE>AAA</TITLE></HEAD><BODY>"
     46 
     47 + "<a href='http://topic.csdn.net/u/20080522/14/0ff402ef-c382-499a-8213-ba6b2f550425.html'>连接1</a>"
     48 
     49 + "<a href='http://topic.csdn.net'>连接2</a></BODY></HTML>";
     50 
     51 // 创建Parser对象根据传给字符串和指定的编码
     52 
     53 Parser parser = Parser.createParser(htmlcode, "GBK");
     54 
     55 // 创建HtmlPage对象HtmlPage(Parser parser)
     56 
     57 HtmlPage page = new HtmlPage(parser);
     58 
     59 try {
     60 
     61 // HtmlPage extends visitor,Apply the given visitor to the current
     62 
     63 // page.
     64 
     65 parser.visitAllNodesWith(page);
     66 
     67 } catch (ParserException e1) {
     68 
     69 e1 = null;
     70 
     71 }
     72 
     73 // 所有的节点
     74 
     75 NodeList nodelist = page.getBody();
     76 
     77 // 建立一个节点filter用于过滤节点
     78 
     79 NodeFilter filter = new TagNameFilter("A");
     80 
     81 // 得到所有过滤后,想要的节点
     82 
     83 nodelist = nodelist.extractAllNodesThatMatch(filter, true);
     84 
     85 for (int i = 0; i < nodelist.size(); i++) {
     86 
     87 LinkTag link = (LinkTag) nodelist.elementAt(i);
     88 
     89 // 链接地址
     90 
     91 System.out.println(link.getAttribute("href") + "\n");
     92 
     93 // 链接名称
     94 
     95 System.out.println(link.getStringText());
     96 
     97 }
     98 
     99 }
    100 
    101 }

    结果如下:

    http://topic.csdn.net/u/20080522/14/0ff402ef-c382-499a-8213-ba6b2f550425.html

    连接1

    http://topic.csdn.net

    连接2

    2. 使用HtmlParser抓去网页内容

      1 package parser;
      2 
      3 import org.htmlparser.Parser;
      4 
      5 import org.htmlparser.beans.StringBean;
      6 
      7 import org.htmlparser.filters.NodeClassFilter;
      8 
      9 import org.htmlparser.parserapplications.StringExtractor;
     10 
     11 import org.htmlparser.tags.BodyTag;
     12 
     13 import org.htmlparser.util.NodeList;
     14 
     15 import org.htmlparser.util.ParserException;
     16 
     17 /**
     18 
     19  * 使用HtmlParser抓去网页内容: 要抓去页面的内容最方便的方法就是使用StringBean. 里面有几个控制页面内容的几个参数.
     20 
     21  * 在后面的代码中会有说明. Htmlparser包中还有一个示例StringExtractor 里面有个直接得到内容的方法,
     22 
     23  * 其中也是使用了StringBean . 另外直接解析Parser的每个标签也可以的.
     24 
     25  * 
     26 
     27  * @author chenguoyong
     28 
     29  * 
     30 
     31  */
     32 
     33 public class GetContent {
     34 
     35 public void getContentUsingStringBean(String url) {
     36 
     37 StringBean sb = new StringBean();
     38 
     39 sb.setLinks(true); // 是否显示web页面的连接(Links)
     40 
     41 // 为了取得页面的整洁美观一般设置上面两项为true , 如果要保持页面的原有格式, 如代码页面的空格缩进 可以设置为false
     42 
     43 sb.setCollapse(true); // 如果是true的话把一系列空白字符用一个字符替代.
     44 
     45 sb.setReplaceNonBreakingSpaces(true);// If true regular space
     46 
     47 sb
     48 
     49 .setURL("http://www.blogjava.net/51AOP/archive/2006/07/19/59064.html");
     50 
     51 System.out.println("The Content is :\n" + sb.getStrings());
     52 
     53 }
     54 
     55 public void getContentUsingStringExtractor(String url, boolean link) {
     56 
     57 // StringExtractor内部机制和上面的一样.做了一下包装
     58 
     59 StringExtractor se = new StringExtractor(url);
     60 
     61 String text = null;
     62 
     63 try {
     64 
     65 text = se.extractStrings(link);
     66 
     67 System.out.println("The content is :\n" + text);
     68 
     69 } catch (ParserException e) {
     70 
     71 e.printStackTrace();
     72 
     73 }
     74 
     75 }
     76 
     77 public void getContentUsingParser(String url) {
     78 
     79 NodeList nl;
     80 
     81 try {
     82 
     83 Parser p = new Parser(url);
     84 
     85 nl = p.parse(new NodeClassFilter(BodyTag.class));
     86 
     87 BodyTag bt = (BodyTag) nl.elementAt(0);
     88 
     89 System.out.println(bt.toPlainTextString()); // 保留原来的内容格式. 包含js代码
     90 
     91 } catch (ParserException e) {
     92 
     93 e.printStackTrace();
     94 
     95 }
     96 
     97 }
     98 
     99 /**
    100 
    101  * @param args
    102 
    103  */
    104 
    105 public static void main(String[] args) {
    106 
    107 String url = "http://www.blogjava.net/51AOP/archive/2006/07/19/59064.html";
    108 
    109 //new GetContent().getContentUsingParser(url);
    110 
    111 //--------------------------------------------------
    112 
    113 new GetContent().getContentUsingStringBean(url);
    114 
    115 }
    116 
    117 }
    118 
    119 3.将整个html内容保存到指定文件
    120 
    121 package parser;
    122 
    123 import java.io.BufferedReader;
    124 
    125 import java.io.BufferedWriter;
    126 
    127 import java.io.FileWriter;
    128 
    129 import java.io.IOException;
    130 
    131 import java.io.InputStream;
    132 
    133 import java.io.InputStreamReader;
    134 
    135 import java.net.MalformedURLException;
    136 
    137 import java.net.URL;
    138 
    139 /**
    140 
    141  * 基本能实现网页抓取,不过要手动输入URL 将整个html内容保存到指定文件
    142 
    143  * 
    144 
    145  * @author chenguoyong
    146 
    147  * 
    148 
    149  */
    150 
    151 public class ScrubSelectedWeb {
    152 
    153 private final static String CRLF = System.getProperty("line.separator");
    154 
    155 /**
    156 
    157  * @param args
    158 
    159  */
    160 
    161 public static void main(String[] args) {
    162 
    163 try {
    164 
    165 URL ur = new URL("http://www.google.cn/");
    166 
    167 InputStream instr = ur.openStream();
    168 
    169 String s, str;
    170 
    171 BufferedReader in = new BufferedReader(new InputStreamReader(instr));
    172 
    173 StringBuffer sb = new StringBuffer();
    174 
    175 BufferedWriter out = new BufferedWriter(new FileWriter(
    176 
    177 "D:/outPut.txt"));
    178 
    179 while ((s = in.readLine()) != null) {
    180 
    181 sb.append(s + CRLF);
    182 
    183 }
    184 
    185 System.out.println(sb);
    186 
    187 str = new String(sb);
    188 
    189 out.write(str);
    190 
    191 out.close();
    192 
    193 in.close();
    194 
    195 } catch (MalformedURLException e) {
    196 
    197 e.printStackTrace();
    198 
    199 } catch (IOException e) {
    200 
    201 e.printStackTrace();
    202 
    203 }
    204 
    205 }
    206 
    207 }

    4利用htmlparser提取网页纯文本的例子

      1 package parser;
      2 
      3 import org.htmlparser.Node;
      4 
      5 import org.htmlparser.NodeFilter;
      6 
      7 import org.htmlparser.Parser;
      8 
      9 import org.htmlparser.filters.TagNameFilter;
     10 
     11 import org.htmlparser.tags.TableTag;
     12 
     13 import org.htmlparser.util.NodeList;
     14 
     15 /**
     16 
     17  * 标题:利用htmlparser提取网页纯文本的例子
     18 
     19  */
     20 
     21 public class TestHTMLParser2 {
     22 
     23 /**
     24 
     25  * 读取目标html内容
     26 
     27  *
     28 
     29  */
     30 
     31 public static void testHtml() {
     32 
     33 try {
     34 
     35 String sCurrentLine;
     36 
     37 String sTotalString;
     38 
     39 sCurrentLine = "";
     40 
     41 sTotalString = "";
     42 
     43 java.io.InputStream l_urlStream;
     44 
     45 java.net.URL l_url = new java.net.URL(
     46 
     47 "http://10.249.187.199:8083/injs100/");
     48 
     49 java.net.HttpURLConnection l_connection = (java.net.HttpURLConnection) l_url
     50 
     51 .openConnection();
     52 
     53 l_connection.connect();
     54 
     55 l_urlStream = l_connection.getInputStream();
     56 
     57 java.io.BufferedReader l_reader = new java.io.BufferedReader(
     58 
     59 new java.io.InputStreamReader(l_urlStream));
     60 
     61 while ((sCurrentLine = l_reader.readLine()) != null) {
     62 
     63 sTotalString += sCurrentLine + "\r\n";
     64 
     65 }
     66 
     67 String testText = extractText(sTotalString);
     68 
     69 } catch (Exception e) {
     70 
     71 e.printStackTrace();
     72 
     73 }
     74 
     75 }
     76 
     77     /**
     78 
     79      * 抽取纯文本信息
     80 
     81      * @param inputHtml:html文本
     82 
     83      * @return
     84 
     85      * @throws Exception
     86 
     87      */
     88 
     89 public static String extractText(String inputHtml) throws Exception {
     90 
     91 StringBuffer text = new StringBuffer();
     92 
     93 Parser parser = Parser.createParser(new String(inputHtml.getBytes(),
     94 
     95 "GBK"), "GBK");
     96 
     97 // 遍历所有的节点
     98 
     99 NodeList nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
    100 
    101 public boolean accept(Node node) {
    102 
    103 return true;
    104 
    105 }
    106 
    107 });
    108 
    109 System.out.println(nodes.size());
    110 
    111 for (int i = 0; i < nodes.size(); i++) {
    112 
    113 Node nodet = nodes.elementAt(i);
    114 
    115 //字符串的代表性节点:节点的描述
    116 
    117 text.append(new String(nodet.toPlainTextString().getBytes("GBK"))
    118 
    119 + "\r\n");
    120 
    121 }
    122 
    123 return text.toString();
    124 
    125 }
    126 
    127     /**
    128 
    129      *  读取文件的方式/utl 来分析内容. filePath也可以是一个Url.
    130 
    131      * @param resource :文件/Url
    132 
    133      * @throws Exception
    134 
    135      */
    136 
    137 public static void test5(String resource) throws Exception {
    138 
    139 Parser myParser = new Parser(resource);
    140 
    141 myParser.setEncoding("GBK");
    142 
    143 String filterStr = "table";
    144 
    145 NodeFilter filter = new TagNameFilter(filterStr);
    146 
    147 NodeList nodeList = myParser.extractAllNodesThatMatch(filter);
    148 
    149 /*for(int i=0;i<nodeList.size();i++)
    150 
    151 {
    152 
    153 TableTag tabletag = (TableTag) nodeList.elementAt(i);
    154 
    155 //标签名称
    156 
    157 System.out.println(tabletag.getTagName());
    158 
    159 System.out.println(tabletag.getText());
    160 
    161 }*/
    162 
    163 TableTag tabletag = (TableTag) nodeList.elementAt(1);
    164 
    165 }
    166 
    167 public static void main(String[] args) throws Exception {
    168 
    169 test5("http://10.249.187.199:8083/injs100/");
    170 
    171 //testHtml();
    172 
    173 }
    174 
    175 }

    5.html解析table

      1 package parser;
      2 
      3 import org.apache.log4j.Logger;
      4 
      5 import org.htmlparser.NodeFilter;
      6 
      7 import org.htmlparser.Parser;
      8 
      9 import org.htmlparser.filters.NodeClassFilter;
     10 
     11 import org.htmlparser.filters.OrFilter;
     12 
     13 import org.htmlparser.filters.TagNameFilter;
     14 
     15 import org.htmlparser.tags.TableColumn;
     16 
     17 import org.htmlparser.tags.TableRow;
     18 
     19 import org.htmlparser.tags.TableTag;
     20 
     21 import org.htmlparser.util.NodeList;
     22 
     23 import org.htmlparser.util.ParserException;
     24 
     25 import junit.framework.TestCase;
     26 
     27 public class ParserTestCase extends TestCase {
     28 
     29 private static final Logger logger = Logger.getLogger(ParserTestCase.class);
     30 
     31 public ParserTestCase(String name) {
     32 
     33 super(name);
     34 
     35 }
     36 
     37 /**
     38 
     39  * 测试对<table>
     40 
     41  * <tr>
     42 
     43  * <td></td>
     44 
     45  * </tr>
     46 
     47  * </table>的解析
     48 
     49  */
     50 
     51 public void testTable() {
     52 
     53 Parser myParser;
     54 
     55 NodeList nodeList = null;
     56 
     57 myParser = Parser
     58 
     59 .createParser(
     60 
     61 "<body> "
     62 
     63 + "<table id=’table1′ >"
     64 
     65 + "<tr id='tro1'><td>1-11</td><td>1-12</td><td>1-13</td></tr>"
     66 
     67 + "<tr id='tro2'><td>1-21</td><td>1-22</td><td>1-23</td></tr>"
     68 
     69 + "<tr id='tro3'><td>1-31</td><td>1-32</td><td>1-33</td></tr></table>"
     70 
     71 + "<table id=’table2′ >"
     72 
     73 + "<tr id='tro4'><td>2-11</td><td>2-12</td><td>2-13</td></tr>"
     74 
     75 + "<tr id='tro5'><td>2-21</td><td>2-22</td><td>2-23</td></tr>"
     76 
     77 + "<tr id='tro6'><td>2-31</td><td>2-32</td><td>2-33</td></tr></table>"
     78 
     79 + "</body>", "GBK");
     80 
     81 NodeFilter tableFilter = new NodeClassFilter(TableTag.class);
     82 
     83 OrFilter lastFilter = new OrFilter();
     84 
     85 lastFilter.setPredicates(new NodeFilter[] { tableFilter });
     86 
     87 try {
     88 
     89 nodeList = myParser.parse(lastFilter);
     90 
     91 for (int i = 0; i <= nodeList.size(); i++) {
     92 
     93 if (nodeList.elementAt(i) instanceof TableTag) {
     94 
     95 TableTag tag = (TableTag) nodeList.elementAt(i);
     96 
     97 TableRow[] rows = tag.getRows();
     98 
     99 for (int j = 0; j < rows.length; j++) {
    100 
    101 TableRow tr = (TableRow) rows[j];
    102 
    103 System.out.println(tr.getAttribute("id"));
    104 
    105 if (tr.getAttribute("id").equalsIgnoreCase("tro1")) {
    106 
    107 TableColumn[] td = tr.getColumns();
    108 
    109 for (int k = 0; k < td.length; k++) {
    110 
    111 // logger.fatal("<td>" +
    112 
    113 // td[k].toPlainTextString());
    114 
    115 System.out.println("<td>"
    116 
    117 + td[k].toPlainTextString());
    118 
    119 }
    120 
    121 }
    122 
    123 }
    124 
    125 }
    126 
    127 }
    128 
    129 } catch (ParserException e) {
    130 
    131 e.printStackTrace();
    132 
    133 }
    134 
    135 }
    136 
    137 /**
    138 
    139  * 得到目标数据
    140 
    141  * 
    142 
    143  * @param url:目标url
    144 
    145  * @throws Exception
    146 
    147  */
    148 
    149 public static void getDatabyUrl(String url) throws Exception {
    150 
    151 Parser myParser = new Parser(url);
    152 
    153 NodeList nodeList = null;
    154 
    155 myParser.setEncoding("gb2312");
    156 
    157 NodeFilter tableFilter = new NodeClassFilter(TableTag.class);
    158 
    159 OrFilter lastFilter = new OrFilter();
    160 
    161 lastFilter.setPredicates(new NodeFilter[] { tableFilter });
    162 
    163 try {
    164 
    165 nodeList = myParser.parse(lastFilter);
    166 
    167 // 可以从数据table的size:19-21开始到结束
    168 
    169 for (int i = 15; i <= nodeList.size(); i++) {
    170 
    171 if (nodeList.elementAt(i) instanceof TableTag) {
    172 
    173 TableTag tag = (TableTag) nodeList.elementAt(i);
    174 
    175 TableRow[] rows = tag.getRows();
    176 
    177 for (int j = 0; j < rows.length; j++) {
    178 
    179 TableRow tr = (TableRow) rows[j];
    180 
    181 if (tr.getAttribute("id") != null
    182 
    183 && tr.getAttribute("id").equalsIgnoreCase(
    184 
    185 "tr02")) {
    186 
    187 TableColumn[] td = tr.getColumns();
    188 
    189 // 对不起,没有你要查询的记录!
    190 
    191 if (td.length == 1) {
    192 
    193 System.out.println("对不起,没有你要查询的记录");
    194 
    195 } else {
    196 
    197 for (int k = 0; k < td.length; k++) {
    198 
    199 System.out.println("<td>内容:"
    200 
    201 + td[k].toPlainTextString().trim());
    202 
    203 }
    204 
    205 }
    206 
    207 }
    208 
    209 }
    210 
    211 }
    212 
    213 }
    214 
    215 } catch (ParserException e) {
    216 
    217 e.printStackTrace();
    218 
    219 }
    220 
    221 }
    222 
    223 /**
    224 
    225  * 测试已经得出有数据时table:22个,没有数据时table:19个
    226 
    227  * 
    228 
    229  * @param args
    230 
    231  */
    232 
    233 public static void main(String[] args) {
    234 
    235 try {
    236 
    237 // getDatabyUrl("http://gd.12530.com/user/querytonebytype.do?field=tonecode&condition=619505000000008942&type=1006&pkValue=619505000000008942");
    238 
    239 getDatabyUrl("http://gd.12530.com/user/querytonebytype.do?field=tonecode&condition=619272000000001712&type=1006&pkValue=619272000000001712");
    240 
    241 } catch (Exception e) {
    242 
    243 e.printStackTrace();
    244 
    245 }
    246 
    247 }
    248 
    249 }

    6.html解析常用

      1 package com.jscud.test;
      2 
      3 import java.io.BufferedReader;
      4 import java.io.File;
      5 import java.io.FileInputStream;
      6 import java.io.InputStreamReader;
      7 
      8 import org.htmlparser.Node;
      9 import org.htmlparser.NodeFilter;
     10 import org.htmlparser.Parser;
     11 import org.htmlparser.filters.NodeClassFilter;
     12 import org.htmlparser.filters.OrFilter;
     13 import org.htmlparser.nodes.TextNode;
     14 import org.htmlparser.tags.LinkTag;
     15 import org.htmlparser.util.NodeList;
     16 import org.htmlparser.util.ParserException;
     17 import org.htmlparser.visitors.HtmlPage;
     18 import org.htmlparser.visitors.TextExtractingVisitor;
     19 
     20 import com.jscud.util.LogMan; //一个日志记录类
     21 
     22 /**
     23 * 演示了Html Parse的应用.
     24 * 
     25 * @author scud http://www.jscud.com (http://www.jscud.com/)
     26 */
     27 
     28 public class ParseHtmlTest
     29 {
     30 
     31 public static void main(String[] args) throws Exception
     32 {
     33 String aFile = "e:/jscud/temp/test.htm";
     34 
     35 String content = readTextFile(aFile, "GBK");
     36 
     37 test1(content);
     38 System.out.println("====================================");
     39 
     40 test2(content);
     41 System.out.println("====================================");
     42 
     43 test3(content);
     44 System.out.println("====================================");
     45 
     46 test4(content);
     47 System.out.println("====================================");
     48 
     49 test5(aFile);
     50 System.out.println("====================================");
     51 
     52 //访问外部资源,相对慢
     53 test5("http://www.jscud.com (http://www.jscud.com/)"); 
     54 System.out.println("====================================");
     55 
     56 }
     57 
     58 /**
     59 * 读取文件的方式来分析内容.
     60 * filePath也可以是一个Url.
     61 * 
     62 * @param resource 文件/Url
     63 */
     64 public static void test5(String resource) throws Exception
     65 {
     66 Parser myParser = new Parser(resource);
     67 
     68 //设置编码
     69 myParser.setEncoding("GBK");
     70 
     71 HtmlPage visitor = new HtmlPage(myParser);
     72 
     73 myParser.visitAllNodesWith(visitor);
     74 
     75 String textInPage = visitor.getTitle();
     76 
     77 System.out.println(textInPage);
     78 }
     79 
     80 /**
     81 * 按页面方式处理.对一个标准的Html页面,推荐使用此种方式.
     82 */
     83 public static void test4(String content) throws Exception
     84 {
     85 Parser myParser;
     86 myParser = Parser.createParser(content, "GBK");
     87 
     88 HtmlPage visitor = new HtmlPage(myParser);
     89 
     90 myParser.visitAllNodesWith(visitor);
     91 
     92 String textInPage = visitor.getTitle();
     93 
     94 System.out.println(textInPage);
     95 }
     96 
     97 /**
     98 * 利用Visitor模式解析html页面.
     99 *
    100 * 小优点:翻译了<>等符号 
    101 * 缺点:好多空格,无法提取link
    102 * 
    103 */
    104 public static void test3(String content) throws Exception
    105 {
    106 Parser myParser;
    107 myParser = Parser.createParser(content, "GBK");
    108 
    109 TextExtractingVisitor visitor = new TextExtractingVisitor();
    110 
    111 myParser.visitAllNodesWith(visitor);
    112 
    113 String textInPage = visitor.getExtractedText();
    114 
    115 System.out.println(textInPage);
    116 }
    117 
    118 /**
    119 * 得到普通文本和链接的内容.
    120 * 
    121 * 使用了过滤条件.
    122 */
    123 public static void test2(String content) throws ParserException
    124 {
    125 Parser myParser;
    126 NodeList nodeList = null;
    127 
    128 myParser = Parser.createParser(content, "GBK");
    129 
    130 NodeFilter textFilter = new NodeClassFilter(TextNode.class);
    131 NodeFilter linkFilter = new NodeClassFilter(LinkTag.class);
    132 
    133 //暂时不处理 meta
    134 //NodeFilter metaFilter = new NodeClassFilter(MetaTag.class);
    135 
    136 OrFilter lastFilter = new OrFilter();
    137 lastFilter.setPredicates(new NodeFilter[] { textFilter, linkFilter });
    138 
    139 nodeList = myParser.parse(lastFilter);
    140 
    141 Node[] nodes = nodeList.toNodeArray();
    142 
    143 for (int i = 0; i < nodes.length; i++)
    144 {
    145 Node anode = (Node) nodes[i];
    146 
    147 String line = "";
    148 if (anode instanceof TextNode)
    149 {
    150 TextNode textnode = (TextNode) anode;
    151 //line = textnode.toPlainTextString().trim();
    152 line = textnode.getText();
    153 }
    154 else if (anode instanceof LinkTag)
    155 {
    156 LinkTag linknode = (LinkTag) anode;
    157 
    158 line = linknode.getLink();
    159 //@todo ("") 过滤jsp标签:可以自己实现这个函数
    160 //line = StringFunc.replace(line, "<%.*%>", "");
    161 }
    162 
    163 if (isTrimEmpty(line))
    164 continue;
    165 
    166 System.out.println(line);
    167 }
    168 }
    169 
    170 /**
    171 * 解析普通文本节点.
    172 * 
    173 * @param content
    174 * @throws ParserException
    175 */
    176 public static void test1(String content) throws ParserException
    177 {
    178 Parser myParser;
    179 Node[] nodes = null;
    180 
    181 myParser = Parser.createParser(content, null);
    182 
    183 nodes = myParser.extractAllNodesThatAre(TextNode.class); //exception could be thrown here
    184 
    185 for (int i = 0; i < nodes.length; i++)
    186 {
    187 TextNode textnode = (TextNode) nodes[i];
    188 String line = textnode.toPlainTextString().trim();
    189 if (line.equals(""))
    190 continue;
    191 System.out.println(line);
    192 }
    193 
    194 }
    195 
    196 /**
    197 * 读取一个文件到字符串里.
    198 * 
    199 * @param sFileName 文件名
    200 * @param sEncode String
    201 * @return 文件内容
    202 */
    203 public static String readTextFile(String sFileName, String sEncode)
    204 {
    205 StringBuffer sbStr = new StringBuffer();
    206 
    207 try
    208 {
    209 File ff = new File(sFileName);
    210 InputStreamReader read = new InputStreamReader(new FileInputStream(ff),
    211 sEncode);
    212 BufferedReader ins = new BufferedReader(read);
    213 
    214 String dataLine = "";
    215 while (null != (dataLine = ins.readLine()))
    216 {
    217 sbStr.append(dataLine);
    218 sbStr.append("\r\n");
    219 }
    220 
    221 ins.close();
    222 }
    223 catch (Exception e)
    224 {
    225 LogMan.error("read Text File Error", e);
    226 }
    227 
    228 return sbStr.toString();
    229 }
    230 
    231 /**
    232 * 去掉左右空格后字符串是否为空
    233 * @param astr String
    234 * @return boolean
    235 */
    236 public static boolean isTrimEmpty(String astr)
    237 {
    238 if ((null == astr) || (astr.length() == 0))
    239 {
    240 return true;
    241 }
    242 if (isBlank(astr.trim()))
    243 {
    244 return true;
    245 }
    246 return false;
    247 }
    248 
    249 /**
    250 * 字符串是否为空:null或者长度为0.
    251 * @param astr 源字符串.
    252 * @return boolean
    253 */
    254 public static boolean isBlank(String astr)
    255 {
    256 if ((null == astr) || (astr.length() == 0))
    257 {
    258 return true;
    259 }
    260 else
    261 {
    262 return false;
    263 }
    264 }
    265 
    266 }

    2.使用 HttpClient 和 HtmlParser 实现简易爬虫

     本小结简单的介绍一下 HttpClinet 和 HtmlParser 两个开源的项目,以及他们的网站和提供下载的地址。

      HttpClient 简介

     HTTP 协议是现在的因特网最重要的协议之一。除了 WEB 浏览器之外, WEB 服务,基于网络的应用程序以及日益增长的网络计算不断扩展着 HTTP 协议的角色,使得越来越多的应用程序需要 HTTP 协议的支持。虽然 JAVA 类库 .net 包提供了基本功能, 来使用 HTTP 协议访问网络资源,但是其灵活性和功能远不能满足很多应用程序的需要。而 Jakarta Commons HttpClient 组件寻求提供更为灵活,更加高效的 HTTP 协议支持,简化基于 HTTP 协议的应用程序的创建。 HttpClient 提供了很多的特性,支持最新的 HTTP 标准,可以访问这里了解更多关于 HttpClinet 的详细信息。目前有很多的开源项目都用到了 HttpClient 提供的 HTTP功能,登陆网址可以查看这些项目。本文中使用 HttpClinet 提供的类库来访问和下载 Internet上面的网页,在后续部分会详细介绍到其提供的两种请求网络资源的方法: Get 请求和 Post 请求。Apatche 提供免费的 HTTPClien t源码和 JAR 包下载,可以登陆这里 下载最新的HttpClient 组件。笔者使用的是 HttpClient3.1。

      HtmlParser 简介

       当今的 Internet 上面有数亿记的网页,越来越多应用程序将这些网页作为分析和处理的数据对象。这些网页多为半结构化的文本,有着大量的标签和嵌套的结构。当我们自己开发一 些处理网页的应用程序时,会想到要开发一个单独的网页解析器,这一部分的工作必定需要付出相当的精力和时间。事实上,做为 JAVA 应用程序开发者, HtmlParser 为其提供了强大而灵活易用的开源类库,大大节省了写一个网页解析器的开销。 HtmlParser 是 http://sourceforge.net 上活跃的一个开源项目,它提供了线性和嵌套两种方式来解析网页,主要用于 html 网页的转换(Transformation) 以及网页内容的抽取 (Extraction)。HtmlParser 有如下一些易于使用的特性:过滤器 (Filters),访问者模式 (Visitors),处理自定义标签以及易于使用的 JavaBeans。正如 HtmlParser 首页所说:它是一个快速,健壮以及严格测试过的组件;以它设计的简洁,程序运行的速度以及处理 Internet 上真实网页的能力吸引着越来越多的开发者。 本文中就是利用HtmlParser 里提取网页里的链接,实现简易爬虫里的关键部分。HtmlParser 最新的版本是HtmlParser1.6,可以登陆这里下载其源码、 API 参考文档以及 JAR 包。


     简单强大的 StringBean 

     如果你想要网页中去掉所有的标签后剩下的文本,那就是用 StringBean 吧。以下简单的代码可以帮你解决这样的问题:

      清单5

      StringBean sb = new StringBean();

      sb.setLinks(false);//设置结果中去点链接

      sb.setURL(url);//设置你所需要滤掉网页标签的页面 url

      System.out.println(sb.getStrings());//打印结果

      HtmlParser 提供了强大的类库来处理网页,由于本文旨在简单的介绍,因此只是将与笔者后续爬虫部分有关的关键类库进行了示例说明。感兴趣的读者可以专门来研究一下 HtmlParser 更为强大的类库。

      简易爬虫的实现

      HttpClient 提供了便利的 HTTP 协议访问,使得我们可以很容易的得到某个网页的源码并保存在本地;HtmlParser 提供了如此简便灵巧的类库,可以从网页中便捷的提取出指向其他网页的超链接。笔者结合这两个开源包,构建了一个简易的网络爬虫。

      爬虫 (Crawler) 原理

       学过数据结构的读者都知道有向图这种数据结构。如下图所示,如果将网页看成是图中的某一个节点,而将网页中指向其他网页的链接看成是这个节点指向其他节 点的边,那么我们很容易将整个 Internet 上的网页建模成一个有向图。理论上,通过遍历算法遍历该图,可以访问到Internet 上的几乎所有的网页。最简单的遍历就是宽度优先以及深度优先。以下笔者实现的简易爬虫就是使用了宽度优先的爬行策略。

      图 2. 网页关系的建模图

      简易爬虫实现流程

      在看简易爬虫的实现代码之前,先介绍一下简易爬虫爬取网页的流程。

     图 3. 爬虫流程图

    各个类的源码以及说明

      对应上面的流程图,简易爬虫由下面几个类组成,各个类职责如下:

      Crawler.java:爬虫的主方法入口所在的类,实现爬取的主要流程。

      LinkDb.java:用来保存已经访问的 url 和待爬取的 url 的类,提供url出对入队操作。

      Queue.java: 实现了一个简单的队列,在 LinkDb.java 中使用了此类。

      FileDownloader.java:用来下载 url 所指向的网页。

      HtmlParserTool.java: 用来抽取出网页中的链接。

      LinkFilter.java:一个接口,实现其 accept() 方法用来对抽取的链接进行过滤。 

      下面是各个类的源码,代码中的注释有比较详细的说明。

    3.Htmlparser汇总说明

    关键字: htmlparser 

        需要做一个垂直搜索引擎,比较了nekohtml和htmlparser 的功能,尽管nekohtml在容错性、性能等方面的口碑好像比htmlparser好(htmlunit也用的是nekohtml),但感觉 nekohtml的测试用例和文档都比htmlparser都少,而且htmlparser基本上能够满足垂直搜索引擎页面处理分析的需求,因此先研究一 下htmlparser的使用,有空再研究nekohtml和mozilla html parser的使用。 

        html的功能还是官方说得最为清楚, 

    引用

        HTML Parser is a Java library used to parse HTML in either a linear or nested fashion. Primarily used for transformation or extraction, it features filters, visitors, custom tags and easy to use JavaBeans. It is a fast, robust and well tested package. 

        The two fundamental use-cases that are handled by the parser are extraction and transformation (the syntheses use-case, where HTML pages are created from scratch, is better handled by other tools closer to the source of data). While prior versions concentrated on data extraction from web pages, Version 1.4 of the HTMLParser has substantial improvements in the area of transforming web pages, with simplified tag creation and editing, and verbatim toHtml() method output.



        研究的重点还是extraction的使用,有空再研究transformation的使用。 
    1、htmlparser对html页面处理的数据结构 



    如图所示,HtmlParser采用了经典的Composite模式,通过RemarkNode、TextNode、TagNode、AbstractNode和Tag来描述HTML页面各元素。 

        * org.htmlparser.Node: 

        Node接口定义了进行树形结构节点操作的各种典型操作方法,

    包括: 

        节点到html文本、text文本的方法:toPlainTextString、toHtml 

       典型树形结构遍历的方法:getParent、getChildren、getFirstChild、getLastChild、getPreviousSibling、getNextSibling、getText 

        获取节点对应的树形结构结构的顶级节点Page对象方法:getPage 

        获取节点起始位置的方法:getStartPosition、getEndPosition 

       Visitor方法遍历节点时候方法:accept (NodeVisitor visitor) 

        Filter方法:collectInto (NodeList list, NodeFilter filter) 

        Object方法:toString、clone 

        * org.htmlparser.nodes.AbstractNode: 

        AbstractNode是形成HTML树形结构抽象基类,实现了Node接口。 

        在htmlparser中,Node分成三类: 

        RemarkNode:代表Html中的注释 

        TagNode:标签节点。 

        TextNode:文本节点 

        这三类节点都继承AbstractNode。 

        * org.htmlparser.nodes.TagNode: 

        TagNode包含了对HTML处理的核心的各个类,是所有TAG的基类,其中有分为包含其他TAG的复合节点ComositeTag和不包含其他TAG的叶子节点Tag。 

        复合节点CompositeTag:   

            AppletTag,BodyTag,Bullet,BulletList,DefinitionList,DefinitionListBullet,Div,FormTag,FrameSetTag,HeadingTag, 

            HeadTag,Html,LabelTag,LinkTag,ObjectTag,ParagraphTag,ScriptTag,SelectTag,Span,StyleTag,TableColumn, 

           TableHeader,TableRow,TableTag,TextareaTag,TitleTag 

        叶子节点TAG: 

            BaseHrefTag,DoctypeTag,FrameTag,ImageTag,InputTag,JspTag,MetaTag,ProcessingInstructionTag, 
    2、htmlparser对html页面处理的算法 

    主要是如下几种方式 

    l 采用Visitor方式访问Html 

    1. 3、htmlparser关键包结构说明  
    
    2.   
    
    3.     htmlparser其实核心代码并不多,好好研究一下其代码,弥补文档不足的问题。同时htmlparser的代码注释和单元测试用例还是很齐全的,也有助于了解htmlparser的用法。  
    
    4.   
    
    5.   
    
    6. 3.1、org.htmlparser  
    
    7.   
    
    8.     定义了htmlparser的一些基础类。其中最为重要的是Parser类。  
    
    9.   
    
    10.     Parser 是htmlparser的最核心的类,其构造函数提供了如下:Parser.createParser (String html,  String charset)、 Parser ()、Parser (Lexer lexer, ParserFeedback fb)、 Parser (URLConnection connection, ParserFeedback fb)、Parser  (String resource, ParserFeedback feedback)、 Parser (String resource)  
    
    11.   
    
    12.   各构造函数的具体用法及含义可以查看其代码,很容易理解。  
    
    13.   
    
    14.   Parser常用的几个方法:  
    
    15.   
    
    16.     *   elements获取元素  
    
    17.   
    
    18.     Parser parser = new Parser (”http://www.google.com”);  
    
    19.     for (NodeIterator i = parser.elements (); i.hasMoreElements (); )  
    
    20.       processMyNodes (i.nextNode ());  
    
    21.   
    
    22.     * parse (NodeFilter filter):通过NodeFilter方式获取  
    
    23.     * visitAllNodesWith (NodeVisitor visitor):通过Nodevisitor方式  
    
    24.     * extractAllNodesThatMatch (NodeFilter filter):通过NodeFilter方式  
    
    25.   
    
    26. 3.2、org.htmlparser.beans  
    
    27.   
    
    28.     对Visitor和Filter的方法进行了封装,定义了针对一些常用html元素操作的bean,简化对常用元素的提取操作。  
    
    29.   
    
    30.     包括:FilterBean、HTMLLinkBean、HTMLTextBean、LinkBean、StringBean、BeanyBaby等。  
    
    31. 3.3、org.htmlparser.nodes  
    
    32.   
    
    33.     定义了基础的node,包括:AbstractNode、RemarkNode、TagNode、TextNode等。  
    
    34. 3.4、org.htmlparser.tags  
    
    35.   
    
    36.     定义了htmlparser的各种tag。  
    
    37. 3.5、org.htmlparser.filters  
    
    38.   
    
    39.      定义了htmlparser所提供的各种filter,主要通过extractAllNodesThatMatch  (NodeFilter filter)来对html页面指定类型的元素进行过滤,包括:AndFilter、 CssSelectorNodeFilter、 HasAttributeFilter、HasChildFilter、 HasParentFilter、HasSiblingFilter、 IsEqualFilter、LinkRegexFilter、 LinkStringFilter、NodeClassFilter、 NotFilter、OrFilter、RegexFilter、 StringFilter、TagNameFilter、XorFilter  
    
    40. 3.6、org.htmlparser.visitors  
    
    41.   
    
    42.     定义了htmlparser所提供的各种visitor,主要通过visitAllNodesWith (NodeVisitor visitor)来对 html页面元素进行遍历,包括:HtmlPage、LinkFindingVisitor、NodeVisitor、  ObjectFindingVisitor、StringFindingVisitor、TagFindingVisitor、  TextExtractingVisitor、UrlModifyingVisitor  
    
    43.   
    
    44.    
    
    45. 3.7、org.htmlparser.parserapplications  
    
    46.   
    
    47.    定义了一些实用的工具,包括LinkExtractor、SiteCapturer、StringExtractor、WikiCapturer,这几个类也可以作为htmlparser使用样例。  
    
    48. 3.8、org.htmlparser.tests  
    
    49.   
    
    50.    对各种功能的单元测试用例,也可以作为htmlparser使用的样例。  
    
    51.   
    
    52.    
    
    53. 4、htmlparser的使用样例  
    
    54.   
    
    55.    
    
    56.   
    
    57. import java.net.URL;  
    
    58.   
    
    59. import junit.framework.TestCase;  
    
    60.   
    
    61. import org.apache.log4j.Logger;  
    
    62. import org.htmlparser.Node;  
    
    63. import org.htmlparser.NodeFilter;  
    
    64. import org.htmlparser.Parser;  
    
    65. import org.htmlparser.Tag;  
    
    66. import org.htmlparser.beans.LinkBean;  
    
    67. import org.htmlparser.filters.NodeClassFilter;  
    
    68. import org.htmlparser.filters.OrFilter;  
    
    69. import org.htmlparser.filters.TagNameFilter;  
    
    70. import org.htmlparser.tags.HeadTag;  
    
    71. import org.htmlparser.tags.ImageTag;  
    
    72. import org.htmlparser.tags.InputTag;  
    
    73. import org.htmlparser.tags.LinkTag;  
    
    74. import org.htmlparser.tags.OptionTag;  
    
    75. import org.htmlparser.tags.SelectTag;  
    
    76. import org.htmlparser.tags.TableColumn;  
    
    77. import org.htmlparser.tags.TableRow;  
    
    78. import org.htmlparser.tags.TableTag;  
    
    79. import org.htmlparser.tags.TitleTag;  
    
    80. import org.htmlparser.util.NodeIterator;  
    
    81. import org.htmlparser.util.NodeList;  
    
    82. import org.htmlparser.util.ParserException;  
    
    83. import org.htmlparser.visitors.HtmlPage;  
    
    84. import org.htmlparser.visitors.NodeVisitor;  
    
    85. import org.htmlparser.visitors.ObjectFindingVisitor;  
    
    86.   
    
    87. public class ParserTestCase extends TestCase {  
    
    88.   
    
    89.     private static final Logger logger = Logger.getLogger(ParserTestCase.class);  
    
    90.   
    
    91.     public ParserTestCase(String name) {  
    
    92.         super(name);  
    
    93.     }  
    
    94.     /* 
    
    95.      * 测试ObjectFindVisitor的用法 
    
    96.      */  
    
    97.     public void testImageVisitor() {  
    
    98.         try {  
    
    99.             ImageTag imgLink;  
    
    100.             ObjectFindingVisitor visitor = new ObjectFindingVisitor(  
    
    101.                     ImageTag.class);  
    
    102.             Parser parser = new Parser();  
    
    103.             parser.setURL(”http://www.google.com”);  
    
    104.             parser.setEncoding(parser.getEncoding());  
    
    105.             parser.visitAllNodesWith(visitor);  
    
    106.             Node[] nodes = visitor.getTags();  
    
    107.             for (int i = 0; i < nodes.length; i++) {  
    
    108.                 imgLink = (ImageTag) nodes[i];  
    
    109.                 logger.fatal(”testImageVisitor() ImageURL = “  
    
    110.                         + imgLink.getImageURL());  
    
    111.                 logger.fatal(”testImageVisitor() ImageLocation = “  
    
    112.                         + imgLink.extractImageLocn());  
    
    113.                 logger.fatal(”testImageVisitor() SRC = “  
    
    114.                         + imgLink.getAttribute(”SRC”));  
    
    115.             }  
    
    116.         }  
    
    117.         catch (Exception e) {  
    
    118.             e.printStackTrace();  
    
    119.         }  
    
    120.     }  
    
    121.     /* 
    
    122.      * 测试TagNameFilter用法 
    
    123.      */  
    
    124.     public void testNodeFilter() {  
    
    125.         try {  
    
    126.             NodeFilter filter = new TagNameFilter(”IMG”);  
    
    127.             Parser parser = new Parser();  
    
    128.             parser.setURL(”http://www.google.com”);  
    
    129.             parser.setEncoding(parser.getEncoding());  
    
    130.             NodeList list = parser.extractAllNodesThatMatch(filter);  
    
    131.             for (int i = 0; i < list.size(); i++) {  
    
    132.                 logger.fatal(”testNodeFilter() ” + list.elementAt(i).toHtml());  
    
    133.             }  
    
    134.         } catch (Exception e) {  
    
    135.             e.printStackTrace();  
    
    136.         }  
    
    137.   
    
    138.     }  
    
    139.     /* 
    
    140.      * 测试NodeClassFilter用法 
    
    141.      */  
    
    142.     public void testLinkTag() {  
    
    143.         try {  
    
    144.   
    
    145.             NodeFilter filter = new NodeClassFilter(LinkTag.class);  
    
    146.             Parser parser = new Parser();  
    
    147.             parser.setURL(”http://www.google.com”);  
    
    148.             parser.setEncoding(parser.getEncoding());  
    
    149.             NodeList list = parser.extractAllNodesThatMatch(filter);  
    
    150.             for (int i = 0; i < list.size(); i++) {  
    
    151.                 LinkTag node = (LinkTag) list.elementAt(i);  
    
    152.                 logger.fatal(”testLinkTag() Link is :” + node.extractLink());  
    
    153.             }  
    
    154.         } catch (Exception e) {  
    
    155.             e.printStackTrace();  
    
    156.         }  
    
    157.   
    
    158.     }  
    
    159.     /* 
    
    160.      * 测试<link href=” text=’text/css’ rel=’stylesheet’ />用法 
    
    161.      */  
    
    162.     public void testLinkCSS() {  
    
    163.         try {  
    
    164.   
    
    165.             Parser parser = new Parser();  
    
    166.             parser  
    
    167.                     .setInputHTML(”<head><title>Link Test</title>”  
    
    168.                             + “<link href=’/test01/css.css’ text=’text/css’ rel=’stylesheet’ />”  
    
    169.                             + “<link href=’/test02/css.css’ text=’text/css’ rel=’stylesheet’ />”  
    
    170.                             + “</head>” + “<body>”);  
    
    171.             parser.setEncoding(parser.getEncoding());  
    
    172.             NodeList nodeList = null;  
    
    173.   
    
    174.             for (NodeIterator e = parser.elements(); e.hasMoreNodes();) {  
    
    175.                 Node node = e.nextNode();  
    
    176.                 logger  
    
    177.                         .fatal(”testLinkCSS()” + node.getText()  
    
    178.                                 + node.getClass());  
    
    179.   
    
    180.             }  
    
    181.         } catch (Exception e) {  
    
    182.             e.printStackTrace();  
    
    183.         }  
    
    184.     }  
    
    185.     /* 
    
    186.      * 测试OrFilter的用法 
    
    187.      */  
    
    188.     public void testOrFilter() {  
    
    189.         NodeFilter inputFilter = new NodeClassFilter(InputTag.class);  
    
    190.         NodeFilter selectFilter = new NodeClassFilter(SelectTag.class);  
    
    191.         Parser myParser;  
    
    192.         NodeList nodeList = null;  
    
    193.   
    
    194.         try {  
    
    195.             Parser parser = new Parser();  
    
    196.             parser  
    
    197.                     .setInputHTML(”<head><title>OrFilter Test</title>”  
    
    198.                             + “<link href=’/test01/css.css’ text=’text/css’ rel=’stylesheet’ />”  
    
    199.                             + “<link href=’/test02/css.css’ text=’text/css’ rel=’stylesheet’ />”  
    
    200.                             + “</head>”  
    
    201.                             + “<body>”  
    
    202.                             + “<input type=’text’ value=’text1′ name=’text1′/>”  
    
    203.                             + “<input type=’text’ value=’text2′ name=’text2′/>”  
    
    204.                             + “<select><option id=’1′>1</option><option id=’2′>2</option><option id=’3′></option></select>”  
    
    205.                             + “<a href=’http://www.yeeach.com’>yeeach.com</a>”  
    
    206.                             + “</body>”);  
    
    207.   
    
    208.             parser.setEncoding(parser.getEncoding());  
    
    209.             OrFilter lastFilter = new OrFilter();  
    
    210.             lastFilter.setPredicates(new NodeFilter[] { selectFilter,  
    
    211.                     inputFilter });  
    
    212.             nodeList = parser.parse(lastFilter);  
    
    213.             for (int i = 0; i <= nodeList.size(); i++) {  
    
    214.                 if (nodeList.elementAt(i) instanceof InputTag) {  
    
    215.                     InputTag tag = (InputTag) nodeList.elementAt(i);  
    
    216.                     logger.fatal(”OrFilter tag name is :” + tag.getTagName()  
    
    217.                             + ” ,tag value is:” + tag.getAttribute(”value”));  
    
    218.                 }  
    
    219.                 if (nodeList.elementAt(i) instanceof SelectTag) {  
    
    220.                     SelectTag tag = (SelectTag) nodeList.elementAt(i);  
    
    221.                     NodeList list = tag.getChildren();  
    
    222.   
    
    223.                     for (int j = 0; j < list.size(); j++) {  
    
    224.                         OptionTag option = (OptionTag) list.elementAt(j);  
    
    225.                         logger  
    
    226.                                 .fatal(”OrFilter Option”  
    
    227.                                         + option.getOptionText());  
    
    228.                     }  
    
    229.   
    
    230.                 }  
    
    231.             }  
    
    232.   
    
    233.         } catch (ParserException e) {  
    
    234.             e.printStackTrace();  
    
    235.         }  
    
    236.     }  
    
    237.     /* 
    
    238.      * 测试对<table><tr><td></td></tr></table>的解析 
    
    239.      */  
    
    240.     public void testTable() {  
    
    241.         Parser myParser;  
    
    242.         NodeList nodeList = null;  
    
    243.         myParser = Parser.createParser(”<body> ” + “<table id=’table1′ >”  
    
    244.                 + “<tr><td>1-11</td><td>1-12</td><td>1-13</td>”  
    
    245.                 + “<tr><td>1-21</td><td>1-22</td><td>1-23</td>”  
    
    246.                 + “<tr><td>1-31</td><td>1-32</td><td>1-33</td></table>”  
    
    247.                 + “<table id=’table2′ >”  
    
    248.                 + “<tr><td>2-11</td><td>2-12</td><td>2-13</td>”  
    
    249.                 + “<tr><td>2-21</td><td>2-22</td><td>2-23</td>”  
    
    250.                 + “<tr><td>2-31</td><td>2-32</td><td>2-33</td></table>”  
    
    251.                 + “</body>”, “GBK”);  
    
    252.         NodeFilter tableFilter = new NodeClassFilter(TableTag.class);  
    
    253.         OrFilter lastFilter = new OrFilter();  
    
    254.         lastFilter.setPredicates(new NodeFilter[] { tableFilter });  
    
    255.         try {  
    
    256.             nodeList = myParser.parse(lastFilter);  
    
    257.             for (int i = 0; i <= nodeList.size(); i++) {  
    
    258.                 if (nodeList.elementAt(i) instanceof TableTag) {  
    
    259.                     TableTag tag = (TableTag) nodeList.elementAt(i);  
    
    260.                     TableRow[] rows = tag.getRows();  
    
    261.   
    
    262.                     for (int j = 0; j < rows.length; j++) {  
    
    263.                         TableRow tr = (TableRow) rows[j];  
    
    264.                         TableColumn[] td = tr.getColumns();  
    
    265.                         for (int k = 0; k < td.length; k++) {  
    
    266.                             logger.fatal(”<td>” + td[k].toPlainTextString());  
    
    267.                         }  
    
    268.   
    
    269.                     }  
    
    270.   
    
    271.                 }  
    
    272.             }  
    
    273.   
    
    274.         } catch (ParserException e) {  
    
    275.             e.printStackTrace();  
    
    276.         }  
    
    277.     }  
    
    278.     /* 
    
    279.      * 测试NodeVisitor的用法,遍历所有节点 
    
    280.      */  
    
    281.     public void testVisitorAll() {  
    
    282.         try {  
    
    283.             Parser parser = new Parser();  
    
    284.             parser.setURL(”http://www.google.com”);  
    
    285.             parser.setEncoding(parser.getEncoding());  
    
    286.             NodeVisitor visitor = new NodeVisitor() {  
    
    287.                 public void visitTag(Tag tag) {  
    
    288.                     logger.fatal(”testVisitorAll()  Tag name is :”  
    
    289.                             + tag.getTagName() + ” \n Class is :”  
    
    290.                             + tag.getClass());  
    
    291.                 }  
    
    292.   
    
    293.             };  
    
    294.   
    
    295.             parser.visitAllNodesWith(visitor);  
    
    296.         } catch (ParserException e) {  
    
    297.             e.printStackTrace();  
    
    298.         }  
    
    299.     }  
    
    300.     /* 
    
    301.      * 测试对指定Tag的NodeVisitor的用法 
    
    302.      */  
    
    303.     public void testTagVisitor() {  
    
    304.         try {  
    
    305.   
    
    306.             Parser parser = new Parser(  
    
    307.                     “<head><title>dddd</title>”  
    
    308.                             + “<link href=’/test01/css.css’ text=’text/css’ rel=’stylesheet’ />”  
    
    309.                             + “<link href=’/test02/css.css’ text=’text/css’ rel=’stylesheet’ />”  
    
    310.                             + “</head>” + “<body>”  
    
    311.                             + “<a href=’http://www.yeeach.com’>yeeach.com</a>”  
    
    312.                             + “</body>”);  
    
    313.             NodeVisitor visitor = new NodeVisitor() {  
    
    314.                 public void visitTag(Tag tag) {  
    
    315.                     if (tag instanceof HeadTag) {  
    
    316.                         logger.fatal(”visitTag() HeadTag : Tag name is :”  
    
    317.                                 + tag.getTagName() + ” \n Class is :”  
    
    318.                                 + tag.getClass() + “\n Text is :”  
    
    319.                                 + tag.getText());  
    
    320.                     } else if (tag instanceof TitleTag) {  
    
    321.                         logger.fatal(”visitTag() TitleTag : Tag name is :”  
    
    322.                                 + tag.getTagName() + ” \n Class is :”  
    
    323.                                 + tag.getClass() + “\n Text is :”  
    
    324.                                 + tag.getText());  
    
    325.   
    
    326.   
    
    327.                     } else if (tag instanceof LinkTag) {  
    
    328.                         logger.fatal(”visitTag() LinkTag : Tag name is :”  
    
    329.                                 + tag.getTagName() + ” \n Class is :”  
    
    330.                                 + tag.getClass() + “\n Text is :”  
    
    331.                                 + tag.getText() + ” \n getAttribute is :”  
    
    332.                                 + tag.getAttribute(”href”));  
    
    333.                     } else {  
    
    334.                         logger.fatal(”visitTag() : Tag name is :”  
    
    335.                                 + tag.getTagName() + ” \n Class is :”  
    
    336.                                 + tag.getClass() + “\n Text is :”  
    
    337.                                 + tag.getText());  
    
    338.                     }  
    
    339.   
    
    340.                 }  
    
    341.   
    
    342.             };  
    
    343.   
    
    344.             parser.visitAllNodesWith(visitor);  
    
    345.         } catch (Exception e) {  
    
    346.             e.printStackTrace();  
    
    347.         }  
    
    348.     }  
    
    349.     /* 
    
    350.      * 测试HtmlPage的用法 
    
    351.      */  
    
    352.     public void testHtmlPage() {  
    
    353.         String inputHTML = “<html>” + “<head>”  
    
    354.                 + “<title>Welcome to the HTMLParser website</title>”  
    
    355.                 + “</head>” + “<body>” + “Welcome to HTMLParser”  
    
    356.                 + “<table id=’table1′ >”  
    
    357.                 + “<tr><td>1-11</td><td>1-12</td><td>1-13</td>”  
    
    358.                 + “<tr><td>1-21</td><td>1-22</td><td>1-23</td>”  
    
    359.                 + “<tr><td>1-31</td><td>1-32</td><td>1-33</td></table>”  
    
    360.                 + “<table id=’table2′ >”  
    
    361.                 + “<tr><td>2-11</td><td>2-12</td><td>2-13</td>”  
    
    362.                 + “<tr><td>2-21</td><td>2-22</td><td>2-23</td>”  
    
    363.                 + “<tr><td>2-31</td><td>2-32</td><td>2-33</td></table>”  
    
    364.                 + “</body>” + “</html>”;  
    
    365.         Parser parser = new Parser();  
    
    366.         try {  
    
    367.             parser.setInputHTML(inputHTML);  
    
    368.             parser.setEncoding(parser.getURL());  
    
    369.             HtmlPage page = new HtmlPage(parser);  
    
    370.             parser.visitAllNodesWith(page);  
    
    371.             logger.fatal(”testHtmlPage -title is :” + page.getTitle());  
    
    372.             NodeList list = page.getBody();  
    
    373.   
    
    374.             for (NodeIterator iterator = list.elements(); iterator  
    
    375.                     .hasMoreNodes();) {  
    
    376.                 Node node = iterator.nextNode();  
    
    377.                 logger.fatal(”testHtmlPage -node  is :” + node.toHtml());  
    
    378.             }  
    
    379.   
    
    380.         } catch (ParserException e) {  
    
    381.             // TODO Auto-generated catch block  
    
    382.             e.printStackTrace();  
    
    383.         }  
    
    384.     }  
    
    385.     /* 
    
    386.      * 测试LinkBean的用法 
    
    387.      */  
    
    388.     public void testLinkBean() {  
    
    389.         Parser parser = new Parser();  
    
    390.   
    
    391.         LinkBean linkBean = new LinkBean();  
    
    392.         linkBean.setURL(”http://www.google.com”);  
    
    393.         URL[] urls = linkBean.getLinks();  
    
    394.   
    
    395.         for (int i = 0; i < urls.length; i++) {  
    
    396.             URL url = urls[i];  
    
    397.             logger.fatal(”testLinkBean() -url  is :” + url);  
    
    398.         }  
    
    399.   
    
    400.     }  

     401.   

     402. } 

      1 package cn;
      2 
      3  
      4 
      5 import java.io.BufferedReader;
      6 
      7 import java.io.File;
      8 
      9 import java.io.FileOutputStream;
     10 
     11 import java.io.IOException;
     12 
     13 import java.io.InputStream;
     14 
     15 import java.io.InputStreamReader;
     16 
     17 import java.io.OutputStream;
     18 
     19 import java.net.ConnectException;
     20 
     21 import java.net.MalformedURLException;
     22 
     23 import java.net.URL;
     24 
     25 import java.util.ArrayList;
     26 
     27 import java.util.List;
     28 
     29 import java.util.UUID;
     30 
     31  
     32 
     33 import org.htmlparser.NodeFilter;
     34 
     35 import org.htmlparser.Parser;
     36 
     37 import org.htmlparser.filters.TagNameFilter;
     38 
     39 import org.htmlparser.tags.ImageTag;
     40 
     41 import org.htmlparser.util.NodeList;
     42 
     43 import org.htmlparser.util.ParserException;
     44 
     45 import org.htmlparser.visitors.HtmlPage;
     46 
     47  
     48 
     49 public class getAll {
     50 
     51 private final static String CRLF = System.getProperty("line.separator");// 回车换行
     52 
     53  
     54 
     55 public static void makeHtm(int x) {
     56 
     57 InputStream instr = null;
     58 
     59 List list = new ArrayList<String>();
     60 
     61 for (; x > 89205; x--) {
     62 
     63 list.clear();
     64 
     65 try {
     66 
     67 URL ur = new URL("你要扒的地址" + x + ".html"); // 这个要按照情况而定了,我不多说了。
     68 
     69 try {
     70 
     71 System.out.println("正在加载页面:     " + ur.toString());
     72 
     73 instr = ur.openStream(); // 获得网页输出流
     74 
     75 } catch (ConnectException e) {
     76 
     77 System.out.println(e.toString());
     78 
     79 makeHtm(--x); // 如果连接超时,将会抛出这个异常并且换成新的网址继续扒。
     80 
     81 }
     82 
     83 String s = null;
     84 
     85 BufferedReader in = new BufferedReader(new InputStreamReader(
     86 
     87 instr));
     88 
     89 StringBuffer sb = new StringBuffer();
     90 
     91  
     92 
     93 while ((s = in.readLine()) != null) {
     94 
     95 sb.append(s + CRLF); // 读取网页信息,放入字符串缓冲区
     96 
     97 }
     98 
     99 Parser parser = Parser.createParser(sb.toString(), "utf-8"); // 获得整个网页的缓冲区创建解析器
    100 
    101 HtmlPage page = new HtmlPage(parser); // 把解析器交给解析htmlpage
    102 
    103 try {
    104 
    105 parser.visitAllNodesWith(page);
    106 
    107 } catch (ParserException e1) {
    108 
    109 e1 = null;
    110 
    111 }
    112 
    113 NodeList nodelist = page.getBody(); // 获得网页的body部分
    114 
    115 NodeFilter filter = new TagNameFilter("IMG"); // 过滤 img标签也可以过滤
    116 
    117 // sapn、a等标签
    118 
    119  
    120 
    121 nodelist = nodelist.extractAllNodesThatMatch(filter, true);
    122 
    123 for (int i = 0; i < nodelist.size(); i++) {
    124 
    125 ImageTag link = (ImageTag) nodelist.elementAt(i); // 获得所有的
    126 
    127 // IMG标签
    128 
    129 String src = link.getAttribute("src"); // 获得img标签的src属性、这个属性就是
    130 
    131 // 就是那个图片的网址
    132 
    133 list.add(src);
    134 
    135 /**
    136 
    137  * LinkTag link = (LinkTag) nodelist.elementAt(i); // 链接地址
    138 
    139  * System.out.println(link.getAttribute("href") + "\n"); //
    140 
    141  * 链接名称 System.out.println(link.getStringText());
    142 
    143  * 如果过滤超链接就这样写 当然上面的 filter的过滤条件要改成"A"
    144 
    145  */
    146 
    147 }
    148 
    149 in.close();
    150 
    151 down(list, x); // 调用down方法交给 那个存放链接的集合,和 当前下载的x页
    152 
    153 list.clear();
    154 
    155 } catch (MalformedURLException e) {
    156 
    157 e.printStackTrace();
    158 
    159 } catch (IOException e) {
    160 
    161 e.printStackTrace();
    162 
    163 }
    164 
    165 }
    166 
    167 System.out.println("下载完成");
    168 
    169 }
    170 
    171  
    172 
    173 public static void down(List<String> list, int x) throws IOException {
    174 
    175 String substring = UUID.randomUUID().toString();
    176 
    177 InputStream in = null;
    178 
    179 try {
    180 
    181 if (list != null) {
    182 
    183 for (String src : list) {
    184 
    185 URL url = new URL(src);
    186 
    187 try {
    188 
    189 System.out.println("正在下载:   " + url.toString());
    190 
    191 in = url.openStream();
    192 
    193 } catch (ConnectException e) {
    194 
    195 System.out.println(e.toString());
    196 
    197 list.clear();
    198 
    199 makeHtm(--x);
    200 
    201 }
    202 
    203 String string = UUID.randomUUID().toString();
    204 
    205 File forder = new File("F://fuck//" + substring);
    206 
    207 if (!forder.exists()) {
    208 
    209 forder.mkdir();
    210 
    211 }
    212 
    213 File file = new File("F://xx//" + substring + "//" + string
    214 
    215 + ".jpg"); // 每个网页的图片都放在一个UUID的文件夹里,每个图片都是
    216 
    217 // 一个UUID的名字
    218 
    219 OutputStream out = new FileOutputStream(file);
    220 
    221 byte[] b = new byte[1024 * 6]; // 我习惯这个数字 你可以改大点
    222 
    223 int len;
    224 
    225 while ((len = in.read(b)) != -1) {
    226 
    227 out.write(b, 0, len); // 流的对拷,不多说了
    228 
    229 out.flush();
    230 
    231 }
    232 
    233 }
    234 
    235 }
    236 
    237 } catch (MalformedURLException e) {
    238 
    239 makeHtm(--x);
    240 
    241 e.printStackTrace();
    242 
    243 }
    244 
    245 }
    246 
    247 }

     当然 你别忘记  写个 main方法调用他 

  • 相关阅读:
    Java基础50道经典练习题(33)——杨辉三角
    Java基础50道经典练习题(32)——左移右移
    团队第二阶段冲刺04
    团队第二阶段冲刺03
    团队第二阶段冲刺02
    团队第二阶段冲刺01
    团队意见汇总
    各组意见汇总
    团队第一阶段冲刺07
    绩效评估01
  • 原文地址:https://www.cnblogs.com/yixiwenwen/p/2747133.html
Copyright © 2020-2023  润新知