Java使用Jsoup實(shí)現(xiàn)將瀏覽器書簽HTML轉(zhuǎn)換為JSON
一、背景說(shuō)明
瀏覽器(Chrome / Edge / Firefox)導(dǎo)出的書簽文件,通常是 Netscape Bookmark HTML 格式。
在實(shí)際開(kāi)發(fā)中,我們可能會(huì)遇到以下需求:
- 將瀏覽器書簽導(dǎo)入到自己的系統(tǒng)
- 對(duì)書簽進(jìn)行結(jié)構(gòu)化存儲(chǔ)(如數(shù)據(jù)庫(kù)、JSON)
- 做書簽導(dǎo)航站、搜索、同步工具等
本文通過(guò) Jsoup + Fastjson2,演示如何將書簽 HTML 解析為層級(jí) JSON 結(jié)構(gòu),并支持 遞歸子目錄。
二、書簽 HTML 格式說(shuō)明
瀏覽器導(dǎo)出的書簽文件大致結(jié)構(gòu)如下:
<DL>
<DT><H3>文件夾</H3>
<DL>
<DT><A rel="external nofollow" >百度</A>
<DT><H3>子文件夾</H3>
<DL>
<DT><A rel="external nofollow" >百度地圖</A>
</DL>
</DL>
</DL>
關(guān)鍵點(diǎn):
<H3>:表示一個(gè)文件夾<A>:表示一個(gè)書簽鏈接<DL>:表示當(dāng)前文件夾的內(nèi)容- 文件夾與其內(nèi)容是 H3 → 緊跟的 DL
三、技術(shù)選型
| 技術(shù) | 作用 |
|---|---|
| Jsoup | 解析 HTML DOM |
| Fastjson2 | 構(gòu)建 JSON 數(shù)據(jù) |
| JUnit + SpringBootTest | 測(cè)試運(yùn)行 |
四、完整示例代碼
下面給出 完整可運(yùn)行代碼,包括導(dǎo)入、類定義和遞歸方法:
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() {
// 模擬瀏覽器導(dǎo)出的書簽 HTML 內(nèi)容
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 文件夾對(duì)應(yīng)的 H3 元素
* @return JSONObject 結(jié)構(gòu) {name, links, subFolders}
*/
private static JSONObject processFolder(Element folderElement) {
JSONObject folderJson = new JSONObject();
// 文件夾名稱
folderJson.put("name", folderElement.text());
// 當(dāng)前文件夾對(duì)應(yīng)的 <DL>
Element dl = folderElement.nextElementSibling();
// 當(dāng)前目錄下的鏈接
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 示例
運(yùn)行上面的代碼,控制臺(tái)輸出類似:
{
"name": "書簽欄",
"links": [
{
"name": "百度一下,你就知道",
"url": "https://www.baidu.com/"
}
],
"subFolders": [
{
"name": "子書簽",
"links": [
{
"name": "百度地圖",
"url": "https://map.baidu.com/"
}
],
"subFolders": []
}
]
}
六、實(shí)現(xiàn)思路總結(jié)
- H3 表示文件夾
- H3 后面的 DL 是內(nèi)容
- 使用
nextElementSibling()關(guān)聯(lián)目錄 - 遞歸解析子文件夾
- 通過(guò)
> dt > a和> dt > h3選擇器分別獲取當(dāng)前目錄的書簽和子文件夾
到此這篇關(guān)于Java使用Jsoup實(shí)現(xiàn)將瀏覽器書簽HTML轉(zhuǎn)換為JSON的文章就介紹到這了,更多相關(guān)Java瀏覽器書簽HTML轉(zhuǎn)JSON內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot2如何禁用自帶tomcat的session功能
這篇文章主要介紹了springboot2如何禁用自帶tomcat的session功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringBoot+Hibernate實(shí)現(xiàn)自定義數(shù)據(jù)驗(yàn)證及異常處理
這篇文章主要為大家介紹了SpringBoot如何整合Hibernate自定義數(shù)據(jù)驗(yàn)證及多種方式異常處理,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-04-04
Java遞歸算法經(jīng)典實(shí)例(經(jīng)典兔子問(wèn)題)
本文主要對(duì)經(jīng)典的兔子案例分析,來(lái)進(jìn)一步更好的理解和學(xué)習(xí)java遞歸算法,具有很好的參考價(jià)值,需要的朋友一起來(lái)看下吧2016-12-12
關(guān)于@DS注解切換數(shù)據(jù)源失敗的原因?qū)崙?zhàn)記錄
項(xiàng)目配置了多個(gè)數(shù)據(jù)源,需要使用@DS注解來(lái)切換數(shù)據(jù)源,但是卻遇到了問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于@DS注解切換數(shù)據(jù)源失敗原因的相關(guān)資料,需要的朋友可以參考下2023-05-05
Nacos客戶端配置中心緩存動(dòng)態(tài)更新實(shí)現(xiàn)源碼
這篇文章主要為大家介紹了Nacos客戶端配置中心緩存動(dòng)態(tài)更新實(shí)現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-03-03
Spring Boot 中的自動(dòng)配置autoconfigure詳解
這篇文章主要介紹了Spring Boot 中的自動(dòng)配置autoconfigure詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-01-01

