我试图解析HTML以下使用jsoup但没能得到正确的语法它。
<div class="info"><strong>Line 1:</strong> some text 1<br>
<b>some text 2</b><br>
<strong>Line 3:</strong> some text 3<br>
</div>
我需要捕捉一些文本1,一些文本2和三个不同的变量一些文本3。
我对第一行中的XPath(这应该是3系相似),但未能制定出相当的CSS选择器。
//div[@class='info']/strong[1]/following::text()
请帮忙。
在一个单独的我有几百个HTML文件和需要分析并从中提取数据在数据库中存储。 是Jsoup最佳选择呢?
我想,因为我还没有找到解决方案,重新打开了这个问题。 请帮忙。
这真的看起来像Jsoup不能处理获取文本进行混合内容的元素。 下面是用用你制定的XPath的解决方案XOM和TagSoup :
import java.io.IOException;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Nodes;
import nu.xom.ParsingException;
import nu.xom.ValidityException;
import nu.xom.XPathContext;
import org.ccil.cowan.tagsoup.Parser;
import org.xml.sax.SAXException;
public class HtmlTest {
public static void main(final String[] args) throws SAXException, ValidityException, ParsingException, IOException {
final String html = "<div class=\"info\"><strong>Line 1:</strong> some text 1<br><b>some text 2</b><br><strong>Line 3:</strong> some text 3<br></div>";
final Parser parser = new Parser();
final Builder builder = new Builder(parser);
final Document document = builder.build(html, null);
final nu.xom.Element root = document.getRootElement();
final Nodes textElements = root.query("//xhtml:div[@class='info']/xhtml:strong[1]/following::text()", new XPathContext("xhtml", root.getNamespaceURI()));
for (int textNumber = 0; textNumber < textElements.size(); ++textNumber) {
System.out.println(textElements.get(textNumber).toXML());
}
}
}
这种输出:
some text 1
some text 2
Line 3:
some text 3
不知道你正在尝试做虽然什么更多的细节,我不知道这是否是你想要什么。
你的问题我认为是,文本你感兴趣的,只有一个短语任何定义标记中包含“一些文本2”,这是由封闭<b>
</b>
标签。 因此,这是通过容易获得:
String text2 = doc.select("div.info b").text();
返回
some text 2
感兴趣的其他文本只能被定义为在您持有的文字<div class="info">
标签,仅此而已。 所以,我知道得到这个唯一的办法是让这个大元素持有的所有文字:
String text1 = doc.select("div.info").text();
但不幸的是,这获得此元素持有的所有文字:
Line 1: some text 1 some text 2 Line 3: some text 3
这是对我所能做的最好的,我希望有人能找到一个更好的答案,并会继续关注此问题。
这是可能得到的对象引用个别TextNodes。 我想,也许你过来看了Jsoup的TextNode对象。
在顶层的文本元素是一个TextNode对象的实例。 例如,“一些文本1”和“一些文本3”下既TextNode对象“<DIV类=‘信息’>”和“第1行:”是“的<strong>”下一个TextNode对象
元素对象有textNodes() ,这将是有用的,你得到这些TextNode对象的保持方法。
请检查下面的代码:
String html = "<html>" +
"<body>" +
"<div class="info">" +
"<strong>Line 1:</strong> some text 1<br>" +
"<b>some text 2</b><br>" +
"<strong>Line 3:</strong> some text 3<br>" +
"</div>" +
"</body>" +
"</html>";
Document document = JSoup.parse(html);
Element infoDiv = document.select("div.info").first();
List<TextNode> infoDivTextNodes = infoDiv.textNodes();
此代码找到的第一个<div>元素谁具有键=“类”和值=“信息”的属性。 然后得到的所有TextNode的参考直接“<DIV类=‘信息’>”下的对象。 这份名单是这样的:
List<TextNode>[" some text 1", " some text 3"]
TextNode对象有一些很好的数据和方法与之相关联的,你可以利用,并扩展节点为您提供了更多的功能利用。
以下是获得了内部的div带class =“信息”每个TextNode对象引用的一个例子。
for(Iterator<Element> elementIt = document.select("div.info").iterator(); elementIt.hasNext();){
Element element = elementIt.next();
for (Iterator<TextNode> textIt = element.textNodes().iterator(); textIt.hasNext();) {
TextNode textNode = textIt.next();
//Do your magic with textNode now.
//You can even reference it's parent via the inherited Node Object's
//method .parent();
}
}
使用这种嵌套迭代器技术,您可以访问对象的所有文本节点,并与一些聪明的逻辑,你可以只是做Jsoup的结构中任何你想要的。
我已经实现这个逻辑,我在过去创造了一个拼写检查方法,它确实有一定的性能影响非常大的HTML文档具有高数量的元素,也许很多表之类的东西。 但如果你的文件是合理的长,你应该得到足够的性能。
以下是获得对文档的每一TextNode对象引用的示例。
Document document = Jsoup.parse(html);
for (Iterator<Element> elementIt = document.body().getAllElements().iterator(); elementIt.hasNext();) {
Element element = elementIt.next();
//Maybe some magic for each element..
for (Iterator<TextNode> textIt = element.textNodes().iterator(); textIt.hasNext();) {
TextNode textNode = textIt.next();
//Lots of magic here for each textNode..
}
}