使用 Jupyter Notebook 写博客

借助 Jupyter Notebooks 和 fast_template,我们可以轻松分享散文、代码、表格、图表等等!
技术
作者

Jeremy Howard

发布日期

2020年1月20日

Jupyter Notebooks 是一个非常适合创建“代码密集型”博客文章的环境。也许你甚至没打算写一篇博客文章,但你在 Notebook 中做了一些有趣的实验,事后意识到你的结果值得分享。无论如何,你都需要一种方法将你的 Notebook 发布到你的博客上。

fast_templatenbdev 被设置为可以很好地处理 Jupyter Notebooks。Jupyter Notebooks 和 GitHub Pages 已经提供了一些将 Notebook 导出为 markdown 的支持;但我建议你使用 fast_templatenbdev,按照本文描述的过程,因为否则你将无法获得以下有用的功能:

整篇文章都是使用这种方法创建的。你可以在此处查看 源代码 Notebook

撰写你的 Notebook

你的 markdown 单元格、代码单元格以及所有输出都将出现在导出的博客文章中。唯一不会显示的是交互式输出 (例如 ipywidgets、bokeh 图形等),或者你使用下文讨论的 #hide 标记明确隐藏的单元格。

在撰写 Notebook 时,只需写下你希望读者看到的内容。由于大多数写作平台都很难包含代码和输出,我们许多人养成了包含的实际示例比应有的要少的习惯。因此,请尝试养成在写作时包含大量示例的新习惯。

通常你会想隐藏一些样板代码,例如 import 语句。在任何单元格的顶部添加 #hide,使其不显示在输出中。

Jupyter 会显示单元格最后一行的结果,因此无需包含 print()。(并且包含不需要的额外代码会增加读者的认知负担;所以不要包含你真正不需要的代码!)

1+1
2

它不仅适用于文本,也适用于图片。例如,这里是 flip_lr 数据增强的一个示例 使用 fastai.vision

Image.open('../fast.ai/images/fast_template/image2.png').flip_lr()

png
……还有图表
plt.plot([1,2]);

png
……还有 Pandas DataFrames,以及更多!
pd.DataFrame({'a':[1,2], 'b':[3,4]})
a b
0 1 3
1 2 4

你还可以将图片(例如截图)直接粘贴到 Jupyter 的 markdown 单元格中。这会在 Notebook 中创建一个嵌入文件,Jupyter 称之为“附件”。或者你可以使用 Markdown 通过 URL 引用互联网上的图片。

导出为 Markdown

在导出到 markdown 之前,首先需要确保你的 Notebook 已保存,因此按下 s 键或点击 FileSave。然后关闭带有打开的 Notebook 的浏览器标签页。这很重要,因为当我们导出到 markdown 时,任何附件都将被导出到文件中,Notebook 也将被更新以引用这些外部文件。因此,Notebook 本身会发生变化;如果保持打开状态,你可能会意外覆盖更新后的 Notebook。

你需要安装 nbdev;如果还没有安装,请使用以下命令安装:

pip install nbdev

然后,在你的终端中,cd 到包含你的 Notebook 的文件夹,然后键入(假设你的 Notebook 文件名为 name.ipynb

nbdev_nb2md name.ipynb

你会看到创建了一个文件 name.md 和一个文件夹 name_files(其中“name”被替换为你的 Notebook 文件名)。一个问题是 markdown 导出器假定你的图片将在 name_files 文件夹中,但在你的博客上它们会在 /images/name_files 中。因此我们需要在 markdown 文件中进行搜索和替换来修复此问题。我们可以使用 python 自动完成。创建一个名为 upd_md.py 的文件,内容如下:

import fileinput,re
for f in fileinput.input(inplace=True):
    print(re.sub(r'^(!.*]\()(\w+_files/)', r'\1/images/\2', f), end='')

然后,在终端中运行(假设 upd_md.py 和你的 markdown 文档在同一个文件夹中)

python upd_md.py name.md

这会就地修改你的 markdown 文档,因此每个图片引用都会带有正确的 /images/ 前缀。

最后,将 name_files 复制到你的博客仓库的 images 文件夹中,并将 name.md 复制到你的 _posts 文件夹中,并将 name.md 重命名为所需的 YEAR-MONTH-DAY-name.md 格式。提交并将其推送到 GitHub,你就会看到你的博文了!