HTML文档大纲提取

本文档介绍了如何使用Jsoup和SnakeYAML库从语雀API获取HTML内容并解析文档大纲。通过递归方法,实现了将HTML头标签转换为大纲目录,并以O(n-1)²的时间复杂度提取目录结构。最后,文章提供了相关依赖及关键代码示例。
摘要由CSDN通过智能技术生成

前言

        最近公司要做新版的帮助中心文档展示(开发文档、用户帮助文档),叫我来调研技术方案。要以最低成本最快时间完成。由于公司给用户的帮助文档之前都维护在语雀中,考虑到迁移成本和时间成本,优先考虑接入语雀Api完成需求。但是发现语雀只支持返回htmlmarkdown源码,没有文档大纲的数据。所以需要我们的后端开发同学来提取大纲的数据,在github上找到了两三个相关项目代码,但都是以python实现的,代码很乱,也没有耐心去阅读实现思路。在此记录一下实现过程。

正文

        功能实现大致流程如下:

        运营人员在语雀编写文档->从语雀获取文档目录和html信息->解析大纲数据->存储至文件系统

以下为语雀官方Api文档。

Doc - 文档 · 语雀获取一个仓库的文档列表GET /repos/:name...https://www.yuque.com/yuque/developer/doc

 HTML大纲提取测试地址HTML 5 Outlinerhttps://gsnedders.html5.org/outliner/

 使用到的包:

        <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
        <!-- jsoup是Java爬虫使用解析html的工具包。-->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.15.3</version>
        </dependency>
        
        <!-- 解析yaml文档或文本的工具包,语雀返回的知识库目录格式为yaml文档 -->
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.26</version>
        </dependency>

提取HTML目录大纲代码,使用递归,时间复杂度为O(n-1)2

   /**
     * @desc 获取html大纲目录
     * @author Liangwz
     * @date 2022/9/2 14:20
     * @param html html body代码
     * @return java.util.List<DocLinkDto>
     */
    private List<DocLinkDto> getLinkNodes(String html) {
        if (StringUtils.isBlank(html)) {
            return new ArrayList<>();
        }
        //解析html
        Document document = Jsoup.parseBodyFragment(html);
        Elements allResult = new Elements();
        //获取所有H标签集合
        for (int i = 1; i < 7; i++) {
            allResult.addAll(document.getElementsByTag("h"+i));
        }
        //按照标签位置先后排序
        allResult = allResult.stream().sorted(Comparator.comparing(Node::siblingIndex)).collect(Collectors.toCollection(Elements::new));
1       //提取大纲信息返回
        return getLinkNodes(allResult);
    }


    /**
     * @desc 获取html大纲目录
     * @author Liangwz
     * @date 2022/9/2 14:20
     * @param allTag h标签集合
     * @return java.util.List<DocLinkDto>
     */       
    private static List<DocLinkDto> getLinkNodes(Elements allTag) {
        List<DocLinkDto> result = new ArrayList<>();
        for (int i = 0; i < allTag.size(); i++) {
            Element elementI = allTag.get(i);
            Integer hTagNumI = getHTagNum(elementI.tagName());
            //获取子区间集合
            Elements childrenElements = new Elements();
            for (int j = i + 1; j < allTag.size(); j++) {
                Element elementJ = allTag.get(j);
                if (getHTagNum(allTag.get(j).tagName()) <= hTagNumI) {
                    break;
                }
                i = j;
                childrenElements.add(elementJ);
            }
            DocLinkDto linkDto = new DocLinkDto(elementI.text(), "#" + elementI.id(), elementI.tagName(), new ArrayList<>());
            if (childrenElements.isEmpty()) {
                result.add(linkDto);
                continue;
            } else {
                //递归获取子节点
                linkDto.setChildren(getLinkNodes(childrenElements));
            }
            result.add(linkDto);
        }
        return result;
    }

    /**
     * @desc 获取html h标签级别
     * @author Liangwz
     * @date 2022/9/2 14:19 
     * @param tagName
     * @return java.lang.Integer
     */       
    private static Integer getHTagNum(String tagName) {
        return Integer.valueOf(tagName.replace("h", ""));
    }



import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

/**
 * 类 名 称:LinkDto
 * 类 描 述:文档大纲节点信息
 * 创建时间:2022/9/1 19:26
 * 创 建 人:liangwz
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DocLinkDto implements Serializable {

    //标题
    private String title;
    //路径
    private String href;
    //类型(h1,h2,h3...)
    private String type;
    //子节点
    private List<DocLinkDto> children;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值