惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 司徒正美
N
News and Events Feed by Topic
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
Help Net Security
Help Net Security
N
News and Events Feed by Topic
O
OpenAI News
L
LangChain Blog
F
Full Disclosure
A
About on SuperTechFans
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
Cloudbric
Cloudbric
W
WeLiveSecurity
Application and Cybersecurity Blog
Application and Cybersecurity Blog
罗磊的独立博客
Attack and Defense Labs
Attack and Defense Labs
PCI Perspectives
PCI Perspectives
TaoSecurity Blog
TaoSecurity Blog
AI
AI
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
C
CXSECURITY Database RSS Feed - CXSecurity.com
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Apple Machine Learning Research
Apple Machine Learning Research
C
CERT Recently Published Vulnerability Notes
T
The Exploit Database - CXSecurity.com
T
Threatpost
P
Palo Alto Networks Blog
G
GRAHAM CLULEY
Last Week in AI
Last Week in AI
雷峰网
雷峰网
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园 - 聂微东
P
Proofpoint News Feed
Latest news
Latest news
S
SegmentFault 最新的问题
J
Java Code Geeks
T
Threat Research - Cisco Blogs
H
Help Net Security
P
Privacy International News Feed

szhshp 的第三边境研究所

假设, AI 把我代替的那一刻真的到来 | szhshp 的第三边境研究所 小傻瓜都能懂的 AstrBot QQ 机器人集成 MCP 功能实战指南 | szhshp 的第三边境研究所 《智人之上: 从石器时代到 AI 时代的信息网络简史》阅读笔记 | szhshp 的第三边境研究所 iPadOS 26 无法设置空间场景图片壁纸的解决方法 | szhshp 的第三边境研究所 《一路云海》(终) | szhshp 的第三边境研究所 《一路云海》(四): 如何不按套路旅行 | szhshp 的第三边境研究所 《一路云海》(三): In Ya Mellow Tone | szhshp 的第三边境研究所 《一路云海》(二): 关西世博参观纪实 | szhshp 的第三边境研究所 《一路云海》(一): 新的征程 | szhshp 的第三边境研究所 2025 大阪世博会 [ 3 天前-先到先得 ] 阶段 场馆预约必中独家攻略 | szhshp 的第三边境研究所 Hackathon 随想 | szhshp 的第三边境研究所 一杯双皮奶 | szhshp 的第三边境研究所 Armbian + CasaOS + NAS 配置指南 | szhshp 的第三边境研究所 Docker 构建镜像报错: error getting credentials - err: exit status 1, out: `` | szhshp 的第三边境研究所 Disqus RIP! 论过高的维护成本如何治疗固执的坏习惯 | szhshp 的第三边境研究所 炸弹猫桌游变体规则 | szhshp 的第三边境研究所 《小岛经济学》阅读笔记 | szhshp 的第三边境研究所 《金钱心理学》阅读笔记 | szhshp 的第三边境研究所 2025 博客第十年展望 - 再见我的过去 | szhshp 的第三边境研究所 我在独立游戏里面致敬的作品 | szhshp 的第三边境研究所 《How to make thing faster》阅读笔记 | szhshp 的第三边境研究所 《The Art of Clean Code》阅读笔记 | szhshp 的第三边境研究所 《Clean Architecture: A Craftsman Guide to Software Structure and Design》阅读笔记 | szhshp 的第三边境研究所 《How AI Works》阅读笔记 | szhshp 的第三边境研究所 游戏策划废案 - Project Uranus | szhshp 的第三边境研究所 游戏策划废案 - Project X | szhshp 的第三边境研究所 人生第一款独立游戏开发复盘 | szhshp 的第三边境研究所 Trap of Life | szhshp 的第三边境研究所 如果我用手搓了个暗物质雏形 | szhshp 的第三边境研究所 《Rust Programming Language》- EX - Cheatsheet | szhshp 的第三边境研究所 新的播放器上线了 | szhshp 的第三边境研究所 Cypress - End-to-End Testing: OKTA Authentication with MFA | szhshp 的第三边境研究所 VSC x VIM - 反正多学几个快捷键没有坏处 | szhshp 的第三边境研究所 两小时 Docker 速成 - Getting Started | szhshp 的第三边境研究所 《The Joy of Javascript》- 5 - Data | szhshp 的第三边境研究所 《The Joy of Javascript》- 4 - Meta Programming | szhshp 的第三边境研究所 《The Joy of Javascript》- 3 - ADT(Algebraic Data Type) | szhshp 的第三边境研究所 Web-Automation Testing | szhshp 的第三边境研究所 《The Joy of Javascript》- 2 - Functor/Monad | szhshp 的第三边境研究所 《The Joy of Javascript》- 1 - Object/Function | szhshp 的第三边境研究所 EvalError: Possible side-effect in debug-evaluate | szhshp 的第三边境研究所 前端 QA 工具链指南 - husky,commitlint,commitizen,eslint,typescript,express | szhshp 的第三边境研究所 效率工具 & 软件推荐 | szhshp 的第三边境研究所 站点开源 Project Titan | szhshp 的第三边境研究所 cmd/powershell-命令速查-Cheatsheet | szhshp 的第三边境研究所 Git-命令速查与相关问题解决-Cheatsheet & Troubleshooting | szhshp 的第三边境研究所 Tailwind.css not included in NextJS Production | szhshp 的第三边境研究所 Github GraphQL API - Data Integration | szhshp 的第三边境研究所 尝试 Windows Terminal + z.lua | szhshp 的第三边境研究所 StrokePlus.net - Powerful Hotkey Boost | szhshp 的第三边境研究所 优雅地 Hack 一台黑苹果 | szhshp 的第三边境研究所 一杯关东煮 | szhshp 的第三边境研究所 Gitee x PicGo 管理图床 | szhshp 的第三边境研究所 Create Your Own Redux (Typescript) | szhshp 的第三边境研究所 Getting Started: Ionic + Capacitor + React + Typescript + Android | szhshp 的第三边境研究所 GraphQL: File Upload & Troubleshooting | szhshp 的第三边境研究所 吉祥航空随心飞刷票工具循环查票工具 | szhshp 的第三边境研究所 NVM Windows Portable Installation | szhshp 的第三边境研究所 NextJS x Typescript - Integration & Troubleshooting | szhshp 的第三边境研究所 全站点升级 - Project Titan | szhshp 的第三边境研究所 AWS-EC2-常见问题解决-Troubleshooting | szhshp 的第三边境研究所 Workbox-Getting Started | szhshp 的第三边境研究所 《时间简史》阅读笔记 | szhshp 的第三边境研究所 《时间的秩序》阅读笔记 | szhshp 的第三边境研究所 ESLint-常见问题解决-Troubleshooting | szhshp 的第三边境研究所 站点索引 | szhshp 的第三边境研究所 个人知识库搭建 - Hexo 实现 Github/Coding 持续集成 | szhshp 的第三边境研究所 BMOB-常见问题解决-Troubleshooting | szhshp 的第三边境研究所 React + Typescript: 开启 HMR/Hot Loader | szhshp 的第三边境研究所 Yarn & NPM | szhshp 的第三边境研究所 ESLint: Typescript + React + TSX 集成 | szhshp 的第三边境研究所 《10101》EP15:过年 2020 | szhshp 的第三边境研究所 Cmder-Usage | szhshp 的第三边境研究所 Redux-DOM not refreshed | szhshp 的第三边境研究所 React Semantic UI-CheatSheet | szhshp 的第三边境研究所 Typescript: Getting Started | szhshp 的第三边境研究所 Flutter-Getting Started | szhshp 的第三边境研究所 Typescript: Access window object with type check | szhshp 的第三边境研究所 VSC Extension Development-Create A Code Formatter Extension | szhshp 的第三边境研究所 OneNote Extension-Main API | szhshp 的第三边境研究所 TortoiseGit Win10 Icon not showing correctly | szhshp 的第三边境研究所 Mongoose: aggregate() 方法实现聚合函数 | szhshp 的第三边境研究所 React In Depth - React 源码解析 - render() & Fiber | szhshp 的第三边境研究所 MongoDB x Mongoose: 实现类似 Join 的功能 | szhshp 的第三边境研究所 Disqus 评论框改造工程-实现 Disqus 代理的 Serverless 服务 | szhshp 的第三边境研究所 GUI, CLI, Terminal, Shell, TTY, Console, Bash | szhshp 的第三边境研究所 Jest Async Best Practise: No Nested Async | szhshp 的第三边境研究所 关系型数据库与非关系型数据库优缺点分析 | szhshp 的第三边境研究所 New Edge & Chromium Error - Package is invalid: 'CRX_VERSION_NUMBER_INVALID' | szhshp 的第三边境研究所 选择 GraphQL 的 N 个理由 | szhshp 的第三边境研究所 StrokePlus - 鼠标手势神器的代码编写技巧 | szhshp 的第三边境研究所 嗨,好久不见 | szhshp 的第三边境研究所 Vue + ElementUI 集成 Vue Router | szhshp 的第三边境研究所 IE8 - Unknown Runtime Error Using innerHTML & Ajax | szhshp 的第三边境研究所 React: Handling Events | szhshp 的第三边境研究所 React-Navigation Integration with Redux | szhshp 的第三边境研究所 React: States is tricky | szhshp 的第三边境研究所 《10101》EP14:小剧场 | szhshp 的第三边境研究所 ColdFusion - Basic - arguments in cffunction | szhshp 的第三边境研究所 ColdFusion - Basic - cfset | szhshp 的第三边境研究所
为知笔记 RIP: 迁移剩余的笔记 | szhshp 的第三边境研究所
2025-01-18 · via szhshp 的第三边境研究所

Meta

目录

关于数据记录的哲学

  • 毫无疑问: 降低耦合, 减少软件和框架的依赖
  • 提高可迁移性, 降低迁移成本
  • 跨平台, 跨设备

行业反例

  1. 为知笔记
  2. 有道云笔记
  3. 印象笔记

Background Story

大概 4 年前, 我将 Tech 笔记的内容迁移 到了自己的一个子站点, 然后使用 Hexo Serve 起来公开访问.

后期也尝试过 Docusaurus, 但是这类静态网站生成器都有一定的局限性, 我没法完全自由操作笔记渲染器和生成器.

今天我需要个 Mermaid, 明天我需要个 Exclidraw, 后天我需要个 Image Lightbox, 就算是插件也很麻烦, 这些我现在都不愿意再去折腾.

AI 时代开始的那一年我就已经将公开的笔记站点下线了, 因为我觉得没有必要喂给 AI.

最终我全部将笔记单纯扔到 NAS, 用一个简单的文件夹结构来管理, 使用 Obsidian 来查看和编辑.

有一些工作相关的笔记因为不便公开因此没有迁移, 但是我也没有在意, 就一直放到了现在.

直到前两天突然发现为知笔记的账号竟然用的是统一的密码, 于是我上去准备修改一下密码, 结果发现里面竟然还存了两百多篇笔记.

方案研究

当年我是用了一个 python 工具将为知笔记的笔记导出成 markdown 文件, 但是今天无论如何都找不到这个工具了.

我在网上找了一圈, 也没有找到合适的工具, 于是我决定自己写一个.

研究了一下相关:

  • 为知笔记是将笔记保存在本地, 未加密且内容包含:
    • 使用 HTML 方式保存的 markdown 的原文
      • 很奇葩, 类似是用 Rich Editor 导出的内容: 合法 markdown 段落被包裹在多个 <div> 里面
    • 图片等附件
  • SQLite 数据库保存了笔记的元数据

为知笔记的数据结构

.
├── index.db                ========> [ WizNote database ]
├── notes                   ========> [ Actual notes folder ]
│   ├── {06bdffb9-d9af-4e4e-8d45-3d8a488aca7b}   ========> [ Zipped notes(HTML+Images) ]
│   ├── {123e4567-e89b-12d3-a456-426614174000}
│   ├── (...)
└── wizthumb.db 

详细流程

  1. 读取 index.db 获取笔记的元数据, 内容很详细了, 包含了笔记的 GUID , 标题 , 目录 等.
     {
       // GUID
       DOCUMENT_GUID: '2e05ddd4-870e-4b3a-b38b-2a5300363f28', 
       // Title
       DOCUMENT_TITLE: 'Log: PCC - Performance Improvement.md', 
       // Location
       DOCUMENT_LOCATION: '/#Work-Archived/Archived/', 
    
    
       (... Unnecessary fields ...)
     }
  2. 根据每一篇笔记 GUID, 读取 notes 文件夹下的对应文件夹, 解压缩
  3. 获取解压缩出来的 index.html 文件是笔记的内容
    • 这里是一段保存在 index.html 里面的 raw 文本:
        <body>
        [TOC]<br />
        # PCC-pcc_selectScope update<br />
        ## Requirement<br />
        根据不同的用户,在Business Selector中显示此用户已经拥有权限所对应的Business<br />
        <br />
        ## Procedure<br />
        这个CT从confMineral3_ebtn_PB.cfm调用,在弹窗中出现,原来的CT-pcc_selectScope中只有一个<br />
        ```HTML<br />
        &lt;cfparam name="Attributes.businessDisabled" default = "false"&gt;<br />
        ```<br />
        来判断用户是否有选择Business的权限,现在要根据数据库中的用户权限来限定选项并允许选择<br />
        <br />
        ## Dev<br />
        ...
    • 很显然, 是正常合法的 markdown, 但是保存在了 html 里面
  4. 解压缩出来的 /index_files 文件夹是笔记的附件, 由于保存的是合法 markdown, 正文里面已经包含了图片的引用, 直接复制到笔记文件夹下
  5. 最终导出结果:
    final
      ├── Tech
      │   ├── Logs: Archived Logs
      │   │   ├── index.md
      │   │   └── index_files
      │   │       ├── 219ed06c-a080-41f6-a03c-915bbce626c2.png
      │   │       ├── 56026f34-073c-4601-b09d-c436b7a78ba8.png
      │   │       ├── 74beeaa8-14d3-423f-93cf-9edd220202e3.png
      │   │       ├── 94e7e3af-6bec-4faf-83c6-9b1481350601.png
      │   │       ├── a1aec740-94e0-4d50-9f78-3114fd666de6.jpg
      │   │       ├── a213075f-eda7-4172-a42f-2e73daf3ff3e.png
      │   │       ├── a59350a6-48d1-41e4-9dd0-7458dc5fce1f.png
      │   │       ├── a76ae0c2-5e54-4aa7-bfa0-1f81122bcbb2.png
      │   │       ├── de4db3b0-9e9c-4d08-9c56-e39113fa7fc2.png
      │   │       └── fefc4cc6-ba3a-48e6-814b-9e9da5b4dae7.jpg
      │   ├── Logs: CF11
      │   │   └── SQL2012 Switch
      │   │       ├── index.md
      │   │       └── index_files
      │   │           └── clip_image002.png
      └── Tmp: SQL Database Academy
          ├── index.md
          └── index_files
              ├── 185eea5e-fff9-4f86-bd7b-8e29df73a0dc.png
              ├── 5108ae70-c9c7-4c69-b55f-889cd464ac3a.jpg
              └── a3f6a93c-eff8-4410-8f20-26ef003d7517.jpg

代码实现

研究一小时, 码代码十分钟

https://github.com/szhshp/Wiznote2Markdown

多花 3 分钟顺手发布到 NPM

未来就可以一行命令解决所有问题

npx wiznote2markdown