我正在编写一个清理网页的脚本。这包括遍历所有标签(元素)并检查某些规则:
for (Element element : document.select("*") ) {
if (element == null) {
continue;
}
if ( RULE1) ) {
element.remove();
}
else if( RULE2){
element.remove();
}
else if ( RULE3 ) {
element.remove();
}
else if ( RULE4 ) {
element.remove();
}
}
我已经在数十页上测试了这个没有问题。今天我刚刚点击了一个网页java.lang.IndexOutOfBoundsException
:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.remove(ArrayList.java:492)
at org.jsoup.nodes.Node.removeChild(Node.java:423)
at org.jsoup.nodes.Node.remove(Node.java:266)
我的猜测是,在某些时候代码会尝试删除已经删除的元素。但不能告诉我们应该如何/为什么会发生这种情况。
有什么想法吗?
感谢。
编辑1:导致中断的规则
我发现导致代码失败的规则。其中一条规则实际上并没有移除element
但重置其文本:
else if ( matches junk text ) {
String match = getMatchingJunk ( element.ownText() );
if ( match.length() < JUNK_TEXT_ELEMENT_REMOVAL_THRESH ) {
element.text( removeSmallest(element.ownText(), match) ); // <= causing error
continue;
}
element.remove();
}
如果我删除了行element.text( removeSmallest(element.ownText(), match) )
,则错误消失。
答案 0 :(得分:0)
如果我分两个阶段清除垃圾文本,代码似乎有效。代码看起来有点重复和hackish。可能有更好的方法:
第一阶段:收集所有垃圾
Map <String, Element> junks = new HashMap <String, Element>();
for (Element element : document.select("*") ) {
...
if () {
...
}
else if ( matches junk text ) {
String match = getMatchingJunk ( element.ownText() );
if ( match.length() < JUNK_TEXT_ELEMENT_REMOVAL_THRESH ) {
//element.text( removeSmallest(element.ownText(), match) ); // <= causing error
junks.put(elOwnText,element);
continue;
}
element.remove();
}
}
第二阶段:清除垃圾
if ( size(junks) > 0 ) {
for(Map.Entry<String,Element> ent : junks.entrySet()){
String match = getMatchingJunk (ent.getKey()); // this looks repetitive. probably there's a better way to do it
if ( match.length() < JUNK_TEXT_ELEMENT_REMOVAL_THRESH ) {
ent.getValue().text( removeSmallest(ent.getKey(), match) ); // purge junk
}
} // end for
} // end if