Buku 书签管理完全指南 / 第 06 章:导入导出
第 06 章:导入导出
学习在不同格式和平台之间迁移书签数据,实现数据的自由流动。
6.1 导入概览
Buku 支持多种导入格式,方便从其他工具或浏览器迁移书签数据。
支持的导入格式
| 格式 | 命令 | 来源 | 说明 |
|---|
| HTML | buku -i file.html | 浏览器导出 | Netscape Bookmark 标准格式 |
| Markdown | buku -i file.md | 手动整理 | 支持特定 Markdown 格式 |
| Org | buku -i file.org | Emacs Org-mode | Org 格式书签 |
| XBEL | buku -i file.xbel | 部分浏览器 | XML Bookmark Exchange Language |
| JSON | buku -i file.json | Buku 自身导出 | Buku 原生 JSON 格式 |
| SQLite | 手动导入 | Buku 数据库 | 直接复制数据库文件 |
导入命令
# 基本导入
buku -i bookmarks.html
# 导入时自动获取缺失的标题
buku -a -i bookmarks.html # 仅在添加新书签时获取标题
# 导入后验证
buku -p | tail -20 # 查看最后导入的书签
6.2 从浏览器导入
从 Chrome 导出
# Chrome 导出步骤:
# 1. 打开 Chrome 浏览器
# 2. 点击右上角三点菜单 → 书签 → 书签管理器
# 3. 点击右上角三点菜单 → 导出书签
# 4. 保存为 HTML 文件
# 导入到 Buku
buku -i ~/Downloads/chrome_bookmarks.html
# 验证导入
buku -p | head -20
echo "导入书签数: $(buku -p | grep -c '^[0-9]')"
从 Firefox 导出
# Firefox 导出步骤:
# 1. 打开 Firefox 浏览器
# 2. 点击书签按钮 → 管理书签(Ctrl+Shift+O)
# 3. 点击导入和备份 → 导出书签到 HTML
# 4. 保存为 HTML 文件
# 导入到 Buku
buku -i ~/Downloads/firefox_bookmarks.html
从 Edge 导出
# Edge 导出步骤:
# 1. 打开 Edge 浏览器
# 2. 点击三点菜单 → 收藏夹
# 3. 点击三点菜单 → 导出收藏夹
# 4. 保存为 HTML 文件
# 导入到 Buku
buku -i ~/Downloads/edge_bookmarks.html
从 Safari 导出
# Safari 导出步骤:
# 1. 打开 Safari
# 2. 菜单栏 → 文件 → 导出 → 书签
# 3. 保存为 HTML 文件
# 导入到 Buku
buku -i ~/Downloads/safari_bookmarks.html
各浏览器导出格式对比
| 浏览器 | 导出格式 | 标签支持 | 文件夹转换 | 备注 |
|---|
| Chrome | HTML | ❌ | ✅ 文件夹转标签 | 最通用 |
| Firefox | HTML | ❌ | ✅ 文件夹转标签 | 支持完整导出 |
| Edge | HTML | ❌ | ✅ 文件夹转标签 | 兼容 Chrome |
| Safari | HTML | ❌ | ✅ 文件夹转标签 | 基本支持 |
6.3 从其他工具导入
从 Pinboard 导入
# Pinboard 导出步骤:
# 1. 登录 https://pinboard.in
# 2. 访问 https://pinboard.in/export/
# 3. 选择格式 → 导出所有书签
# 4. 下载 JSON 或 HTML 文件
# 导入 HTML 格式
buku -i pinboard_export.html
# 导入 JSON 格式(需要预处理)
# Pinboard JSON 格式与 Buku 不同,需要转换
python3 << 'EOF'
import json
with open('pinboard_export.json', 'r') as f:
bookmarks = json.load(f)
with open('buku_import.txt', 'w') as f:
for bm in bookmarks:
url = bm.get('href', '')
title = bm.get('description', '')
tags = ','.join(bm.get('tags', []))
if tags:
tags = ',' + tags + ','
f.write(f"{url} {title} {tags}\n")
EOF
# 使用转换后的文件批量导入
while IFS=' ' read -r url title tags; do
buku -a "$url" "$title" "$tags"
done < buku_import.txt
从 Raindrop.io 导入
# Raindrop.io 导出步骤:
# 1. 登录 https://raindrop.io
# 2. 设置 → 导出 → 选择 HTML 格式
# 3. 下载导出文件
# 导入到 Buku
buku -i raindrop_export.html
从 Pocket 导入
# Pocket 导出步骤:
# 1. 访问 https://getpocket.com/export
# 2. 导出为 HTML 文件
# 导入到 Buku
buku -i pocket_export.html
# Pocket 导出的 HTML 格式可能需要额外处理
# 如果导入失败,手动转换格式
从 Linkding 导入
# Linkding 导出步骤:
# 1. 登录 Linkding Web 界面
# 2. 设置 → 导出 → Netscape HTML
# 导入到 Buku
buku -i linkding_export.html
# 或使用 Linkding API 获取数据
curl -H "Authorization: Token YOUR_TOKEN" \
http://localhost:9090/api/bookmarks/ | \
python3 -c "
import json, sys
data = json.load(sys.stdin)
for bm in data.get('results', []):
url = bm.get('url', '')
title = bm.get('title', '')
tags = ','.join([',' + t['name'] for t in bm.get('tag_items', [])])
print(f'{url}\t{title}\t{tags}')
" > linkding_bookmarks.tsv
# 批量导入
while IFS=$'\t' read -r url title tags; do
buku -a "$url" "$title" "$tags"
done < linkding_bookmarks.tsv
从 Shiori 导入
# Shiori 数据库位于 SQLite 中
# 直接使用 SQL 提取数据
sqlite3 ~/.local/share/shiori/shiori.db << 'EOF'
.mode tabs
.output shiori_bookmarks.tsv
SELECT url, title, '' FROM bookmark;
.output stdout
EOF
# 导入到 Buku
while IFS=$'\t' read -r url title tags; do
buku -a "$url" "$title"
done < shiori_bookmarks.tsv
6.4 导出格式
导出为 HTML
# 导出所有书签为 HTML(浏览器可导入格式)
buku -e bookmarks.html
# 导出特定书签
buku -e selected.html 1-10 # 导出第 1-10 条
buku -e python_bookmarks.html -s python # 导出搜索结果
# HTML 导出格式说明
# Buku 导出的 HTML 使用 Netscape Bookmark File Format
# 可直接导入 Chrome、Firefox、Edge 等浏览器
导出为 Markdown
# 导出为 Markdown 格式
buku -e bookmarks.md
# Markdown 输出示例:
# - [Buku 项目](https://github.com/jarun/buku)
# - [Python 文档](https://docs.python.org)
# - [Rust 语言](https://www.rust-lang.org)
导出为 Org 格式
# 导出为 Emacs Org-mode 格式
buku -e bookmarks.org
# Org 输出示例:
# * Bookmarks
# ** [[https://github.com/jarun/buku][Buku 项目]]
# ** [[https://docs.python.org][Python 文档]]
导出为 JSON
# 使用内置 JSON 输出
buku -j > bookmarks.json
# JSON 结构示例:
# [
# {
# "id": 1,
# "url": "https://github.com/jarun/buku",
# "metadata": "Buku 项目",
# "tags": ",bookmark,cli,python,",
# "description": ""
# }
# ]
# 导出为格式化 JSON
buku -j | python3 -m json.tool > bookmarks_formatted.json
导出为 XBEL
# Buku 不直接支持 XBEL 导出
# 需要通过 HTML 间接转换
# 先导出为 HTML
buku -e bookmarks.html
# 然后使用工具转换为 XBEL
# (XBEL 是一种较少使用的格式,主要用于部分浏览器)
导出格式对比
| 格式 | 命令 | 浏览器可导入 | 人类可读 | 脚本处理 | 标签信息 |
|---|
| HTML | buku -e file.html | ✅ | 中 | 中 | 有限 |
| Markdown | buku -e file.md | ❌ | ✅ 高 | 高 | ❌ |
| Org | buku -e file.org | ❌ | ✅ 高 | 高 | ❌ |
| JSON | buku -j > file.json | ❌ | 中 | ✅ 最佳 | ✅ 完整 |
| TSV | buku -f 5 | ❌ | 中 | ✅ 高 | ✅ |
6.5 浏览器迁移
从 Chrome 完全迁移到 Buku
#!/bin/bash
# chrome_to_buku.sh - 从 Chrome 完全迁移书签
echo "=== Chrome → Buku 迁移工具 ==="
echo ""
# 步骤 1:导出 Chrome 书签
echo "请先从 Chrome 导出书签:"
echo " 1. 打开 Chrome → 书签 → 书签管理器"
echo " 2. 点击 ⋮ → 导出书签"
echo " 3. 保存为 chrome_bookmarks.html"
echo ""
read -p "输入导出文件路径: " chrome_file
if [ ! -f "$chrome_file" ]; then
echo "文件不存在: $chrome_file"
exit 1
fi
# 步骤 2:备份当前 Buku 数据库
backup_file="$HOME/.local/share/buku/bookmarks_backup_$(date +%Y%m%d_%H%M%S).db"
cp ~/.local/share/buku/bookmarks.db "$backup_file" 2>/dev/null
echo "已备份当前数据库: $backup_file"
# 步骤 3:导入书签
echo "正在导入书签..."
buku -i "$chrome_file"
# 步骤 4:验证
imported=$(buku -p | grep -c "^[0-9]")
echo "导入完成!当前总书签数: $imported"
# 步骤 5:提示
echo ""
echo "建议操作:"
echo " 1. 检查导入结果: buku -p | head -30"
echo " 2. 为书签添加标签"
echo " 3. 删除不需要的书签"
从 Firefox 完全迁移到 Buku
#!/bin/bash
# firefox_to_buku.sh - 从 Firefox 完全迁移书签
echo "=== Firefox → Buku 迁移工具 ==="
echo ""
echo "请先从 Firefox 导出书签:"
echo " 1. 打开 Firefox → 书签 → 管理书签 (Ctrl+Shift+O)"
echo " 2. 点击 导入和备份 → 导出书签到 HTML"
echo " 3. 保存为 firefox_bookmarks.html"
echo ""
read -p "输入导出文件路径: " firefox_file
if [ ! -f "$firefox_file" ]; then
echo "文件不存在: $firefox_file"
exit 1
fi
# 备份
backup_file="$HOME/.local/share/buku/bookmarks_backup_$(date +%Y%m%d_%H%M%S).db"
cp ~/.local/share/buku/bookmarks.db "$backup_file" 2>/dev/null
echo "已备份: $backup_file"
# 导入
echo "正在导入..."
buku -i "$firefox_file"
# 验证
echo "导入完成!当前总书签数: $(buku -p | grep -c '^[0-9]')"
双向同步方案
#!/bin/bash
# sync_browser_buku.sh - 浏览器与 Buku 双向同步
# 注意:这是一个概念性脚本
# 真正的双向同步需要更复杂的逻辑来处理冲突
BUKU_EXPORT="/tmp/buku_export.html"
BROWSER_EXPORT="$1"
# 1. 从 Buku 导出
buku -e "$BUKU_EXPORT"
# 2. 从浏览器导入(单向合并)
if [ -n "$BROWSER_EXPORT" ] && [ -f "$BROWSER_EXPORT" ]; then
echo "导入浏览器书签到 Buku..."
buku -i "$BROWSER_EXPORT"
fi
# 3. 导出最新数据供浏览器导入
echo "导出 Buku 书签供浏览器导入..."
buku -e ~/buku_bookmarks_for_browser.html
echo "请将 ~/buku_bookmarks_for_browser.html 导入到浏览器"
6.6 数据备份与恢复
备份策略
# 手动备份
cp ~/.local/share/buku/bookmarks.db ~/backups/bookmarks_$(date +%Y%m%d).db
# 自动备份脚本
cat > ~/backup_buku.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="$HOME/backups/buku"
mkdir -p "$BACKUP_DIR"
DATE=$(date +%Y%m%d_%H%M%S)
cp ~/.local/share/buku/bookmarks.db "$BACKUP_DIR/bookmarks_$DATE.db"
# 保留最近 30 天的备份
find "$BACKUP_DIR" -name "bookmarks_*.db" -mtime +30 -delete
echo "备份完成: $BACKUP_DIR/bookmarks_$DATE.db"
EOF
chmod +x ~/backup_buku.sh
# 使用 cron 定期备份
# crontab -e
# 0 2 * * * ~/backup_buku.sh # 每天凌晨 2 点备份
恢复数据
# 从备份恢复
cp ~/backups/buku/bookmarks_20260510.db ~/.local/share/buku/bookmarks.db
# 验证恢复
buku -p | head -10
echo "总书签数: $(buku -p | grep -c '^[0-9]')"
数据库合并
#!/bin/bash
# merge_databases.sh - 合并两个 Buku 数据库
DB1="$1"
DB2="$2"
OUTPUT="$3"
if [ -z "$DB1" ] || [ -z "$DB2" ] || [ -z "$OUTPUT" ]; then
echo "用法: $0 <数据库1> <数据库2> <输出文件>"
exit 1
fi
# 提取两个数据库的书签
sqlite3 "$DB1" "SELECT url, metadata, tags, desc FROM bookmarks;" > /tmp/db1_bookmarks.tsv
sqlite3 "$DB2" "SELECT url, metadata, tags, desc FROM bookmarks;" > /tmp/db2_bookmarks.tsv
# 合并(去重)
cat /tmp/db1_bookmarks.tsv /tmp/db2_bookmarks.tsv | sort -u > /tmp/merged_bookmarks.tsv
# 创建新数据库
cp "$DB1" "$OUTPUT"
sqlite3 "$OUTPUT" "DELETE FROM bookmarks;"
# 导入合并后的数据
while IFS=$'\t' read -r url metadata tags desc; do
sqlite3 "$OUTPUT" "INSERT OR IGNORE INTO bookmarks (url, metadata, tags, desc) VALUES ('$url', '$metadata', '$tags', '$desc');"
done < /tmp/merged_bookmarks.tsv
echo "合并完成: $OUTPUT"
echo "总书签数: $(sqlite3 "$OUTPUT" "SELECT COUNT(*) FROM bookmarks;")"
6.7 导入导出最佳实践
导入前检查清单
┌────────────────────────────────────────────────────────────┐
│ 导入前检查清单 │
├────────────────────────────────────────────────────────────┤
│ │
│ □ 备份当前 Buku 数据库 │
│ □ 检查导入文件格式是否正确 │
│ □ 确认导入文件编码为 UTF-8 │
│ □ 检查是否有重复书签 │
│ □ 规划导入后的标签策略 │
│ □ 准备清理脚本(删除不需要的书签) │
│ │
└────────────────────────────────────────────────────────────┘
导入后清理
# 1. 检查导入结果
buku -p | head -30
# 2. 查找可能的重复
buku -j | jq -r '.[].url' | sort | uniq -d
# 3. 为导入的书签添加标签
# (浏览器导出通常不包含标签信息)
buku -s "github.com" | grep "^[0-9]" | awk '{print $1}' | tr -d '.' | while read id; do
buku -u "$id" + ,github,code
done
# 4. 删除死链
buku -f 4 | while read url; do
status=$(curl -o /dev/null -s -w "%{http_code}" --connect-timeout 5 "$url" 2>/dev/null)
if [ "$status" = "000" ] || [ "$status" = "404" ]; then
echo "死链 [$status]: $url"
fi
done
6.8 常见问题
| 问题 | 原因 | 解决方案 |
|---|
| 导入后书签数为 0 | 文件格式不支持 | 检查文件格式,确保是 HTML/JSON |
| 重复书签 | 多次导入 | 先删除重复再导入 |
| 标签丢失 | 浏览器不导出标签 | 导入后手动添加标签 |
| 中文乱码 | 编码问题 | 确保文件为 UTF-8 编码 |
| 导入很慢 | 书签数量大 | 耐心等待,或分批导入 |
| JSON 导入失败 | 格式不匹配 | 检查 JSON 结构,使用正确格式 |
6.9 本章小结
| 操作 | 命令 | 说明 |
|---|
| 导入 HTML | buku -i file.html | 从浏览器导入 |
| 导入 Markdown | buku -i file.md | Markdown 格式 |
| 导出 HTML | buku -e file.html | 浏览器可导入 |
| 导出 Markdown | buku -e file.md | 人类可读 |
| 导出 JSON | buku -j > file.json | 脚本处理最佳 |
| 备份数据库 | cp bookmarks.db backup.db | 直接复制文件 |
| 恢复数据库 | cp backup.db bookmarks.db | 直接覆盖文件 |
扩展阅读
下一章:第 07 章:加密与安全 — 学习使用 AES-256 加密保护书签数据库。