【chrome插件】只需一键,浏览器的书签信息就可以导出成为CSV了

源码地址:
https://gitee.com/lineuman/lcs_ext_demos.git

如果有用记得关注我哦,下次继续,不迷路~~~~

如何将浏览器书签导出为 CSV 文件:一步步教你制作 Chrome 插件

在日常上网过程中,我们常常会收藏大量的网页书签,以便日后查阅。例如我的浏览器已经保存了大概1500个的网页书签。

然而,浏览器默认的书签管理功能可能无法满足我们的一些特殊需求,比如批量导出书签信息、进行离线备份或在其他应用中使用。如果您想将浏览器的书签导出为 CSV 文件,以便在 Excel 等工具中查看和管理,那么本文将详细介绍如何通过编写一个 Chrome 插件来实现这一目标。

前言

本文将指导您一步步制作一个 Chrome 插件,实现以下功能:

  • 一键获取所有浏览器收藏的网址。
  • 将书签信息(标题、URL、文件夹路径、添加日期)导出为 CSV 文件。
  • 在插件的选项页面预览书签信息。
  • 通过悬浮按钮,随时导出书签 CSV 文件。

无论您是否有编程经验,都可以按照本文的指导完成插件的制作。



准备工作

在开始之前,您需要:

  • 基本的编程知识:了解 HTML、CSS 和 JavaScript 的基础语法。
  • Chrome 浏览器:本文以 Chrome 浏览器为例,其他基于 Chromium 的浏览器可能也适用。
  • 文本编辑器 :推荐使用 VS Code、Sublime Text 等。
    当然了,即使这些信息你都不会也没关系。

创建项目结构

首先,在您的电脑上创建一个新的文件夹,用于存放插件的文件。您可以将其命名为 bookmark_exporter。在该文件夹中,创建以下文件和文件夹:

  • manifest.json:插件的配置文件。
  • popup.html:插件弹出页面的 HTML 文件。
  • popup.js:弹出页面的 JavaScript 文件。
  • options.html:插件选项页面的 HTML 文件。
  • options.js:选项页面的 JavaScript 文件。
  • icons 文件夹(可选):存放插件的图标。我就没有用到icons

项目结构如下:

bookmark_exporter/
├── manifest.json
├── popup.html
├── popup.js
├── options.html
├── options.js

编写 manifest.json

manifest.json 是 Chrome 插件的配置文件,用于描述插件的基本信息和权限。

manifest.json 中输入以下内容:

json 复制代码
{
  "manifest_version": 3,
  "name": "书签导出工具",
  "version": "1.0",
  "description": "一键获取所有浏览器收藏的网址,并导出为 CSV 文件",
  "permissions": ["bookmarks"],
  "action": {
    "default_popup": "popup.html",
    "
  },
  "options_page": "options.html"
}

说明:

  • "manifest_version": 3:指定使用 Manifest V3 版本。
  • "permissions": ["bookmarks"]:声明插件需要访问书签的权限。
  • "action":定义插件的图标和弹出页面。
  • "options_page": "options.html":指定插件的选项页面。

制作弹出页面 popup.htmlpopup.js

弹出页面是用户点击插件图标时显示的界面。

编写 popup.html

创建 popup.html 文件,输入以下内容:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>书签导出工具</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            width: 300px;
            margin: 0;
            padding: 10px;
        }
        button {
            width: 100%;
            padding: 10px;
            font-size: 16px;
            cursor: pointer;
            margin-bottom: 5px;
        }
        #bookmarkList {
            margin-top: 10px;
            max-height: 400px;
            overflow-y: auto;
            list-style: none;
            padding: 0;
        }
        #bookmarkList li {
            margin-bottom: 5px;
        }
        #bookmarkList a {
            text-decoration: none;
            color: #0066cc;
        }
        #bookmarkList a:hover {
            text-decoration: underline;
        }
    </style>
</head>
<body>
    <button id="exportBtn">导出所有书签网址</button>
    <button id="exportCSVBtn">导出书签为CSV文件</button>
    <ul id="bookmarkList"></ul>
    <script src="popup.js"></script>
</body>
</html>

编写 popup.js

创建 popup.js 文件,输入以下内容:

javascript 复制代码
document.addEventListener('DOMContentLoaded', function() {
  // 导出所有书签网址并显示在列表中
  document.getElementById('exportBtn').addEventListener('click', function() {
      chrome.bookmarks.getTree(function(bookmarkTreeNodes) {
          let bookmarkList = document.getElementById('bookmarkList');
          bookmarkList.innerHTML = ''; // 清空列表
          processBookmarks(bookmarkTreeNodes, bookmarkList);
      });
  });
  
  // 导出书签为CSV文件
  document.getElementById('exportCSVBtn').addEventListener('click', exportBookmarksAsCSV);
});

// 递归遍历书签树,将书签显示在列表中
function processBookmarks(bookmarks, parentElement) {
  for (let bookmark of bookmarks) {
      if (bookmark.url) {
          let li = document.createElement('li');
          let a = document.createElement('a');
          a.href = bookmark.url;
          a.textContent = bookmark.title || bookmark.url;
          a.target = '_blank';
          li.appendChild(a);
          parentElement.appendChild(li);
      }
      if (bookmark.children) {
          processBookmarks(bookmark.children, parentElement);
      }
  }
}

// 导出书签为CSV文件的函数
function exportBookmarksAsCSV() {
  chrome.bookmarks.getTree(function(bookmarkTreeNodes) {
      let rows = [];
      // 添加CSV的表头
      rows.push(['标题', 'URL', '文件夹路径', '添加日期'].join(','));
      collectBookmarkData(bookmarkTreeNodes, rows, '');
      let csvContent = rows.join('\n');
      let blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
      let url = URL.createObjectURL(blob);
      let link = document.createElement('a');
      let currentDate = new Date().toISOString().slice(0,10);
      link.download = `Bookmarks_${currentDate}.csv`;
      link.href = url;
      link.style.display = 'none';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
  });
}

// 递归遍历书签树,收集书签数据
function collectBookmarkData(bookmarks, rows, parentFolder) {
  for (let bookmark of bookmarks) {
      // 更新当前的文件夹路径
      let currentFolder = parentFolder;
      if (bookmark.title && !bookmark.url) {
          // 这是一个文件夹,更新路径
          currentFolder = parentFolder ? parentFolder + '/' + bookmark.title : bookmark.title;
      }

      if (bookmark.url) {
          let title = '"' + (bookmark.title.replace(/"/g, '""') || '') + '"';
          let url = '"' + bookmark.url.replace(/"/g, '""') + '"';
          let dateAdded = bookmark.dateAdded ? new Date(bookmark.dateAdded).toLocaleString() : '';
          let folderPath = '"' + (currentFolder.replace(/"/g, '""') || '') + '"';
          let row = [title, url, folderPath, dateAdded].join(',');
          rows.push(row);
      }

      if (bookmark.children) {
          collectBookmarkData(bookmark.children, rows, currentFolder);
      }
  }
}

添加 Options 页面预览书签信息

选项页面用于在导出 CSV 之前,预览所有的书签信息。

编写 options.html

创建 options.html 文件,输入以下内容:

html 复制代码
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>书签预览</title>
    <style>
        /* 添加 body 的底部填充,防止内容被按钮遮挡 */
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 10px;
            padding-bottom: 80px;
            /* 添加底部填充 */
        }

        #bookmarkTable {
            width: 100%;
            border-collapse: collapse;
        }

        #bookmarkTable th,
        #bookmarkTable td {
            border: 1px solid #ccc;
            padding: 8px;
            text-align: left;
        }

        #bookmarkTable th {
            background-color: #f2f2f2;
        }

        #exportCSVBtn {
            position: fixed;
            top: 20px;
            right: 200px;
            padding: 15px 20px;
            font-size: 16px;
            cursor: pointer;
            background-color: #007BFF;
            /* 按钮背景色 */
            color: white;
            /* 按钮文字颜色 */
            border: none;
            border-radius: 5px;
            /* 圆角 */
            box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3);
            /* 阴影效果 */
        }

        #exportCSVBtn:hover {
            background-color: #0056b3;
            /* 悬停时的背景色 */
        }
    </style>
</head>

<body>
    <h1>书签预览</h1>
    <button id="exportCSVBtn">导出书签为 CSV 文件</button>

    <table id="bookmarkTable">
        <thead>
            <tr>
                <th>标题</th>
                <th>URL</th>
                <th>文件夹路径</th>
                <th>添加日期</th>
            </tr>
        </thead>
        <tbody id="bookmarkBody">
            <!-- 书签数据将被插入到这里 -->
        </tbody>
    </table>
    <script src="options.js"></script>
</body>

</html>

编写 options.js

创建 options.js 文件,输入以下内容:

javascript 复制代码
document.addEventListener('DOMContentLoaded', function() {
    // 获取书签并显示在表格中
    chrome.bookmarks.getTree(function(bookmarkTreeNodes) {
        let bookmarkBody = document.getElementById('bookmarkBody');
        bookmarkBody.innerHTML = ''; // 清空表格
        collectBookmarkData(bookmarkTreeNodes, bookmarkBody, '');
    });

    // 添加导出 CSV 的功能
    document.getElementById('exportCSVBtn').addEventListener('click', exportBookmarksAsCSV);
});

// 递归遍历书签树,收集书签数据并显示在表格中
function collectBookmarkData(bookmarks, tableBody, parentFolder) {
    for (let bookmark of bookmarks) {
        // 更新当前的文件夹路径
        let currentFolder = parentFolder;
        if (bookmark.title && !bookmark.url) {
            // 这是一个文件夹,更新路径
            currentFolder = parentFolder ? parentFolder + '/' + bookmark.title : bookmark.title;
        }

        if (bookmark.url) {
            let row = tableBody.insertRow();
            let titleCell = row.insertCell(0);
            let urlCell = row.insertCell(1);
            let folderCell = row.insertCell(2);
            let dateCell = row.insertCell(3);

            titleCell.textContent = bookmark.title || '';
            urlCell.innerHTML = `<a href="${bookmark.url}" target="_blank">${bookmark.url}</a>`;
            folderCell.textContent = currentFolder || '';
            dateCell.textContent = bookmark.dateAdded ? new Date(bookmark.dateAdded).toLocaleString() : '';
        }

        if (bookmark.children) {
            collectBookmarkData(bookmark.children, tableBody, currentFolder);
        }
    }
}

// 导出书签为 CSV 文件的函数
function exportBookmarksAsCSV() {
    chrome.bookmarks.getTree(function(bookmarkTreeNodes) {
        let rows = [];
        // 添加 CSV 的表头
        rows.push(['标题', 'URL', '文件夹路径', '添加日期'].join(','));
        collectBookmarkDataForCSV(bookmarkTreeNodes, rows, '');
        let csvContent = rows.join('\n');
        let blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
        let url = URL.createObjectURL(blob);
        let link = document.createElement('a');
        let currentDate = new Date().toISOString().slice(0,10);
        link.download = `Bookmarks_${currentDate}.csv`;
        link.href = url;
        link.style.display = 'none';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    });
}

// 递归遍历书签树,收集书签数据用于 CSV 导出
function collectBookmarkDataForCSV(bookmarks, rows, parentFolder) {
    for (let bookmark of bookmarks) {
        // 更新当前的文件夹路径
        let currentFolder = parentFolder;
        if (bookmark.title && !bookmark.url) {
            // 这是一个文件夹,更新路径
            currentFolder = parentFolder ? parentFolder + '/' + bookmark.title : bookmark.title;
        }

        if (bookmark.url) {
            let title = '"' + (bookmark.title.replace(/"/g, '""') || '') + '"';
            let url = '"' + bookmark.url.replace(/"/g, '""') + '"';
            let dateAdded = bookmark.dateAdded ? new Date(bookmark.dateAdded).toLocaleString() : '';
            let folderPath = '"' + (currentFolder.replace(/"/g, '""') || '') + '"';
            let row = [title, url, folderPath, dateAdded].join(',');
            rows.push(row);
        }

        if (bookmark.children) {
            collectBookmarkDataForCSV(bookmark.children, rows, currentFolder);
        }
    }
}

实现书签导出为 CSV 文件功能

在上述代码中,已经实现了将书签导出为 CSV 文件的功能。以下是关键点:

  • 书签数据收集:通过递归遍历书签树,收集每个书签的标题、URL、文件夹路径和添加日期。
  • CSV 格式处理:为了确保 CSV 格式正确,对标题、URL 和文件夹路径中的双引号进行了转义,并用双引号包裹字段。
  • 文件下载 :使用 Blob 对象创建 CSV 文件的数据,并利用 URL.createObjectURL 生成下载链接,模拟点击实现文件下载。


加载并测试插件

  1. 打开扩展程序页面

    在 Chrome 浏览器中,输入 chrome://extensions/ 并回车。

  2. 开启开发者模式

    页面右上角有一个"开发者模式"的开关,开启它。

  3. 加载已解压的扩展程序

    点击左上角的"加载已解压的扩展程序"按钮,选择您的项目文件夹 bookmark_exporter

  4. 测试插件功能

    • 点击浏览器右上角的插件图标,打开弹出页面,尝试导出书签列表或打开预览页面。
    • 在弹出页面中,点击"打开书签预览页面"按钮,进入 Options 页面,预览所有书签信息。
    • 在 Options 页面中,点击"导出书签为 CSV 文件"按钮,测试导出功能。
  5. 检查导出的 CSV 文件

    • 使用 Excel、Notepad++、Google Sheets 等工具打开导出的 CSV 文件。
    • 确认书签的标题、URL、文件夹路径和添加日期是否正确。

总结

通过本文的介绍,您已经学会了如何制作一个 Chrome 插件,实现浏览器书签导出为 CSV 文件的功能。这个插件可以帮助您更好地管理书签,进行数据备份,或在其他场景中利用书签数据。


常见问题

1. 插件无法加载或运行?

  • 确认 manifest.json 的格式正确,注意 JSON 文件不能有注释,属性间需要用逗号隔开。
  • 检查文件名和路径是否正确,尤其是引用的脚本和样式文件。

2. 导出的 CSV 文件乱码?

  • 确认在创建 Blob 对象时,指定了 charset=utf-8{ type: 'text/csv;charset=utf-8;' }
  • 打开 CSV 文件时,选择正确的编码格式。

3. 书签信息不完整或缺失?

  • 检查代码中是否正确地递归遍历了书签树。
  • 确认书签中是否存在特殊字符,必要时进行调试。

4. 如何自定义导出的字段或格式?

  • 可以在代码中修改 collectBookmarkDataForCSV 函数,添加或删除需要的字段。
  • 调整日期格式,使用自定义的日期格式化。

拓展阅读


希望本篇教程对您有所帮助,如果您有任何疑问或建议,欢迎在下方留言讨论!如果对你有帮助,请关注支持一下~

相关推荐
小马哥编程7 小时前
原型链(Prototype Chain)入门
css·vue.js·chrome·node.js·原型模式·chrome devtools
金创想13 小时前
chrome主页被被篡改的修复方法
chrome·主页篡改
东方隐侠安全团队-千里14 小时前
网安瞭望台第17期:Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析
网络·chrome·web安全
m0_7482370515 小时前
Chrome 关闭自动添加https
前端·chrome
张声录11 天前
【ETCD】【实操篇(三)】【ETCDCTL】如何向集群中写入数据
数据库·chrome·etcd
m0_748240021 天前
Chromium 中chrome.webRequest扩展接口定义c++
网络·c++·chrome
冬天vs不冷1 天前
Linux用户与权限管理详解
linux·运维·chrome
SimonLiu0092 天前
[AI]30分钟用cursor开发一个chrome插件
chrome·ai·ai编程
守城小轩2 天前
Chromium GN目标指南 - 查看GN目标(三)
chrome·chrome devtools·指纹浏览器·浏览器开发
守城小轩3 天前
Chromium CDP 开发(八):测试自定义的CDP指令
chrome·chrome devtools·指纹浏览器·浏览器开发