java - html解析器的问题

标签 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;
}

}

这段代码的问题:

  • 返回的行号完全错误。 (甚至有匹配的主题之前的行号)
  • 正则表达式从不匹配,尽管我在带有页面源代码的正则表达式测试器中尝试了它。我只尝试了正则表达式,因为带有 h​​tmlparser 的代码不起作用。

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

最佳答案

对于行号问题: 我假设您想知道为什么会收到这么多行“找到标签” — 超出您的预期。问题是这一行有效地将大部分 HTML 页面加载到一个字符串中:

    String content = tag.toPlainTextString(); 

toPlainTextString() 方法包含标签子标签的文本内容,因此包含 ***** 的标签的所有父标签也将包含 *****。我认为您可能想改用 getText(),它不包含子项的文本(请参阅 JavaDoc)。

请注意,最好避免像这样使用 toPlainTextString(),因为它会非常慢。因为文档中的每个标签都会调用它,所以您可能会强制文档被阅读一百遍,这是不必要的……

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

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

所以你的正则表达式会失败,因为它希望同时获得开始、文本和结束。另外,我认为你需要像这样转义星号匹配器:[\*]+

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

关于java - html解析器的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8014795/

相关文章:

javascript - 在 Javascript(Rhino 引擎)中实现自己的 TrustManager

android - 每秒设置textview的文本时,防止除textview之外的其他 View 更新/重绘

android - 关于小/普通/大/xlarge 和 ldpi/mdpi/hdpi/xhdpi 的 Android 设备的正确图形?

java - 将 Java 中的字符串转换为整数

parsing - Haskell 的 parsec 中 CPS 与非 CPS 解析器的堆使用情况

java - 使用notifyDataSetChanged方法删除项目后如何刷新listView?

java - 用Java从文件中获取值

java - GlassFish 4.1.1 和 Apache Felix 5.4.0

android - 是否可以使用 webrtc 构建原生的 android 到 android 视频聊天应用程序?

ios - 如何解析和访问 HTTPresponse 中的特定数据