光影岁月 發表於 2026-1-13 08:47:54

Python实现将Markdown一键打印为A4专业文档

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">摘要</a></li><li><a href="#_label1">一、功能概览</a></li><li><a href="#_label2">二、使用方法(3步搞定)</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">1. 准备文件结构</a></li><li><a href="#_lab2_2_1">2. 安装依赖</a></li><li><a href="#_lab2_2_2">3. 安装 wkhtmltopdf</a></li><li><a href="#_lab2_2_3">4. 运行脚本</a></li></ul><li><a href="#_label3">三、运行效果</a></li><ul class="second_class_ul"></ul><li><a href="#_label4">四、源代码</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>摘要</h2>
<p><strong>只需一个 Python 脚本,3 秒完成</strong>:从任意 md.md 文件一键生成 <strong>A4 打印完美适配的 PDF</strong>,支持中文、表格、代码块防截断,自动添加 <strong>带分隔线的页眉页脚 + 动态页码</strong>,无需手动调格式、写 HTML、调 CSS。 <strong>适合技术文档、教程、报告、培训资料</strong>,直接打印分发,专业感拉满! <strong>零依赖配置,运行即得,告别 Word 排版痛苦,解放生产力!</strong></p>
<p class="maodian"><a name="_label1"></a></p><h2>一、功能概览</h2>
<p>本脚本实现 <strong>从 Markdown 文件一键生成专业级 A4 打印友好 PDF</strong>,具备以下完整功能:</p>
<table><thead><tr><th>功能</th><th>实现方式</th></tr></thead><tbody><tr><td>中文支持</td><td>使用 Microsoft YaHei + SimSun 字体</td></tr><tr><td>表格美观</td><td>边框、表头灰底、自动分页</td></tr><tr><td>代码块防截断</td><td>page-break-inside: avoid</td></tr><tr><td>页眉(带下划线)</td><td>自定义 header.html</td></tr><tr><td>页脚(带上划线 + 动态页码)</td><td>自定义 footer.html + JavaScript</td></tr><tr><td>自动生成临时文件</td><td>tempfile.mkdtemp()</td></tr><tr><td>一键运行</td><td>无需手动创建 HTML 文件</td></tr></tbody></table>
<p class="maodian"><a name="_label2"></a></p><h2>二、使用方法(3步搞定)</h2>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>1. 准备文件结构</h3>
<p>项目文件夹/&nbsp;</p>
<blockquote><p>├── md.md &larr; 你的 Markdown 文档<br />├── md_to_a4_pdf.py &larr; 本脚本</p></blockquote>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>2. 安装依赖</h3>
<div class="jb51code"><pre class="brush:bash;">pip install markdown pdfkit</pre></div>
<p class="maodian"><a name="_lab2_2_2"></a></p><h3>3. 安装 wkhtmltopdf</h3>
<p>安装后 <strong>修改脚本第 15 行路径</strong>:</p>
<div class="jb51code"><pre class="brush:py;">wkhtmltopdf_path = r"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe"</pre></div>
<p class="maodian"><a name="_lab2_2_3"></a></p><h3>4. 运行脚本</h3>
<div class="jb51code"><pre class="brush:bash;">python md_to_a4_pdf.py</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>三、运行效果</h2>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026011308474558.png" /></p>
<p class="maodian"><a name="_label4"></a></p><h2>四、源代码</h2>
<div class="jb51code"><pre class="brush:py;"># -*- coding: utf-8 -*-
"""
A4 打印友好版 PDF 一键生成脚本(完整版)
功能:
1. 从 md.md 自动生成 PDF
2. 支持中文字体、表格、代码块
3. 带页眉(标题 + 下划线)、页脚(页码 + 上划线)
4. 自动适应 A4 页面,不裁切尾部
5. 自动生成 header.html 和 footer.html
"""

import os
import markdown
import pdfkit
import tempfile

# -------------------------------
# 配置参数(请修改这里)
# -------------------------------
source_md_file = "md.md"                  # 源 Markdown 文件
output_pdf_file = "output_a4.pdf"         # 输出 PDF 文件名
wkhtmltopdf_path = r"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe"# 修改为你的路径

# 页眉页脚内容
header_title = "Hive的安装和配置"         # 页眉标题
footer_text = "第页 / 共 页"# 页脚页码(wkhtmltopdf 自动替换)

# -------------------------------
# 检查 wkhtmltopdf
# -------------------------------
if not os.path.exists(wkhtmltopdf_path):
    print(f"错误:未找到 wkhtmltopdf 可执行文件!")
    print(f"请确认路径正确:{wkhtmltopdf_path}")
    print("下载地址:https://wkhtmltopdf.org/downloads.html")
    exit(1)

# -------------------------------
# 检查 Markdown 文件
# -------------------------------
if not os.path.exists(source_md_file):
    print(f"错误:找不到源 Markdown 文件:{source_md_file}")
    print("请确保 md.md 与脚本在同一目录")
    exit(1)

# -------------------------------
# 读取 Markdown 并转 HTML
# -------------------------------
print("正在读取 Markdown 文件...")
with open(source_md_file, "r", encoding="utf-8") as f:
    md_text = f.read()

html_content = markdown.markdown(
    md_text,
    extensions=["tables", "fenced_code", "nl2br", "toc"]
)

# -------------------------------
# 临时目录:自动生成 header.html 和 footer.html
# -------------------------------
temp_dir = tempfile.mkdtemp(prefix="pdf_gen_")
header_path = os.path.join(temp_dir, "header.html")
footer_path = os.path.join(temp_dir, "footer.html")

# 生成 header.html(带下划线)
header_html = f"""&lt;!DOCTYPE html&gt;
&lt;html&gt;&lt;head&gt;&lt;meta charset="utf-8"&gt;&lt;style&gt;
    body {{ margin:0; padding:0; font-family:"Microsoft YaHei","SimSun",sans-serif; font-size:10pt; }}
    .c {{ text-align:center; padding:5px 0; }}
    .line {{ border-bottom:1px solid #999; margin-top:4px; }}
&lt;/style&gt;&lt;/head&gt;&lt;body&gt;
&lt;div class="c"&gt;{header_title}&lt;/div&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;"""

# 生成 footer.html(带上划线)
# 生成 footer.html(带 JS 动态页码)
footer_html = """&lt;!DOCTYPE html&gt;
&lt;html&gt;&lt;head&gt;&lt;meta charset="utf-8"&gt;&lt;style&gt;
    body {margin:0;padding:0;font-family:"Microsoft YaHei","SimSun",sans-serif;font-size:10pt;text-align:center;}
    .line {border-top:1px solid #999;margin:4px 0;}
&lt;/style&gt;
&lt;script&gt;
    function subst() {
      var vars = {};
      location.search.substring(1).split("&amp;").forEach(function(p){
            var pair = p.split("="); vars] = decodeURIComponent(pair);
      });
      return vars;
    }
    document.addEventListener('DOMContentLoaded', function(){
      var v = subst();
      var el = document.getElementById('pageInfo');
      if(el) el.innerHTML = '第 ' + v.page + ' 页 / 共 ' + v.topage + ' 页';
    });
&lt;/script&gt;
&lt;/head&gt;&lt;body&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;div id="pageInfo" style="padding:5px 0;"&gt;&lt;/div&gt;
&lt;/body&gt;&lt;/html&gt;"""

with open(header_path, "w", encoding="utf-8") as f:
    f.write(header_html)
with open(footer_path, "w", encoding="utf-8") as f:
    f.write(footer_html)

print(f"临时页眉页脚已生成:{temp_dir}")

# -------------------------------
# 完整 HTML 页面
# -------------------------------
full_html = f"""&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset="utf-8"&gt;
&lt;title&gt;{header_title}&lt;/title&gt;
&lt;style&gt;
@page {{
    size: A4;
    margin: 27mm 18mm 27mm 18mm; /* 上右下左,为页眉页脚留空间 */
}}
body {{
    font-family: "Microsoft YaHei", "SimSun", "Arial", sans-serif;
    line-height: 1.7;
    margin: 0;
    color: #333;
}}
h1, h2, h3, h4 {{ color: #2c3e50; margin-top: 1.2em; page-break-after: avoid; }}
table {{ border-collapse: collapse; width: 100%; margin: 10px 0; page-break-inside: auto; }}
th, td {{ border: 1px solid #999; padding: 8px; text-align: left; }}
th {{ background-color: #f5f5f5; font-weight: bold; }}
pre, code {{
    background: #f8f8f8;
    border-radius: 4px;
    page-break-inside: avoid;
    font-family: Consolas, "Courier New", monospace;
}}
pre {{ padding: 12px; overflow: auto; }}
code {{ padding: 2px 6px; font-size: 90%; }}
p, ul, ol, blockquote {{ page-break-inside: avoid; }}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
{html_content}
&lt;/body&gt;
&lt;/html&gt;"""

# -------------------------------
# PDF 配置
# -------------------------------
print("正在配置 PDF 生成参数...")
config = pdfkit.configuration(wkhtmltopdf=wkhtmltopdf_path)

options = {
    'page-size': 'A4',
    'margin-top': '27mm',
    'margin-bottom': '27mm',
    'margin-left': '18mm',
    'margin-right': '18mm',
    'zoom': '0.95',
    'encoding': 'UTF-8',
    'enable-local-file-access': None,

    # 自定义页眉页脚(带线)
    'header-html': header_path,
    'header-spacing': '5',

    'footer-html': footer_path,
    'footer-spacing': '5',
    # 必须添加以下三行
    'enable-javascript': None,
    'javascript-delay': '500',
    'no-stop-slow-scripts': None,
}

# -------------------------------
# 生成 PDF
# -------------------------------
print("正在生成 PDF,请稍候...")
try:
    pdfkit.from_string(
      full_html,
      output_pdf_file,
      configuration=config,
      options=options
    )
    print(f"PDF 生成成功!")
    print(f"文件:{os.path.abspath(output_pdf_file)}")
    print(f"页眉页脚临时文件可删除:{temp_dir}")
except Exception as e:
    print(f"PDF 生成失败:{e}")
    exit(1)

# -------------------------------
# 结束提示
# -------------------------------
print("\n" + "="*50)
print("所有任务完成!")
print("1. 打开 output_a4.pdf 即可查看打印效果")
print("2. 支持直接打印,A4 完美适配")
print("3. 页眉有下划线,页脚有上划线,专业美观")
print("="*50)</pre></div>
頁: [1]
查看完整版本: Python实现将Markdown一键打印为A4专业文档