You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:51:21