Files
ConfigData/每日听力/生成英语听力PDF脚本.py
2026-10-07 10:57:38 +08:00

126 lines
5.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
每日英语听力材料 PDF 生成脚本(学习用)
用途:把一段英语学习材料(英文原文 + 逐句音标 + 中文翻译 + 生词表 + 听力技巧)
生成一份排版美观、可离线收藏的 PDF 文档。
依赖:
pip install reportlab
系统字体(Linux):
- DejaVu Sans:覆盖英文与 IPA 音标字符
- 文鼎 UMingCN(uming.ttc):覆盖中文字符(宋体风格)
关键知识点:
1. reportlab 的 Platypus(SimpleDocTemplate + Paragraph + Table)负责自动排版、分页;
2. reportlab 内置字体不支持中文/IPA,需用 TTFont 注册系统 TTF/TTC 字体;
3. 同一段落里混排中文与英文/IPA 时,用 <font name="..."> 标签切换字体;
4. 注意:reportlab 不支持 CFF 轮廓的字体(如 NotoSansCJK.otf),只能用 TrueType;
5. .ttc 集合字体通过 subfontIndex 选择子字体。
"""
import html as h
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import (Paragraph, SimpleDocTemplate, Spacer,
Table, TableStyle)
# ------------------------- 1. 注册字体 -------------------------
BASE = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'
BASE_BOLD = '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'
CJK = '/usr/share/fonts/truetype/arphic/uming.ttc'
pdfmetrics.registerFont(TTFont('Base', BASE))
pdfmetrics.registerFont(TTFont('Base-Bold', BASE_BOLD))
pdfmetrics.registerFont(TTFont('CJK', CJK, subfontIndex=0)) # UMingCN
def esc(s: str) -> str:
"""转义 < > & 等,避免 Paragraph 把内容当成 XML 标签。"""
return h.escape(s, quote=False)
# ------------------------- 2. 定义样式 -------------------------
title = ParagraphStyle('title', fontName='Base-Bold', fontSize=18, leading=24,
textColor=colors.HexColor('#B22222'), alignment=1, spaceAfter=6)
meta = ParagraphStyle('meta', fontName='CJK', fontSize=10, leading=14,
textColor=colors.HexColor('#666666'), alignment=1, spaceAfter=10)
h1 = ParagraphStyle('h1', fontName='CJK', fontSize=13, leading=18,
textColor=colors.HexColor('#8B0000'), spaceBefore=10, spaceAfter=6)
en = ParagraphStyle('en', fontName='Base', fontSize=11.5, leading=17, spaceBefore=4)
ipa = ParagraphStyle('ipa', fontName='Base', fontSize=9.5, leading=14,
textColor=colors.HexColor('#555555'), leftIndent=6, spaceAfter=2)
note = ParagraphStyle('note', fontName='CJK', fontSize=9.5, leading=14,
textColor=colors.HexColor('#2F5D8A'), leftIndent=12, spaceAfter=4)
zh = ParagraphStyle('zh', fontName='CJK', fontSize=11, leading=18, spaceBefore=3)
def sen(num: str, text: str):
return Paragraph('<font name="Base-Bold">%s</font> %s' % (esc(num), esc(text)), en)
# ------------------------- 3. 准备内容数据 -------------------------
sentences = [
# (编号, 英文句子, 音标, 发音要点中文说明)
("1.", "Today is October 1st — China's National Day.",
"/təˈdeɪ ɪz oʊkˈtoʊbər fɜːrst | ˈtʃaɪnəz ˈnæʃənəl deɪ/",
"● 连读:October 1st 中 /r/ 与 /f/ 自然衔接。"),
("2.", "Streets are decorated with red flags, and cities glow with lanterns and flowers.",
"/striːts ər ˈdekəreɪtɪd wɪð red flægz | ənd ˈsɪtiz gloʊ wɪð ˈlæntərnz ənd ˈflaʊərz/",
"● 重读:decorated、glow 是画面词,加重读出画面感。"),
]
words = [
# (单词, 音标, 中文释义)
("decorate", "/ˈdekəreɪt/", "装饰"),
("glow", "/gloʊ/", "发光,焕发光彩"),
]
# ------------------------- 4. 组装文档 -------------------------
story = []
story.append(Paragraph('<font name="Base-Bold">Happy National Day!</font>'
'<font name="CJK">(国庆节快乐)</font>', title))
story.append(Paragraph('每日英语听力推送 · 示例材料 · 约1分钟朗读量', meta))
story.append(Paragraph('一、英文原文(逐句 + IPA 音标)', h1))
for num, text, ip, n in sentences:
story.append(sen(num, text))
story.append(Paragraph(esc(ip), ipa))
story.append(Paragraph(esc(n), note))
story.append(Paragraph('二、生词与短语', h1))
cell_en = ParagraphStyle('c1', fontName='Base', fontSize=10, leading=13)
cell_ipa = ParagraphStyle('c2', fontName='Base', fontSize=10, leading=13,
textColor=colors.HexColor('#555555'))
cell_zh = ParagraphStyle('c3', fontName='CJK', fontSize=10, leading=13)
head = ParagraphStyle('ch', fontName='CJK', fontSize=10, leading=13, textColor=colors.white)
data = [[Paragraph('单词/短语', head), Paragraph('音标', head), Paragraph('释义', head)]]
for w, ip, z in words:
data.append([Paragraph(esc(w), cell_en),
Paragraph(esc(ip), cell_ipa),
Paragraph(esc(z), cell_zh)])
tbl = Table(data, colWidths=[52*mm, 58*mm, 62*mm])
tbl.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#8B0000')),
('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.HexColor('#F5F0E6')]),
('GRID', (0, 0), (-1, -1), 0.5, colors.HexColor('#CCCCCC')),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('LEFTPADDING', (0, 0), (-1, -1), 5),
('TOPPADDING', (0, 0), (-1, -1), 4),
('BOTTOMPADDING', (0, 0), (-1, -1), 4),
]))
story.append(tbl)
# ------------------------- 5. 写出 PDF -------------------------
doc = SimpleDocTemplate("每日英语听力_示例.pdf", pagesize=A4,
rightMargin=18*mm, leftMargin=18*mm,
topMargin=16*mm, bottomMargin=16*mm,
title="每日英语听力示例")
doc.build(story)
print("PDF generated OK")
#(注:内容由AI生成)