1. 问题背景与核心痛点
作为一名长期使用Jupyter Notebook进行数据分析的从业者,我经常遇到需要将Notebook导出为PDF的场景——无论是项目报告、论文附录还是技术文档。但每次导出包含中文内容的Notebook时,总会遇到令人头疼的字体显示问题:要么中文完全消失变成空白,要么被替换为无法辨认的乱码字符。
这个问题的根源在于Jupyter Notebook默认使用LaTeX引擎进行PDF转换,而标准的LaTeX发行版(如TeX Live)并未预装中文字体库。当LaTeX遇到中文字符时,要么直接忽略(导致空白),要么用错误编码渲染(产生乱码)。我曾见过不少同行被迫将中文内容截图插入Notebook,或者先导出HTML再手动转PDF——这些方法不仅效率低下,还破坏了文档的可编辑性和一致性。
2. 解决方案的技术路线选择
2.1 为什么常规PDF导出会失败
Jupyter Notebook通过nbconvert工具链实现格式转换,其PDF导出实际上分为两个阶段:
- 将
.ipynb文件转换为LaTeX源码(.tex) - 调用系统安装的LaTeX引擎(如pdflatex/xelatex)编译生成PDF
问题出在第二阶段:传统pdflatex使用的是ASCII编码,根本不支持Unicode字符(包括中文)。即使改用xelatex引擎,如果没有正确配置中文字体映射,同样无法渲染中文内容。
2.2 可行的技术方案对比
经过多次实践验证,我总结出三种可行的解决方案:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 使用ctex宏包 | 原生支持中文,配置简单 | 需要完整的中文LaTeX环境 | 长期需要中文PDF输出的用户 |
| 替换为支持中文的模板 | 一次配置永久生效 | 需要修改Jupyter配置 | 团队协作或固定格式需求 |
| 导出HTML后打印 | 无需LaTeX环境 | 格式控制能力弱 | 临时性需求或简单文档 |
对于大多数用户,我强烈推荐第一种方案——通过ctex宏包实现中文支持。这是最稳定、最接近原生LaTeX体验的方法,也是本文重点讲解的方案。
3. 具体实现步骤详解
3.1 环境准备:安装必要组件
首先确保系统中已安装以下软件(以Windows为例,其他系统类似):
完整版TeX Live(推荐)或MiKTeX
- 必须选择"完整安装"而非基础版,确保包含xeCJK和ctex组件
- 验证安装:命令行执行
xelatex --version应显示版本信息
Jupyter Notebook环境
- 通过Anaconda或pip安装的最新版即可
- 验证安装:
jupyter --version查看核心组件版本
中文字体文件
- 系统需至少安装一种中文字体(如思源宋体、方正书宋等)
- 查看已安装字体:Windows运行
fc-list :lang=zh,macOS/Linux使用fc-list
3.2 配置Jupyter使用xelatex引擎
在Jupyter配置文件(通常位于~/.jupyter/jupyter_notebook_config.py)中添加:
c.PDFExporter.latex_command = ['xelatex', '{filename}'] c.PDFExporter.tex_command = ['xelatex', '{filename}']如果没有配置文件,可以通过以下命令生成:
jupyter notebook --generate-config3.3 创建支持中文的LaTeX模板
在用户目录下创建模板文件~/.jupyter/templates/mytemplate.tplx,内容如下:
((*- extends 'article.tplx' -*)) ((* block packages *)) \usepackage{ctex} \usepackage{fontspec} \setmainfont{SimSun} % 设置为系统中已安装的中文字体 \XeTeXlinebreaklocale "zh" \XeTeXlinebreakskip = 0pt plus 1pt ((* endblock packages *))关键配置说明:
ctex宏包提供完整的中文排版支持fontspec允许直接调用系统字体\setmainfont必须指定实际存在的字体名称(可通过fc-list查看)
3.4 实际导出操作流程
在Jupyter Notebook中完成内容编辑,确保所有包含中文的单元格都已执行并显示正常
通过命令行执行导出(推荐方式):
jupyter nbconvert --to pdf --template mytemplate notebook.ipynb或者通过Notebook界面操作:
- File -> Download As -> PDF via LaTeX (.pdf)
- 这种方式会自动应用之前配置的模板
重要提示:首次运行可能会花费较长时间(5-10分钟),因为LaTeX需要下载和缓存字体文件。后续导出会快很多。
4. 常见问题与深度排错
4.1 字体找不到错误(Font not found)
典型报错:
! fontspec error: "font-not-found" The font "SimSun" cannot be found.解决方案:
- 确认字体名称拼写正确(区分大小写)
- 使用
fc-list查看实际可用的字体名称 - 将
.tplx文件中的\setmainfont改为系统存在的字体
4.2 编码错误(Invalid UTF-8)
典型报错:
! Package inputenc Error: Unicode character (U+XXXX)解决方案:
- 确保模板中已启用xelatex引擎
- 检查Notebook文件是否保存为UTF-8编码
- 在Notebook开头添加魔法命令:
%%latex \usepackage{ctex}
4.3 表格/图片中的中文不显示
特殊场景处理:
- 对于Markdown表格中的中文,确保使用标准表格语法
- 对于Matplotlib生成的中文图表,需要在代码中单独设置字体:
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定中文字体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
5. 进阶优化技巧
5.1 自定义PDF元数据
在模板文件中添加以下内容,可以优化PDF的文档属性:
((* block document *)) \documentclass[UTF8]{ctexart} \title{我的中文报告} \author{作者名} \begin{document} \maketitle (( super() )) \end{document} ((* endblock document *))5.2 多字体混合排版
如果需要同时使用中英文字体,可以这样配置:
\usepackage{fontspec} \setmainfont{Times New Roman} \setsansfont{Arial} \setmonofont{Courier New} \setCJKmainfont{SimSun} \setCJKsansfont{SimHei} \setCJKmonofont{FangSong}5.3 批量导出脚本
对于需要定期导出多个Notebook的场景,可以创建shell脚本:
#!/bin/bash for notebook in *.ipynb; do jupyter nbconvert --to pdf --template mytemplate "$notebook" done6. 性能优化与实用建议
缓存机制:LaTeX首次编译后会生成
.aux等中间文件,第二次编译会快很多。建议在正式导出前先试运行一次。字体子集化:如果PDF文件过大,可以在模板中添加:
\usepackage[subset]{fontspec}这样只会嵌入实际使用的字形。
云环境方案:在Colab等云端环境使用时,需要额外安装中文字体:
!apt-get install texlive-xetex texlive-fonts-recommended texlive-latex-recommended !apt-get install fonts-wqy-zenhei版本控制友好:建议将
.tplx模板文件纳入版本控制,确保团队成员使用相同的导出配置。
经过这些配置后,我现在可以一键导出完美支持中文的PDF文档,再也不用担心格式错乱的问题。这个方案在学术论文写作、技术报告提交等场景下尤其有用,希望能帮助到同样受此困扰的同行们。