代码拉取完成,页面将自动刷新
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from PIL import Image
from PyPDF2 import PdfMerger
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors
import collections
import csv
class PDFGenerator:
def __init__(self, background_path):
self.background_path = background_path
self.img_width, self.img_height = self.load_background_image()
self.pages = []
self.num = 0
self.ling_str_num = 21
def load_background_image(self):
# 打开背景图片
bg_image = Image.open(self.background_path)
return bg_image.size
def add_info(self, info):
# 创建PDF文档
c = canvas.Canvas(f"temp_{self.num}.pdf", pagesize=letter)
# 将背景图片绘制到PDF中
c.drawImage(self.background_path, 0, 0, width=letter[0], height=letter[1])
for item in info:
if 'text' in item:
# 如果信息是文本
text = item['text']
font_name = item.get('font', 'Lishu')
font_size = item.get('font_size', 24)
font_color = item.get('font_color', (0, 0, 0)) # 黑色
pos = item.get('pos', None)
# 如果没有指定位置, 则默认居中
if not pos[0]:
pos[0] = (letter[0] - 48 * 2 - len(text) * 24) // 2 + 48
# 计算文本宽度和高度
# 计算文本位置(居中)
text_x, text_y = pos
# 设置字体和颜色
c.setFont(font_name, font_size)
c.setFillColorRGB(*font_color)
# 在页面上绘制文本
c.drawString(text_x, text_y, text)
elif 'img_path' in item:
# 如果信息是图片
img_path = item['img_path']
img_size = item.get('img_size', (200, 200))
img_pos = item.get('img_pos', (0, 0))
# 将图片绘制到页面上
c.drawImage(img_path, img_pos[0], img_pos[1], width=img_size[0], height=img_size[1])
elif 'table' in item:
# 如果信息是表格
table_data = item['table']
table_x, table_y = item.get('table_pos', (0, 0))
# 创建表格对象
table = Table(table_data)
# 定义表格样式
table_style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey), # 表头背景颜色
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), # 表头文本颜色
('ALIGN', (0, 0), (-1, -1), 'CENTER'), # 居中对齐
('FONTNAME', (0, 0), (-1, -1), 'Lishu'), # 表头字体加粗
('BOTTOMPADDING', (0, 0), (-1, 0), 12), # 表头底部边距
('BACKGROUND', (0, 1), (-1, -1), colors.beige), # 表格内容背景颜色
('GRID', (0, 0), (-1, -1), 1, colors.black), # 表格网格线
])
table.setStyle(table_style)
# 将表格插入到页面上
table.wrapOn(c, 0, 0)
table.drawOn(c, table_x, table_y)
# 保存PDF文件
c.showPage()
c.save()
# 将生成的页面添加到列表中
self.pages.append(f"temp_{self.num}.pdf")
self.num += 1
def merge_pages(self, output_path):
# 合并生成的PDF页面到最终PDF文件
pdf_merger = PdfMerger()
for page in self.pages:
pdf_merger.append(page)
pdf_merger.write(output_path)
pdf_merger.close()
def split_text(self, long_text, start_y_pos):
"""
切分字符.
pos代表文字的起始位置, 一行最多25个字符, 但是前后需各自空出两个字符, 因此一行最多21个字符. 需要自己进行位置切分
:param long_text: 长字符
:param start_y_pos: 第一行y坐标
:return:
"""
res = list()
# 首行最多19字符
if len(long_text) <= self.ling_str_num - 2:
res.append({
'text': long_text,
'pos': [24 * 4, start_y_pos],
})
start_y_pos -= 30
else:
# 进行换行切分
line_num = 0
while long_text:
if line_num == 0:
now_text = long_text[:self.ling_str_num - 2]
long_text = long_text[self.ling_str_num - 2:]
left_index = 24 * 4
else:
now_text = long_text[:self.ling_str_num]
long_text = long_text[self.ling_str_num:]
left_index = 24 * 2
res.append({
'text': now_text,
'pos': [left_index, start_y_pos - 30],
})
start_y_pos -= 30
line_num += 1
return res, start_y_pos
@staticmethod
def load_info(path):
"""
读取个人信息
:param path: 文件路径
:return:
"""
with open(path, 'r') as f:
reader = csv.DictReader(f)
return list(reader)
def gen_page_1(self):
# 一页信息
info_list = [{
'text': '河小青校园成长报告',
'font': 'Lishu',
'font_size': 36,
'font_color': (255, 0, 0), # 红色
'pos': [150, 600],
}]
long_text = '春秋更迭,四季变换,回溯刚踏入工院校园时的记忆,你是否还记得第一次见到室友时尴尬而不失礼貌的微笑、第一次军训合唱时的眼神飘忽、第一次做课堂展示汇报时大脑的忽然空白?而今,几载春秋悄然度过,你在美好时光里书写着自己的专属成长故事,在工院的岁月湖畔生动诠释着青春的含义。'
res, end_y_pos = self.split_text(long_text, 560)
info_list += res
long_text = '你的专属校园成长报告记录着你大学期间的奋斗历程,有回忆、有青春、有感动、有关爱,每一个成长的印记,成就了自信坚强,独一无二的你,请细细品味......'
res, end_y_pos = self.split_text(long_text, end_y_pos - 30)
end_y_pos -= 30
info_list += res
info_list.append({
'img_path': '学生校园成长报告/02.png',
'img_size': (516, 100),
'img_pos': (48, 80),
})
# 保存一页信息
self.add_info(info_list)
def gen_page_2(self):
my_info = self.load_info('my_info/基本信息.csv')[0]
info_list = [{
'text': '01 入校--开启逐梦之旅',
'font_size': 36,
'font_color': (255, 0, 0),
'pos': [None, 600],
}]
text_list = [
'2020年9月1日',
'怀着欣喜忐忑的心情',
'你迎来与河南工院的第一次相遇',
'解锁一个新的人生阶段',
'开启一场不负青春的逐梦之旅',
'从此,你有了新名片',
]
end_y_pos = 540
for _text in text_list:
info_list.append({
'text': _text,
'pos': [None, end_y_pos],
})
end_y_pos -= 30
info_list.append({
'img_path': '学生校园成长报告/03.png',
'img_size': (300, 200),
'img_pos': (160, end_y_pos - 200),
})
end_y_pos -= 40
for k, v in my_info.items():
info_list.append({
'text': f'{k}: {v}',
'pos': [220, end_y_pos],
'font_size': 16
})
end_y_pos -= 20
long_text = '入学时的你还是稚嫩面庞、懵懵懂懂现在的你已是风华青春、满腹志向散发出自信光芒的新时代青年'
res, end_y_pos = self.split_text(long_text, end_y_pos - 90)
end_y_pos -= 30
info_list += res
self.add_info(info_list)
def gen_page_3(self):
class_info = self.load_info('my_info/上课.csv')
info_list = [{
'text': '02 学业--为梦想而奋斗',
'font_size': 36,
'font_color': (255, 0, 0),
'pos': [None, 600],
}]
text_list = [
'台上老师娓娓道来,台下的你奋笔疾书',
'笔记上的字迹仿佛像昨天才写下',
'记录的不仅有诗和远方',
'还有课业考试和梦想大考'
]
end_y_pos = 540
for _text in text_list:
info_list.append({
'text': _text,
'pos': [None, end_y_pos],
})
end_y_pos -= 30
info_list.append({
'img_path': '学生校园成长报告/05.png',
'img_size': (500, 350),
'img_pos': (50, end_y_pos - 350),
})
end_y_pos -= 30
text_list = [
'在校期间',
f'你共学习了{len(class_info)}门课程',
f'累计{sum([int(info["课时"]) for info in class_info])}个学时,获得{len(class_info)*4}个学分',
]
for _text in text_list:
info_list.append({
'text': _text,
'pos': [220, end_y_pos],
'font_size': 18
})
end_y_pos -= 30
table_info = [['课程名称', '成绩']]
best_class_name = ''
best_clas_score = 0
for info in class_info:
table_info.append([info['课程'], info['期末考试成绩']])
if int(info['期末考试成绩']) > best_clas_score:
best_class_name = info['课程']
best_clas_score = int(info['期末考试成绩'])
end_y_pos -= 90
info_list += [{
'table': table_info,
'table_pos': (260, end_y_pos), # 表格位置
}]
text_list = [
'其中,成绩最好课程为',
f'{best_class_name},获得{best_clas_score}分',
'超过全校99%的同学',
'从中你一定懂得了“一分耕耘,一份收获”的道理',
]
end_y_pos -= 30
for _text in text_list:
info_list.append({
'text': _text,
'pos': [80, end_y_pos],
'font_size': 18
})
end_y_pos -= 30
self.add_info(info_list)
def gen_page_4(self):
info_list = [{
'text': '03 运动--突破自我极限',
'font_size': 36,
'font_color': (255, 0, 0),
'pos': [None, 600],
}]
text_list = [
'宽阔的操场上,张开你的双臂奋力奔跑',
'哨声、加油声、掌声',
'每一次肆意挥洒的汗水',
'都将凝结成你日后脸颊上的笑容'
]
end_y_pos = 540
for _text in text_list:
info_list.append({
'text': _text,
'pos': [None, end_y_pos],
})
end_y_pos -= 30
info_list.append({
'img_path': '学生校园成长报告/06.png',
'img_size': (500, 350),
'img_pos': (50, end_y_pos - 350),
})
end_y_pos -= 60
sport_info = self.load_info('my_info/体育.csv')
running_info = self.load_info('my_info/跑步.csv')
text_list = [
f'大学期间',
f'你累计跑步总里程为{sum([int(info["里程"]) for info in running_info])}公里',
f'累计跑步总次数为{len(running_info)}次',
'你在校期间的体测成绩最好的3项是:'
]
for _text in text_list:
info_list.append({
'text': _text,
'pos': [240, end_y_pos],
'font_size': 18
})
end_y_pos -= 30
table_data = [list(sport_info[0].keys())]
for info in sport_info:
table_data.append(list(info.values()))
end_y_pos -= 70
info_list += [{
'table': table_data,
'table_pos': (260, end_y_pos), # 表格位置
}]
end_y_pos -= 30
text_list = [
'生命不息,运动不止',
'大学里,你“文武”兼得',
'只要心中有梦想,脸上就有阳光'
]
for _text in text_list:
info_list.append({
'text': _text,
'pos': [240, end_y_pos],
'font_size': 18
})
end_y_pos -= 30
self.add_info(info_list)
def gen_page_5(self):
info_list = [{
'text': '04 美食--重温餐厅美味',
'font_size': 36,
'font_color': (255, 0, 0),
'pos': [None, 600],
}]
text_list = [
'当我们奔向食堂',
'唯有美食不可辜负'
'一朝一夕,一餐一饭',
'给光临的每位学子呈现出家的味道'
]
end_y_pos = 540
for _text in text_list:
info_list.append({
'text': _text,
'pos': [None, end_y_pos],
})
end_y_pos -= 30
info_list.append({
'img_path': '学生校园成长报告/07.png',
'img_size': (500, 350),
'img_pos': (50, end_y_pos - 350),
})
end_y_pos -= 60
canteen_info = self.load_info('my_info/食堂.csv')
canteen_times_info = dict()
for info in canteen_info:
if info['餐厅'] not in canteen_times_info:
canteen_times_info[info['餐厅']] = {
'times': 1,
'money': int(info['金额'])
}
else:
canteen_times_info[info['餐厅']]['times'] += 1
canteen_times_info[info['餐厅']]['money'] += int(info['金额'])
max_times_canteen = 0
max_times_canteen_name = ''
max_times_canteen_money = ''
for canteen_name, now_canteen_info in canteen_times_info.items():
if now_canteen_info['times'] > max_times_canteen:
max_times_canteen = now_canteen_info['times']
max_times_canteen_name = canteen_name
max_times_canteen_money = now_canteen_info['money']
text_list = [
'在校园期间',
f'你一共在{len(set([info["餐厅"] for info in canteen_info]))}个食堂吃过饭',
f'消费了{len(canteen_info)}次',
f'累计金额{sum([int(info["金额"]) for info in canteen_info])}元',
f'其中你最常光顾的食堂的是{max_times_canteen_name}',
f'在这里你一共刷了{max_times_canteen_money}多元',
'我们送你一个荣誉称号',
f'“{max_times_canteen_name}餐厅真爱粉”',
'有时候,嘴上说着不爱了',
'身体却不由自主',
]
for _text in text_list:
info_list.append({
'text': _text,
'pos': [240, end_y_pos],
'font_size': 18
})
end_y_pos -= 30
self.add_info(info_list)
def gen_page_6(self):
info_list = [{
'text': '05 阅读--回首阅读记忆',
'font_size': 36,
'font_color': (255, 0, 0),
'pos': [None, 600],
}]
text_list = [
'阅览室、书桌、书架、自助区......',
'图书馆的每个角落',
'都见证了你日夜的努力与坚持',
'图书馆的书香都激起过你心灵和智慧的共鸣'
]
end_y_pos = 540
for _text in text_list:
info_list.append({
'text': _text,
'pos': [None, end_y_pos],
})
end_y_pos -= 30
info_list.append({
'img_path': '学生校园成长报告/08.png',
'img_size': (500, 350),
'img_pos': (50, end_y_pos - 350),
})
end_y_pos -= 90
library_info = self.load_info('my_info/图书馆.csv')
book_kind_info = collections.defaultdict(int)
for info in library_info:
book_kind_info[info['类别']] += 1
max_times_book_kind_name = 0
max_times_book_kind = 0
for kind, times in book_kind_info.items():
if times > max_times_book_kind:
max_times_book_kind = times
max_times_book_kind_name = kind
text_list = [
library_info[0]['时间'],
'你首次踏入图书馆',
f'你借阅的第一本书是《{library_info[0]["书名"]}》',
f'你共借阅了{len(library_info)}次书',
f'你借阅的{max_times_book_kind}本{max_times_book_kind_name},',
'将助尽早实现科技强国梦',
]
for _text in text_list:
info_list.append({
'text': _text,
'pos': [300, end_y_pos],
'font_size': 18
})
end_y_pos -= 30
self.add_info(info_list)
def gen_page_7(self):
info_list = [{
'text': '06 荣誉--收获胜利果实',
'font_size': 36,
'font_color': (255, 0, 0),
'pos': [None, 600],
}]
text_list = [
'一张张荣誉证书,一次次获得奖金',
'是对自己的肯定',
'也是对努力学习最好的回报',
'承载着你大学时期的心血与智慧'
]
end_y_pos = 540
for _text in text_list:
info_list.append({
'text': _text,
'pos': [None, end_y_pos],
})
end_y_pos -= 30
info_list.append({
'img_path': '学生校园成长报告/09.png',
'img_size': (500, 350),
'img_pos': (50, end_y_pos - 350),
})
end_y_pos -= 90
bursary_info = self.load_info('my_info/奖学金.csv')
compe_info = self.load_info('my_info/比赛.csv')
info_1 = f'包括{"`".join(set([info["名称"] for info in bursary_info]))},共计{sum(int(info["金额"]) for info in bursary_info)}元;'.split('`')
info_2 = f'包括{"`".join(set([info["名称"] for info in compe_info]))},共计{sum(int(info["金额"]) for info in compe_info)}元。'.split('`')
info_2.append('还有参加各种专业技能竞赛获得奖金')
text_list = ['在校期间,你获得了多种奖学金']
text_list += info_1
text_list += info_2
text_list += [
'为你的优秀而点赞、为你的成功而喜悦',
'未来的日子,请继续砥砺前行',
'超越自我,成就更高的梦想!',
]
for _text in text_list:
info_list.append({
'text': _text,
'pos': [260, end_y_pos],
'font_size': 14
})
end_y_pos -= 30
self.add_info(info_list)
def gen_page_8(self):
info_list = [{
'text': '07 寄语--寄希望启征程',
'font_size': 36,
'font_color': (255, 0, 0),
'pos': [None, 600],
}]
text_list = [
'亲爱的河小青',
'趁青春正盛,勇敢地前进',
'万般祝福赠予你',
'心中有梦,以梦为马',
'志存高远,不负韶华',
'前途似海,未来无限',
'愿今后的你',
'眼中有风景,心中有温暖',
'诗意底色常伴,艳阳高照永随',
'长空万里任你展翅翱翔',
'碧海无涯随你乘风破浪',
]
end_y_pos = 540
for _text in text_list:
info_list.append({
'text': _text,
'pos': [None, end_y_pos],
})
end_y_pos -= 30
info_list.append({
'img_path': '学生校园成长报告/10.png',
'img_size': (516, 100),
'img_pos': (48, 80),
})
self.add_info(info_list)
def run(self):
"""
pdf左下角为坐标(0,0), 往右x递增, 往上y递增
"""
print(f'pdf_size: {letter}')
# pdfmetrics.registerFont(TTFont('Lishu', r'C:\Windows\Fonts\SIMLI.TTF'))
pdfmetrics.registerFont(TTFont('Lishu', '/System/Library/AssetsV2/com_apple_MobileAsset_Font7/9d5450ee93f17da1eacfa01b5e7b598f9e2dda2b.asset/AssetData/Baoli.ttc'))
self.gen_page_1()
print('gen page 1 success!')
self.gen_page_2()
print('gen page 2 success!')
self.gen_page_3()
print('gen page 3 success!')
self.gen_page_4()
print('gen page 4 success!')
self.gen_page_5()
print('gen page 5 success!')
self.gen_page_6()
print('gen page 6 success!')
self.gen_page_7()
print('gen page 7 success!')
self.gen_page_8()
print('gen page 8 success!')
print('gen all page success!')
self.merge_pages('output.pdf')
if __name__ == '__main__':
t = PDFGenerator('学生校园成长报告/01-02.png')
t.run()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。