强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Buku 书签管理完全指南 / 第 06 章:导入导出

第 06 章:导入导出

学习在不同格式和平台之间迁移书签数据,实现数据的自由流动。

6.1 导入概览

Buku 支持多种导入格式,方便从其他工具或浏览器迁移书签数据。

支持的导入格式

格式命令来源说明
HTMLbuku -i file.html浏览器导出Netscape Bookmark 标准格式
Markdownbuku -i file.md手动整理支持特定 Markdown 格式
Orgbuku -i file.orgEmacs Org-modeOrg 格式书签
XBELbuku -i file.xbel部分浏览器XML Bookmark Exchange Language
JSONbuku -i file.jsonBuku 自身导出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

各浏览器导出格式对比

浏览器导出格式标签支持文件夹转换备注
ChromeHTML✅ 文件夹转标签最通用
FirefoxHTML✅ 文件夹转标签支持完整导出
EdgeHTML✅ 文件夹转标签兼容 Chrome
SafariHTML✅ 文件夹转标签基本支持

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 是一种较少使用的格式,主要用于部分浏览器)

导出格式对比

格式命令浏览器可导入人类可读脚本处理标签信息
HTMLbuku -e file.html有限
Markdownbuku -e file.md✅ 高
Orgbuku -e file.org✅ 高
JSONbuku -j > file.json✅ 最佳✅ 完整
TSVbuku -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 本章小结

操作命令说明
导入 HTMLbuku -i file.html从浏览器导入
导入 Markdownbuku -i file.mdMarkdown 格式
导出 HTMLbuku -e file.html浏览器可导入
导出 Markdownbuku -e file.md人类可读
导出 JSONbuku -j > file.json脚本处理最佳
备份数据库cp bookmarks.db backup.db直接复制文件
恢复数据库cp backup.db bookmarks.db直接覆盖文件

扩展阅读


下一章第 07 章:加密与安全 — 学习使用 AES-256 加密保护书签数据库。