2026/3/3 2:25:59
网站建设
项目流程
广西建设厅网站彭新唐,设计师网站导航青年帮,网络营销推广的概念,重庆产品推广类网站一、背景说明
浏览器#xff08;Chrome / Edge / Firefox#xff09;导出的书签文件#xff0c;通常是 Netscape Bookmark HTML 格式。 在实际开发中#xff0c;我们可能会遇到以下需求#xff1a;
将浏览器书签导入到自己的系统对书签进行结构化存储#xff08;如数据…一、背景说明浏览器Chrome / Edge / Firefox导出的书签文件通常是Netscape Bookmark HTML 格式。在实际开发中我们可能会遇到以下需求将浏览器书签导入到自己的系统对书签进行结构化存储如数据库、JSON做书签导航站、搜索、同步工具等本文通过Jsoup Fastjson2演示如何将书签 HTML解析为层级 JSON 结构并支持递归子目录。二、书签 HTML 格式说明浏览器导出的书签文件大致结构如下DLDTH3文件夹/H3DLDTAHREFhttps://www.baidu.com/百度/ADTH3子文件夹/H3DLDTAHREFhttps://map.baidu.com/百度地图/A/DL/DL/DL关键点H3表示一个文件夹A表示一个书签链接DL表示当前文件夹的内容文件夹与其内容是H3 → 紧跟的 DL三、技术选型技术作用Jsoup解析 HTML DOMFastjson2构建 JSON 数据JUnit SpringBootTest测试运行四、完整示例代码下面给出完整可运行代码包括导入、类定义和递归方法packagecom.nav.test;importcom.alibaba.fastjson2.JSONArray;importcom.alibaba.fastjson2.JSONObject;importorg.jsoup.Jsoup;importorg.jsoup.nodes.Document;importorg.jsoup.nodes.Element;importorg.jsoup.select.Elements;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;SpringBootTestRunWith(SpringRunner.class)publicclassBookmark{Testpublicvoidmain(){// 模拟浏览器导出的书签 HTML 内容StringbookmarkContent!DOCTYPE NETSCAPE-Bookmark-file-1\n!-- This is an automatically generated file. --\nMETA HTTP-EQUIV\Content-Type\ CONTENT\text/html; charsetUTF-8\\nTITLEBookmarks/TITLE\nH1Bookmarks/H1\nDLp\n DTH3 ADD_DATE\1632971641\ LAST_MODIFIED\1689686797\ PERSONAL_TOOLBAR_FOLDER\true\书签栏/H3\n DLp\n DTA HREF\https://www.baidu.com/\ ADD_DATE\1689686710\百度一下你就知道/A\n DTH3 ADD_DATE\1689686747\ LAST_MODIFIED\1689686798\子书签/H3\n DLp\n DTA HREF\https://map.baidu.com/\ ADD_DATE\1689686769\百度地图/A\n /DLp\n /DLp\n/DLp;// 使用 Jsoup 解析 HTMLDocumentdocJsoup.parse(bookmarkContent);// 找到书签栏Chrome 的 PERSONAL_TOOLBAR_FOLDERElementmainFolderdoc.select(h3[personal_toolbar_folder]).first();// 递归处理JSONObjectresultprocessFolder(mainFolder);// 输出 JSONSystem.out.println(result.toJSONString());}/** * 递归处理文件夹 * * param folderElement 文件夹对应的 H3 元素 * return JSONObject 结构 {name, links, subFolders} */privatestaticJSONObjectprocessFolder(ElementfolderElement){JSONObjectfolderJsonnewJSONObject();// 文件夹名称folderJson.put(name,folderElement.text());// 当前文件夹对应的 DLElementdlfolderElement.nextElementSibling();// 当前目录下的链接JSONArraylinksnewJSONArray();for(Elementa:dl.select( dt a)){JSONObjectlinkJsonnewJSONObject();linkJson.put(name,a.text());linkJson.put(url,a.attr(href));links.add(linkJson);}folderJson.put(links,links);// 子文件夹JSONArraysubFoldersnewJSONArray();for(Elementh3:dl.select( dt h3)){subFolders.add(processFolder(h3));}folderJson.put(subFolders,subFolders);returnfolderJson;}}五、输出 JSON 示例运行上面的代码控制台输出类似{name:书签栏,links:[{name:百度一下你就知道,url:https://www.baidu.com/}],subFolders:[{name:子书签,links:[{name:百度地图,url:https://map.baidu.com/}],subFolders:[]}]}六、实现思路总结H3 表示文件夹H3 后面的 DL 是内容使用nextElementSibling()关联目录递归解析子文件夹通过 dt a和 dt h3选择器分别获取当前目录的书签和子文件夹