我需要从一个页面(包含多个子项)中提取一个标签,然后将检索到的文本拆分为包含多个星号 (*) 的标签。我需要删除带有星号的标签,然后将文本分成我想存储在 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;
}
}
这段代码的问题:
- 返回的行号完全错误。 (甚至有匹配的主题之前的行号)
- 正则表达式从不匹配,尽管我在带有页面源代码的正则表达式测试器中尝试了它。我只尝试了正则表达式,因为带有 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
最佳答案
对于行号问题: 我假设您想知道为什么会收到这么多行“找到标签” — 超出您的预期。问题是这一行有效地将大部分 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/