如何用Jsoup提取段落及子标签文本以适配定制化TTS需求?
解决方案:将子标签文本归属到父标签并保留差异化标记
我来帮你搞定这个问题!你当前的代码之所以会把<u>标签的文本单独输出,核心原因有两个:一是用select("*")遍历了所有元素(包括内联子元素),二是ownText()只会返回元素本身的直接文本,不会包含子元素的内容。要实现把子标签文本归属到父标签下,同时还能区分不同部分的文本(方便TTS差异化读取),可以按以下思路调整代码:
核心思路
不要遍历所有元素,而是针对需要作为整体读取的父元素(比如你的<h3>),遍历它的子节点(包括文本节点和元素节点),这样既能收集完整的文本内容,又能标记哪些文本来自内联子元素(比如<u>)。
示例代码1:针对特定父元素(如h3)处理
如果你只需要处理<h3>这类特定标签,可以直接选中它们,然后遍历子节点:
// 选中所有h3元素 Elements headings = doc.select("h3"); for (Element heading : headings) { StringBuilder fullContent = new StringBuilder(); // 遍历h3的所有子节点,区分普通文本和内联元素文本 for (Node node : heading.childNodes()) { if (node instanceof TextNode) { // 处理普通文本节点 String text = ((TextNode) node).text().trim(); if (!text.isEmpty()) { fullContent.append(text).append(" "); // 标记这是普通文本,用于TTS常规读取 Log.d("Epub", "h3 [普通文本]: " + text); } } else if (node instanceof Element) { Element childElement = (Element) node; String childText = childElement.text().trim(); if (!childText.isEmpty()) { fullContent.append(childText).append(" "); // 标记这是内联子元素的文本,用于TTS差异化读取 Log.d("Epub", "h3 [内联元素<" + childElement.tagName() + ">]: " + childText); } } } // 输出h3的完整内容,方便整体查看 Log.d("Epub", "h3 完整内容: " + fullContent.toString().trim()); }
日志输出效果
h3 [普通文本]: Title h3 [内联元素<u>]: Page h3 [普通文本]: by Ada Lovelace h3 完整内容: Title Page by Ada Lovelace
这样所有文本都归属到<h3>下,同时你能清晰区分哪些是普通文本、哪些是内联子元素的文本,完全满足TTS差异化读取的需求。
示例代码2:全局处理(自动跳过内联元素)
如果你需要处理整个文档的所有元素,希望自动跳过<u>、<span>这类内联标签(不单独输出它们的文本),可以先定义内联标签集合,再过滤遍历:
// 定义需要跳过的内联标签(根据你的需求扩展) Set<String> inlineTags = new HashSet<>(Arrays.asList("u", "span", "em", "strong")); Elements allElements = doc.body().select("*"); for (Element element : allElements) { // 如果是内联标签,直接跳过,文本交给父元素处理 if (inlineTags.contains(element.tagName())) { continue; } if (element.hasText()) { StringBuilder fullContent = new StringBuilder(); // 遍历当前元素的子节点,收集并标记文本 for (Node node : element.childNodes()) { if (node instanceof TextNode) { String text = ((TextNode) node).text().trim(); if (!text.isEmpty()) { fullContent.append(text).append(" "); Log.d("Epub", element.tagName() + " [普通文本]: " + text); } } else if (node instanceof Element) { Element child = (Element) node; if (inlineTags.contains(child.tagName())) { String childText = child.text().trim(); if (!childText.isEmpty()) { fullContent.append(childText).append(" "); Log.d("Epub", element.tagName() + " [内联元素<" + child.tagName() + ">]: " + childText); } } } } Log.d("Epub", element.tagName() + " 完整内容: " + fullContent.toString().trim()); } }
为什么原来的代码不行?
select("*")会选中页面上的所有元素,包括<h3>的子元素<u>,导致子元素被单独遍历输出。ownText()方法仅返回元素本身的直接文本,不包含子元素的内容,所以<h3>的ownText()是Title by Ada Lovelace,而<u>的ownText()是Page,最终分开输出。
内容的提问来源于stack exchange,提问作者Ninad Naik
相关产品推荐
相关产品推荐

