使用 cheerio 把书签html文件转json数据

209 阅读1分钟

在写个小工具里面要用到上传书签html转为json数据

搜索了一些现成的代码都没看懂所以自己写了下

贴出来代码方便后来人使用

如果对有所帮助,可以点点赞

vue3

<template>
  <div>
    <h1>书签转换器</h1>
    <input type="file" @change="handleFileUpload" />
    <div v-if="error" class="error">{{ error }}</div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, watch, computed } from "vue";
import cheerio from "cheerio";

onMounted(() => {
  // createLeaferApp();
});

const bookmarksArray = ref([]);
const error = ref(null);

const handleFileUpload = (event) => {
  console.log("选择文件", event);
  const file = event.target.files?.[0];
  if (file) {
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        let htmlContent = e.target.result;

        // 解析书签,得到一个数组
        let list = parseBookmarksHtml(htmlContent); // 根据实际HTML结构调整选择器

        // 将数组转换为JSON字符串
        bookmarksArray.value = list[0];
        console.log(list, "bookmarksArray", bookmarksArray.value);
        error.value = null;
      } catch (err) {
        console.log(err);
        error.value = "解析书签时出错";
        bookmarksArray.value = "";
      }
    };
    reader.readAsText(file);
  }
};

function parseBookmarksHtml(html) {
  const $ = cheerio.load(html);
  const result = [];
  const rootDl = $("dl").first();

  if (rootDl.length) {
    result.push(...parseBookmarkNodes($, rootDl, null));
  }

  return result;
}

function parseBookmarkNodes($, parentNode, parentId) {
  const bookmarks = [];
  const $dtElements = $(parentNode).find("> dt");

  $dtElements.each((i, dt) => {
    const $dt = $(dt);
    let bookmarkOrFolder;

    // 优先查找 A 标签,因为书签总是直接链接的形式出现
    const $a = $dt.find("> a");
    if ($a.length) {
      // 存在 A 标签,表示这是一个书签
      const bookmarkId = randomID();
      bookmarkOrFolder = {
        id: bookmarkId,
        parentId,
        title: $a.text().trim(),
        url: $a.attr("href"),
        addDate: $a.attr("add_date"),
        lastModified: $a.attr("last_modified"),
        icon: $a.attr("icon"),
      };
    } else {
      // 没有 A 标签,查找 h3 标签确定是否为文件夹
      const $h3 = $dt.find("> h3");
      if ($h3.length) {
        // 存在 H3 标签,表示这是一个文件夹
        const folderId = randomID();
        const folderName = $h3.text().trim();
        const folder = {
          id: folderId,
          parentId,
          title: folderName,
          children: [],
        };

        // 查找并递归解析文件夹内的 DL 元素
        const subDl = $dt.find("> dl");
        if (subDl.length) {
          folder.children = parseBookmarkNodes($, subDl, folderId);
        }

        bookmarkOrFolder = folder;
      } else {
        // 异常情况:DT 元素中没有 A 或 H3,跳过当前 DT
        console.warn("Skipping DT element without A or H3 tag.");
        return;
      }
    }

    bookmarks.push(bookmarkOrFolder);
  });

  return bookmarks;
}

function randomID() {
  return (
    Math.random().toString(36).substring(2, 15) + Date.now().toString(36)
  ).substring(2, 15);
}
</script>

<style lang="less" scoped></style>