在浏览器中把 HTML 文章转换为 Markdown 的 FormatArc 工具截图在浏览器中把 HTML 文章转换为 Markdown 的 FormatArc 工具截图
作者: FormatArc 编辑部发布日期: 2026-09-02更新日期: 2026-09-02

markdown 博客 迁移指南:Qiita 到 Zenn 的完整步骤

想把 Qiita 上的文章搬到 Zenn?搜索一番,个人的迁移体验帖和工具发布帖很多,但把"每一步做什么、什么顺序做"从头到尾讲清楚的文章并不多。这篇文章把 Qiita 到 Zenn 的迁移拆成 4 个步骤,整理容易卡住的语法差异、frontmatter 配置、图片和公开日期的处理。

另外,如果你要迁移的文章没有 Markdown 源文件,只剩公开页面的 HTML(比如从 Medium 或已停办的博客搬过来),把 HTML 粘贴到 HTML 转 Markdown 就能在浏览器内转回 Markdown。转换在浏览器内完成,不上传数据。Qiita 到 Zenn 的迁移两边都是 Markdown,这一步通常不需要。

迁移全景 — 4 个步骤与路径选择

迁移工作可以拆成 4 个步骤:

  1. 从 Qiita 提取文章
  2. 把 Qiita 语法改成 Zenn 语法
  3. 把 frontmatter 改成 Zenn 格式
  4. 处理图片和代码块

根据文章数量和个人偏好选择路径:

  • 文章只有几篇的话,直接从 Qiita 编辑器复制 Markdown 粘贴到 Zenn 网页编辑器最快。步骤 1 可以跳过。
  • 文章多、习惯在 GitHub 管理的话,用 API 批量获取再推到 Zenn 的 GitHub 仓库更稳妥。本文以这条路径为主。
  • 不想敲命令的话,zenn-importer在新标签页中打开 这类社区工具能自动完成步骤 1~3。但语法差异和图片后处理(步骤 2 和 4 的检查)仍然需要手动做。另外,有些迁移工具已经停更了,用之前先确认它还活着。

步骤 1:从 Qiita 提取文章

Qiita 有官方 API v2在新标签页中打开,可以拿到自己文章的 Markdown 源文件。在设置页面生成 access token,然后调用认证用户文章列表接口:

curl -H "Authorization: Bearer YOUR_TOKEN" \
  "https://qiita.com/api/v2/authenticated_user/items?page=1&per_page=100" > items.json

需要记住 3 个要点(均出自官方文档在新标签页中打开):

  • 响应的 body 字段是 Markdown 源文件,rendered_body 是 HTML。迁移用 body
  • per_page 上限是 100。超过 100 篇就递增 page 参数循环获取。
  • 调用限制:认证后每小时 1,000 次,未认证每个 IP 每小时 60 次。个人迁移够用。

步骤 2:Qiita 语法转 Zenn 语法

Markdown 基础部分(标题、列表、链接、表格)可以直接用,但两个平台的专有语法需要改写。主要对应关系如下(依据 Qiita 语法速查表在新标签页中打开Zenn Markdown 语法一览在新标签页中打开):

元素QiitaZenn
提示横幅:::note info:::message
警告横幅:::note warn / :::note alert:::message alert
折叠面板<details><summary> 标签:::details 标题
代码块文件名```ruby:qiita.rb同样的写法可用
公式块```math$$(前后需要空行)
行内公式$`公式`$$公式$

需要注意的是,横幅不能一一对应。Qiita 有 info / warn / alert 三种,Zenn 只有普通和 alert 两种。所以要先决定 warn 往哪边靠,再统一替换。给读者的重要提醒用 alert,补充强调用普通 :::message,按文章语气定就行。

这张对照表只列了主要的。想整篇检查的话,把正文粘贴到 Qiita / Zenn 兼容性检查,会和 74 条语法差异逐条对照,列出"第几行的什么内容,迁过去之后会变成什么样"。能一一对应的 37 条会直接转换,需要判断的 14 条可以选替代方式,剩下 23 条在目标端没有对应写法,只给提示。所有处理在浏览器内完成。

特别要注意的一点:Zenn 不渲染 raw HTML。Qiita 里能用的 <details><img width="...">,到了 Zenn 不会报错,但标签会原样显示在正文里。同理,写了 :::message warn 也不会变成容器,就变成一行普通文本。这种差异发布后才容易发现,所以转换后一定要用预览确认。

替换后的正文,用 Zenn CLI 的预览做最终确认最靠谱。在此之前,可以粘贴到 Zenn 的编辑预览里看效果。:::message 这类 Zenn 专有语法不在 GFM 范围内,会原样保留,但表格、标题、列表的错位在这个阶段就能发现。

步骤 3:frontmatter 配置

Zenn 的文章文件用开头的 frontmatter 管理元数据。按 Zenn CLI 指南在新标签页中打开,最小配置如下:

---
title: "文章标题"
emoji: "📘"
type: "tech"
topics: ["rails", "markdown"]
published: true
published_at: "2023-05-10 09:00"
---

把 Qiita API 响应里的 titletags 映射到这里。topics 最多指定 5 个(Zenn CLI 指南在新标签页中打开)。作为文件名的 slug 有限制:"小写英文字母、数字、连字符、下划线组合,12~50 字符"(Zenn slug 说明在新标签页中打开)。建议提前做一个原文章和新文章的链接对照表,后面查起来方便。

用 published_at 保留公开日期

迁移中最常被抱怨的就是"文章全变成今天发布"。早期的迁移教程写的是"公开日期无法保留",但现在 Zenn 支持在 frontmatter 的 published_at 中指定过去的日期。官方指南在新标签页中打开也明确写了"从其他博客服务迁移文章时想保留公开日期"这个用途。格式是 YYYY-MM-DDYYYY-MM-DD hh:mm(日本时间)。

一个注意点:公开日期只能设置一次,设置后不能改。从 Qiita API 的 created_at 批量导入时,发布前务必确认数值正确。

步骤 4:图片和代码块后处理

贴在 Qiita 上的图片在 Qiita 的图像服务器上,正文引用的是那个 URL。迁移后的文章继续引用同一个 URL,短期内能显示,但图片文件本身不在你的控制范围内。想长期保留的文章,建议下载图片、重新上传到 Zenn,然后把正文中的 URL 替换掉。

代码块方面,文件名指定写法(```ruby:qiita.rb)可以直接用,但 diff 显示等装饰写法不同(Zenn 用 ```diff js 这种空格分隔语法 — Zenn Markdown 语法一览在新标签页中打开)。用过 diff 或公式的文章,不要跳过预览检查。

迁移后原文怎么处理

三个选择:

  1. 保留 Qiita 上的文章,在开头加"已迁移"提示和 Zenn 链接
  2. 把 Qiita 上的正文改成摘要加迁移链接
  3. 删除 Qiita 上的文章

dev.to 有 canonical_url 这个 frontmatter 字段用于声明原始 URL(dev.to 编辑器指南在新标签页中打开),但 Qiita 和 Zenn 的发布流程中没有对应的设置。同一篇文章同时留在两个平台,搜索引擎无法判断哪个是原始版本。如果保留,建议用选项 1 或 2,让读者和搜索引擎都能看出"哪个是主体"。

五大平台对比 — 各能导出什么格式

除了 Qiita 和 Zenn,把主流平台的"文章提取方式"也整理一下,方便跨平台迁移时做参考。

平台提取方式得到的格式
QiitaAPI v2在新标签页中打开 获取Markdown(body)+ HTML(rendered_body
ZennGitHub 仓库关联在新标签页中打开,文章即本地 Markdown 文件Markdown
Dev.to正文是 Markdown + frontmatter(编辑器指南在新标签页中打开),API 配合社区导出工具在新标签页中打开保存Markdown
Hashnode控制台批量导出为 JSON;单篇可在 URL 末尾加 .md 直接获取 Markdown(官方更新日志在新标签页中打开JSON / Markdown
Medium"Download your information在新标签页中打开" 获取 ZIPHTML(无 Markdown 导出)

两边都给 Markdown 的平台之间,只需要处理语法和 frontmatter 转换。涉及只给 HTML 的平台时,就需要下一节的办法了。

没有 Markdown 源文件的恢复

"想迁移但没有 Markdown 源文件"的情况确实存在。Medium 的导出是 HTML 的 ZIP,已停办的服务或老博客可能只剩公开页面的 HTML。Qiita API 的 rendered_body(HTML)也是只有一份 HTML 的情况。

这时候,把 HTML 粘贴到 HTML 转 Markdown 工具运行,就能得到 GFM 兼容的 Markdown。比如:

<h2>安装与运行</h2>
<p>先执行 <code>npm install</code>。</p>

转换后变成:

## 安装与运行

先执行 `npm install`。

转换全部在浏览器内完成,文章数据不会发送到服务器。迁移对象中常混有限定分享的文章或内部草稿,在批量使用在线转换服务之前,确认工具是否只做浏览器端处理。如果要把 Notion 的 HTML 导出整理成 Markdown,可以按 Notion 导出 Markdown 的步骤来做,思路相同。

常见问题

公开日期能保留吗?

可以。在 frontmatter 的 published_at 中指定过去的日期(日本时间)。只能设置一次且不能修改,发布前确认数值(Zenn CLI 指南在新标签页中打开)。

图片不迁移会不会消失?

迁移后短期仍引用 Qiita 的图片 URL,能正常显示。但显示依赖 Qiita 的 CDN,长期保留的文章建议重新上传到 Zenn 并替换 URL。

Zenn 到 Qiita 的反向迁移怎么做?

Zenn 用 GitHub 关联的话,文章本身就是本地 Markdown 文件,不需要额外提取。把步骤 2 的对照表反向应用(:::message 改回 :::note 等),去掉 frontmatter 后粘贴到 Qiita 即可。

能批量自动化吗?

提取和 frontmatter 转换可以用 zenn-importer在新标签页中打开 等工具自动化。但横幅从 3 种归到 2 种、diff 和公式的显示方式无法由机器决定,发布前的预览检查不能省。

总结

Qiita 到 Zenn 的迁移,就是提取(API)、语法归一化(对照表批量替换)、frontmatter(published_at 保留公开日期)、图片和代码块后处理,4 个步骤。如果混着没有 Markdown 源文件的文章,把 HTML 粘贴到 HTML 转 Markdown 工具在浏览器内转换,就能汇入同一条流程。