比如下面的一段html代码<tr><td>  <a href="http://www.test.com"><img src="/~img_folder" /> <b>java test</b></a><td align=center><i>folder</i><td align=right>2009-9-26 16:13:52<td align=right>15
希望获取<b>java test</b>中的java test和><i>folder</i>的folder以及2009-9-26 16:13:52时间,使用HTMLPraser如何实现?

解决方案 »

  1.   

    刚写的,记住,标签只能是td一类的,绝对不可以是b这类文本标签package test;import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;import org.apache.commons.io.FileUtils;
    import org.htmlparser.NodeFilter;
    import org.htmlparser.Parser;
    import org.htmlparser.filters.AndFilter;
    import org.htmlparser.filters.HasAttributeFilter;
    import org.htmlparser.filters.TagNameFilter;
    import org.htmlparser.nodes.TagNode;
    import org.htmlparser.util.NodeList;
    import org.htmlparser.util.ParserException;public class Test {
    public static void main(String args[]) throws IOException {
    //将要解析的文本读到内存
    String content = FileUtils.readFileToString(new File(Test.class
    .getClassLoader().getResource("test/1.txt").getFile()));
    System.out.println(getTagContent(content, "td", null));
    } /**
     * 返回符合要求的第一个标签的文本内容
     * @param content  要解析的文本
     * @param tagName  要解析的标签
     * @param attributesMap  标签的参数和数值,如果没有参数需要解析的话,就为null
     * @return
     */
    public static String getTagContent(String content, String tagName,
    Map<String, String> attributesMap) {
    Parser myParser = Parser.createParser(content, "UTF-8"); // 换成你自己的编码,这里用的是UTF-8
    NodeFilter tagFilter = new TagNameFilter(tagName);
    List<NodeFilter> attributeFiltersList = new ArrayList<NodeFilter>();
    if (attributesMap != null) {
    for (Map.Entry<String, String> entry : attributesMap.entrySet()) {
    attributeFiltersList.add(new HasAttributeFilter(entry.getKey(),
    entry.getValue()));
    }
    }
    attributeFiltersList.add(0, tagFilter);
    NodeFilter filter = new AndFilter(attributeFiltersList.toArray(new NodeFilter[attributeFiltersList.size()]));
    try {
    NodeList list = myParser.parse(filter);
    if (list.size() == 0) {
    return null;
    }
    TagNode node = (TagNode)list.elementAt(0);
    return node.toPlainTextString();
    } catch (ParserException e) {
    // TODO Auto-generated catch block
    return null;
    } }
    }
      

  2.   

    具体用法:String content = FileUtils.readFileToString(new File(Test.class
    .getClassLoader().getResource("test/1.txt").getFile()));
    System.out.println(getTagContent(content, "td", null));
    Map<String,String> attr = new HashMap<String,String>();
    attr.put("align", "right");
    System.out.println(getTagContent(content, "td", attr));
      

  3.   

    使用正则吧,呵呵 String s = "<tr><td>  <a href=\"http://www.test.com\"><img src=\"/~img_folder\" /> <b>java test</b></a><td align=center><i>folder</i><td align=right>2009-9-26 16:13:52<td align=right>15";

    String pattern = "<b>\\s*([^<]*)\\s*</b>.*<i>\\s*([^<]*)\\s*</i><td[^>]*>\\s*(\\s*\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2})";

    Pattern p = Pattern.compile(pattern);
    Matcher m = p.matcher(s);

    while (m.find()) {
    System.out.println(m.group(1));
    System.out.println(m.group(2));
    System.out.println(m.group(3));
    }
    我觉得,无论是用htmlparser还是正则,找出这几段不难,htmlparser也就是做成xml树,然后一级一级的往下找而已
    关键是如何定位这段字符串在整个html中的位置,特别是如果是多次出现的话
    上面的正则只是针对你贴出来的这段串,如果它有一定的特殊性,不保证都适用
      

  4.   

    试了一下,getTagContent(content, "td", null)的话,打印出的是java test,即<b></b>之间的,但是如果我需要获取<i>folder</i>之间的folder怎么办?attr需要如何指定?
      

  5.   

    我想请问下 3 楼,因为htmlparser对抓取比较规范的页面很适合;
    用parser取得标签对间的内容,如你的那个方法,传入的标签为<td>。当我抓取<td>测试</td> ,用你的方法可以抓到“测试”,那如果是现在这样呢:
    <td id="yw" width="6%" nowrap >测试测试测试测试测试</td>是不是也可以用你的那个方法去抓到呢,如果是这样的话,那htmlparser是不是只要是标签对,不管标签还带了什么属性,都忽略呢。。由于是突然之间看到这篇,我自己就没去测试了,所以问下...
      

  6.   

    没用过htmlparser,不过看3楼的代码,估计htmlparser是用Dom把html当xml解析的
    对于Dom对象来说,取一个节点的attribute是会被保存起来的,要取出来也是很容易的事情,所以那些属性是不会被忽略的,htmlparser也应该是有方法来提取这些属性的
    同时,我想,在一个html文件中定位某一个table、td等对象的时候,往往也要通过id或者name属性来确定才行,不然如上面的html,天知道哪个td对象是我要的td啊
      

  7.   

    我是三楼,我给的方法确实只适合于HTML(XML是不会忽略<i></i>的)关于HTMLPARSER,有几种方法来解析HTML,我用的是Filter的方法,可以设置属性(包括无值的属性),但是由于只考虑到LZ的情况,所以功能不全,但是至少给了Filter方式解析HTML的一个小例子。
    另外回9楼,如果只用了TagNameFilter,那么只要标签名对都可以,但是我用AndFilter将这个TagNameFilter和很多HasAtributeFilter组合起来,就可以构成“与”的效果,也就是说出了标签名对,还要标签的属性甚至是值都对。同理,用OrFilter可以构成“或”的效果。
      

  8.   

    那如何获取<b></b>或<i></i>里面的文本?
      

  9.   

    看到“3楼”的回复,自己想来测试下,可竟然报个错,莫名啊
    类里面引入这个:import org.w3c.dom.traversal.NodeFilter;刚开始我以为没错,因为其它地方都没错误,结果错误提示出现在第一行:package com.test;
    报的错误是针对上面引入的那个包:The type org.htmlparser.NodeFilter cannot be resolved. It is indirectly  referenced from required .class files
    自己看了下,它可能是把NodeFilter 当多一个包来处理了,但是为什么却说的是“org.htmlparser.NodeFilter”这个呢,我看了htmlparser.jar里面没有这个NodeFilter ,真的很莫名啊,看来,测试不下去了。
      

  10.   


    htmlparser里面还有个lexer.jar,记得加进去
      

  11.   

    那如何获取 <b> </b>或 <i> </i>里面的文本?
      

  12.   

    那只能用htmlparser一类的纠错之后,把纠错的文本用dom4j来解析