把浏览器里保存的密码迁移到 Bitwarden:先从 Chrome/Edge 导出 CSV,用脚本合并重复条目、按网站分文件夹、转成 Bitwarden 官方 CSV 格式,同时列出“多个网站共用同一个密码”和“短于 12 位”的账号作为改密清单;导入后删除明文 CSV 并关闭浏览器的密码保存。
先看清成品
转换脚本 4 个测试通过;样例 4 行转换为 3 条(合并 1 条重复),报告找出 1 组重复密码、1 个过短密码,且报告里不显示密码本身。输出表头与 Bitwarden 官方文档中的个人保险库 CSV 表头一致。没有导入到真实 Bitwarden 账号。
注意:计划和价格以 Bitwarden 官方价格页为准。不要共享个人账号或主密码,团队共享请用组织和集合。只导入、导出你自己有权管理的凭据。
安全提示:导出的 CSV 是明文,所有密码一览无余。只在自己的电脑上操作,不要放进网盘、不要发给别人,导入完成立即删除(也清空回收站)。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
| Bitwarden CSV | 可直接以 Bitwarden (csv) 格式导入 |
| 去重 | 同网站同用户名只保留一条 |
| 文件夹 | 按主域名分组,如 taobao.com |
| 改密清单 | 重复使用、过短的密码 |
需要准备哪些环境?
| 项目 | 要求 | 说明 |
|---|---|---|
| 浏览器 | Chrome / Edge | 设置 → 密码管理器 → 导出密码 |
| Bitwarden 账号 | 个人保险库 | 免费版即可导入 |
| Python | 3.9 以上 | 只用标准库 |
说明:Bitwarden 本身支持直接导入 Chrome 的 CSV。用本文脚本的好处是导入前去重、分文件夹,并得到改密清单。
文件结构
24-bitwarden-C-src/
├── chrome_to_bitwarden.py
├── sample_chrome.csv # 虚构样例
└── test_convert.py
第 1 步:导出浏览器密码
Chrome:设置 → 自动填充和密码 → Google 密码管理工具 → 设置 → 导出密码(菜单名称随版本变化,以浏览器为准),验证系统密码后保存 CSV。样例格式:
name,url,username,password,note
taobao.com,https://login.taobao.com/,buyer01,Tb-2026-long-pass!,
www.taobao.com,https://www.taobao.com/,buyer01,,
github.com,https://github.com/login,dev@example.com,Tb-2026-long-pass!,
mail.example.com,https://mail.example.com/,me@example.com,123456,旧邮箱
第 2 步:转换脚本
chrome_to_bitwarden.py:
"""把浏览器导出的密码 CSV(Chrome/Edge:name,url,username,password,note)整理成 Bitwarden 个人保险库 CSV。
- 同一网站 + 同一用户名只保留一条(保留密码非空的那条)
- 按主域名放入文件夹,方便导入后整理
- 输出安全报告:重复使用的密码、短于 12 位的密码(报告里不显示密码本身)
"""
import csv, sys
from collections import defaultdict
from urllib.parse import urlparse
HEADER = ["folder", "favorite", "type", "name", "notes", "fields", "reprompt",
"login_uri", "login_username", "login_password", "login_totp"]
# 常见二级后缀;完整规则见 Public Suffix List,这里只做简化处理
TWO_LEVEL = {"com.cn", "net.cn", "org.cn", "gov.cn", "edu.cn", "com.hk", "co.uk", "co.jp"}
def site(url):
host = (urlparse(url if "://" in url else "https://" + url).hostname or "").lower()
parts = host.removeprefix("www.").split(".")
n = 3 if ".".join(parts[-2:]) in TWO_LEVEL else 2
return ".".join(parts[-n:]) if len(parts) >= n else host
def convert(rows):
seen, out = {}, []
for r in rows:
url, user, pw = r.get("url", "").strip(), r.get("username", "").strip(), r.get("password", "")
key = (site(url), user.lower())
if key in seen:
if not out[seen[key]]["login_password"] and pw: out[seen[key]]["login_password"] = pw
continue
seen[key] = len(out)
out.append({"folder": site(url) or "未分类", "favorite": "", "type": "login",
"name": r.get("name", "").strip() or site(url) or url, "notes": r.get("note", ""),
"fields": "", "reprompt": "0", "login_uri": url, "login_username": user,
"login_password": pw, "login_totp": ""})
return out, len(rows) - len(out)
def report(items):
by_pw = defaultdict(list)
for it in items:
if it["login_password"]: by_pw[it["login_password"]].append(f'{it["name"]}({it["login_username"]})')
lines = [f"重复使用:{', '.join(v)}" for v in by_pw.values() if len(v) > 1]
lines += [f'过短({len(it["login_password"])} 位):{it["name"]}({it["login_username"]})'
for it in items if 0 < len(it["login_password"]) < 12]
return lines
if __name__ == "__main__":
src, dst = sys.argv[1], sys.argv[2]
with open(src, encoding="utf-8-sig", newline="") as f:
items, dups = convert(list(csv.DictReader(f)))
with open(dst, "w", encoding="utf-8", newline="") as f:
w = csv.DictWriter(f, fieldnames=HEADER); w.writeheader(); w.writerows(items)
print(f"写出 {dst}:{len(items)} 条,合并重复 {dups} 条")
for line in report(items): print("⚠", line)
Bitwarden 个人保险库 CSV 的表头(大小写必须一致):
folder,favorite,type,name,notes,fields,reprompt,login_uri,login_username,login_password,login_totp
第 3 步:运行
python chrome_to_bitwarden.py 浏览器导出.csv bitwarden_import.csv
样例的本机实际输出(本机运行时输出文件名用的是 out.csv):
写出 out.csv:3 条,合并重复 1 条
⚠ 重复使用:taobao.com(buyer01), github.com(dev@example.com)
⚠ 过短(6 位):mail.example.com(me@example.com)
把报告存下来,导入后按清单去各网站改密码(改完在 Bitwarden 里更新)。测试:python -m pytest -q → 4 passed。
第 4 步:导入 Bitwarden
网页版 工具 → 导入数据,文件格式选 Bitwarden (csv),选择 bitwarden_import.csv,导入。
检查结果:条目数等于脚本输出的条数,左侧出现 taobao.com、github.com 等文件夹。
第 5 步:清理
shred -u 浏览器导出.csv bitwarden_import.csv # Linux;macOS/Windows 删除后清空回收站
然后在浏览器设置中关闭“提议保存密码”,并删除浏览器里已保存的密码,避免两边不同步。
调试示例
最初 site() 只取域名最后两段,www.shop.com.cn 会被归到 com.cn 文件夹。加了常见二级后缀表后返回 shop.com.cn,测试 test_site 覆盖了这个情况。完整规则见 Public Suffix List,脚本只处理常见情况,个别网站分组不准不影响导入。
出错了怎么办?
| 现象 | 原因 | 解决 |
|---|---|---|
| 导入报格式错误 | 表头大小写或列数不对 | 用脚本输出,不要在 Excel 里改表头 |
| 中文乱码 | 用 Excel 保存改成了 GBK | 不要用 Excel 另存;脚本输出为 UTF-8 |
| 条目重复 | 之前已经导入过一次 | 导入前清空测试数据,或在 Bitwarden 里删除重复 |
| 文件夹太多 | 每个网站一个文件夹 | 把 folder 列改成空,或按“工作/生活”手动分 |
| 漏掉了某些密码 | 浏览器不同配置文件分别保存 | 每个配置文件分别导出 |
模板规则
- 明文 CSV 用完即删。
- 迁移的同时处理改密清单。
- 迁移后关闭浏览器密码保存,只用一个密码管理器。
项目资源
| 用途 | 地址 |
|---|---|
| 导入自定义格式文件(CSV 表头) | https://bitwarden.com/help/condition-bitwarden-import/ |
| 从 Chrome 导入 | https://bitwarden.com/help/import-from-chrome/ |
| 导入数据 | https://bitwarden.com/help/import-data/ |
| Public Suffix List | https://publicsuffix.org/ |
| Bitwarden 价格 | https://bitwarden.com/pricing/ |
迁移密码管理器是清理密码的最好时机。顺手把重复和过短的密码换掉,比单纯换个地方存要有价值得多。