htmlparser的问题

时间:2011-11-04 19:33:46

标签: java android parsing html-parsing

我需要从页面中提取一个标签(包含多个子项),然后将检索到的文本拆分为包含多个星号(*)的标签。我需要删除带有星星的标签,然后将文本拆分为我想要存储在StringArray中的部分。

之前我使用过http://htmlparser.sourceforge.net/,它可以很好地从特定标签中提取文本。

public class ToeGuideParser extends NodeVisitor{

private static final String TAG = "ToeGuideParser";
final String url = "http://p7510.teamovercome.net/?page_id=18";
private String Guide;
Context context;
int tag_number = 0;

public ToeGuideParser () throws ParserException{
    this(null);
}

public ToeGuideParser(Context context) throws ParserException{
    context = this.context;

    long bfr = startStopWatch();

    Parser parser = new Parser (url);
    parser.visitAllNodesWith(this);

    stopStopWatch(bfr);
}

public void visitTag (Tag tag){
    String tagName = tag.getTagName();
    String content = tag.toPlainTextString(); 
    //Log.d(TAG, tagName);
    if (tagName.equalsIgnoreCase("div")){
        Attribute attr = tag.getAttributeEx("class");
        if (attr!=null){
            String value = attr.getValue();
            if (value.equals("entry-content")){
                //save
                Guide = tag.toHtml(true);
                int guide_start = tag.getStartingLineNumber();
                int guide_end = tag.getEndingLineNumber();
                Log.d(TAG, "Guide starts at "+guide_start+" and ends at "+guide_end);
                //Log.d(TAG, Guide);
            }
        }
    }
    if (content.contains("*****")){
        tag_number++;
        int start = tag.getStartingLineNumber();
        int end = tag.getEndingLineNumber();
        Log.d(TAG, tag_number+" = Tag found at "+start+", ends at "+end);
    }
}

private void split (String bfrSplit){
    if (bfrSplit != null){
        //Log.d(TAG, bfrSplit);
        Pattern pattern = Pattern.compile("<([A-Z][A-Z0-9]*).*>[*]+</\1>", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(bfrSplit);
                while (matcher.find()){
                    Log.d(TAG,"Start index: " + matcher.start());
                    Log.d(TAG," End index: " + matcher.end() + " ");
                    Log.d(TAG,matcher.group());
                }
    }
}



public void finishedParsing(){
    //split(Guide);
    Log.w(TAG, "#########");
    Log.w(TAG, "finished");
}

public long startStopWatch(){
    return System.currentTimeMillis();
}

public String stopStopWatch(long bfr){
    long time = System.currentTimeMillis()-bfr;
    String formatedTime = "Time Taken: "+time+" milli's" ;
    Log.i(TAG, formatedTime);
    return formatedTime;
}

}

public long startStopWatch(){
    return System.currentTimeMillis();
}

public String stopStopWatch(long bfr){
    long time = System.currentTimeMillis()-bfr;
    String formatedTime = "Time Taken: "+time+" milli's" ;
    Log.i(TAG, formatedTime);
    return formatedTime;
}

}

此代码出现问题:

  • 返回的行号完全错误。 (在主题匹配之前有偶数行号)
  • 正则表达式永远不会匹配,尽管我在带有页面源代码的regextester中尝试过它。我只尝试了正则表达式,因为使用htmlparser的代码不起作用。

Stacktrace来说明:

D / ToeGuideParser ( 2146): 1 = Tag found at 11, ends at 11
D / ToeGuideParser ( 2146): 2 = Tag found at 201, ends at 201
D / ToeGuideParser ( 2146): 3 = Tag found at 202, ends at 202
D / ToeGuideParser ( 2146): 4 = Tag found at 237, ends at 237
D / ToeGuideParser ( 2146): 5 = Tag found at 238, ends at 238
D / ToeGuideParser ( 2146): 6 = Tag found at 239, ends at 239
D / ToeGuideParser ( 2146): Guide starts at 248 and ends at 248
D / ToeGuideParser ( 2146): 7 = Tag found at 248, ends at 248
D / ToeGuideParser ( 2146): 8 = Tag found at 261, ends at 261
D / ToeGuideParser ( 2146): 9 = Tag found at 261, ends at 261
D / ToeGuideParser ( 2146): 10 = Tag found at 280, ends at 280
D / ToeGuideParser ( 2146): 11 = Tag found at 280, ends at 280
D / ToeGuideParser ( 2146): 12 = Tag found at 307, ends at 307
D / ToeGuideParser ( 2146): 13 = Tag found at 318, ends at 318
D / ToeGuideParser ( 2146): 14 = Tag found at 322, ends at 322
D / ToeGuideParser ( 2146): 15 = Tag found at 328, ends at 328
D / ToeGuideParser ( 2146): 16 = Tag found at 350, ends at 350
D / ToeGuideParser ( 2146): 17 = Tag found at 367, ends at 367
D / ToeGuideParser ( 2146): 18 = Tag found at 376, ends at 376
W / ToeGuideParser ( 2146): #########
W / ToeGuideParser ( 2146): finished
I / ToeGuideParser ( 2146): Time Taken: 1021 milli's

1 个答案:

答案 0 :(得分:1)

对于行号问题: 我假设你想知道为什么你会有这么多行说“Tag found at” - 这比你想象的要多。问题是这一行有效地将大部分HTML页面加载到一个字符串中:

    String content = tag.toPlainTextString(); 

toPlainTextString()方法包含标记子项的文本内容,因此包含*****的标记的所有父标记也将包含*****。我想你可能想要使用getText(),而不包括孩子们的文字(见JavaDoc)。

请注意,最好避免使用此类toPlainTextString(),因为它会非常慢。因为它是为文档中的每个标记调用的,所以你可能会强迫文档被读取一百次,不必要......

对于正则表达式问题: 你实际上并没有实际调用包含正则表达式的split()方法。但如果你是,我认为它会失败,因为它试图匹配开始标记,文本节点和结束标记。但HTML Parser一次只能为您提供一个节点,即:

  • visitTag()只为您提供了开始标记
  • visitStringNode()只为您提供文字节点
  • visitEndTag()只为您提供结束标记

所以你的正则表达式会失败,因为它希望一次得到开头,文本和结束。另外,我认为你需要像这样逃避星号匹配器:[\*]+

如果需要在所有三个节点上匹配某些内容,则需要在类中添加一些私有变量来记录状态。即如果visitTag()匹配您想要的标记,则设置一个布尔值表示当前标记有效...然后当调用visitStringNode()时,它可以检查该布尔值以决定是处理文本还是忽略它。然后在遇到结束标记时取消设置布尔值。