【实战】Java使用 Jsoup 将浏览器书签 HTML 转换为 JSON(支持多级目录)

一、背景说明

浏览器(Chrome / Edge / Firefox)导出的书签文件,通常是 Netscape Bookmark HTML 格式

在实际开发中,我们可能会遇到以下需求:

  • 将浏览器书签导入到自己的系统
  • 对书签进行结构化存储(如数据库、JSON)
  • 做书签导航站、搜索、同步工具等

本文通过 Jsoup + Fastjson2 ,演示如何将书签 HTML 解析为层级 JSON 结构 ,并支持 递归子目录


二、书签 HTML 格式说明

浏览器导出的书签文件大致结构如下:

html 复制代码
<DL>
  <DT><H3>文件夹</H3>
  <DL>
    <DT><A HREF="https://www.baidu.com/">百度</A>
    <DT><H3>子文件夹</H3>
    <DL>
      <DT><A HREF="https://map.baidu.com/">百度地图</A>
    </DL>
  </DL>
</DL>

关键点:

  • <H3>:表示一个文件夹
  • <A>:表示一个书签链接
  • <DL>:表示当前文件夹的内容
  • 文件夹与其内容是 H3 → 紧跟的 DL

三、技术选型

技术 作用
Jsoup 解析 HTML DOM
Fastjson2 构建 JSON 数据
JUnit + SpringBootTest 测试运行

四、完整示例代码

下面给出 完整可运行代码,包括导入、类定义和递归方法:

java 复制代码
package com.nav.test;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class Bookmark {

    @Test
    public void main() {
        // 模拟浏览器导出的书签 HTML 内容
        String bookmarkContent = "<!DOCTYPE NETSCAPE-Bookmark-file-1>\n" +
                "<!-- This is an automatically generated file. -->\n" +
                "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n" +
                "<TITLE>Bookmarks</TITLE>\n" +
                "<H1>Bookmarks</H1>\n" +
                "<DL><p>\n" +
                "    <DT><H3 ADD_DATE=\"1632971641\" LAST_MODIFIED=\"1689686797\" PERSONAL_TOOLBAR_FOLDER=\"true\">书签栏</H3>\n" +
                "    <DL><p>\n" +
                "        <DT><A HREF=\"https://www.baidu.com/\" ADD_DATE=\"1689686710\">百度一下,你就知道</A>\n" +
                "        <DT><H3 ADD_DATE=\"1689686747\" LAST_MODIFIED=\"1689686798\">子书签</H3>\n" +
                "        <DL><p>\n" +
                "            <DT><A HREF=\"https://map.baidu.com/\" ADD_DATE=\"1689686769\">百度地图</A>\n" +
                "        </DL><p>\n" +
                "    </DL><p>\n" +
                "</DL><p>";

        // 使用 Jsoup 解析 HTML
        Document doc = Jsoup.parse(bookmarkContent);

        // 找到书签栏(Chrome 的 PERSONAL_TOOLBAR_FOLDER)
        Element mainFolder = doc.select("h3[personal_toolbar_folder]").first();

        // 递归处理
        JSONObject result = processFolder(mainFolder);

        // 输出 JSON
        System.out.println(result.toJSONString());
    }

    /**
     * 递归处理文件夹
     *
     * @param folderElement 文件夹对应的 H3 元素
     * @return JSONObject 结构 {name, links, subFolders}
     */
    private static JSONObject processFolder(Element folderElement) {
        JSONObject folderJson = new JSONObject();

        // 文件夹名称
        folderJson.put("name", folderElement.text());

        // 当前文件夹对应的 <DL>
        Element dl = folderElement.nextElementSibling();

        // 当前目录下的链接
        JSONArray links = new JSONArray();
        for (Element a : dl.select("> dt > a")) {
            JSONObject linkJson = new JSONObject();
            linkJson.put("name", a.text());
            linkJson.put("url", a.attr("href"));
            links.add(linkJson);
        }
        folderJson.put("links", links);

        // 子文件夹
        JSONArray subFolders = new JSONArray();
        for (Element h3 : dl.select("> dt > h3")) {
            subFolders.add(processFolder(h3));
        }
        folderJson.put("subFolders", subFolders);

        return folderJson;
    }
}

五、输出 JSON 示例

运行上面的代码,控制台输出类似:

json 复制代码
{
  "name": "书签栏",
  "links": [
    {
      "name": "百度一下,你就知道",
      "url": "https://www.baidu.com/"
    }
  ],
  "subFolders": [
    {
      "name": "子书签",
      "links": [
        {
          "name": "百度地图",
          "url": "https://map.baidu.com/"
        }
      ],
      "subFolders": []
    }
  ]
}

六、实现思路总结

  1. H3 表示文件夹
  2. H3 后面的 DL 是内容
  3. 使用 nextElementSibling() 关联目录
  4. 递归解析子文件夹
  5. 通过 > dt > a> dt > h3 选择器分别获取当前目录的书签和子文件夹
相关推荐
码农的小菜园17 小时前
Java线程池学习笔记
java·笔记·学习
hongtianzai17 小时前
Laravel8.x核心特性全解析
java·c语言·开发语言·golang·php
逸Y 仙X17 小时前
文章十一:ElasticSearch Dynamic Template详解
java·大数据·数据库·elasticsearch·搜索引擎·全文检索
隔壁小邓17 小时前
IDEA 中同时启动多个微服务
java·微服务·intellij-idea
:12117 小时前
idea17创建tomcat项目(计网底层核心理解!)
java·ide·intellij-idea
Brookty17 小时前
网络通信核心:四元组、socket与IO机制详解
java·网络通信·网络入门
佩奇大王17 小时前
P159 摆动序列
java·开发语言·算法
计算机学姐17 小时前
基于SpringBoot的网吧管理系统
java·spring boot·后端·spring·tomcat·intellij-idea·mybatis
Boop_wu17 小时前
[Java EE 进阶] SpringBoot 配置文件全解析:properties 与 yml 的使用(1)
java·spring boot·spring·java-ee
我不是秋秋17 小时前
软件开发项目各角色关系解析:产品/前后端/测试如何高效协作?
java·算法·面试·职场和发展·哈希算法