背景

​ 网页上的培训材料,内容全是PPT页面图片。直接通过浏览器打印,会存在只打印第一页,并且把浏览器上无效信息也打印出来情况。但目标是希望将页面图片全部打印为pdf形式。

实现方案

  1. 利用网页“另存为”,将页面内所有图片资源下载到本地;
  2. 利用页面html源码,解析出图片下载名与标准名之间对应关系;
  3. 格式化标准名,按文件名顺序排序;
  4. 按文件名顺序合并所有图片到一个pdf文件中。

技术点

  1. 利用BS4解析html文档
  2. 利用PIL的Image合并图片到pdf

操作步骤

  1. 打开页面并选择“另存为”。

  2. 保存到F:\course目录下

  3. 将所有图片文件复制到tmp目录

    通过分析页面图片,所有有效图片都是后缀为JPG格式的图片。

  4. 运行read_html.py文件,标准化tmp目录下图片文件名

    1、使用img标签下的alt文件名替换tmp目录下文件名。(本处实现,发现下载图片文件名为src下文件名,但alt属性中文件名更便于理解和排序)

    2、将文件名中编号规整,保持3位数字。(本处实现,最大的序号为366;名称为“幻灯片2.JPG”的会显示在“幻灯片11.JPG”的后面,需要将“幻灯片2.JPG’和”幻灯片11.JPG“规整为”幻灯片002.JPG”和”幻灯片011.JPG“)

  5. 运行merge_img2pdf.py文件,将tmp目录下所有图片合并成一个pdf文件

源代码及注释

# content of read_html.py# 解析本地html文件,并将图片文件标准化命名import reimport osfrom bs4 import BeautifulSoupdef main():img_dict = {}soup = BeautifulSoup(open('个人中心-云阅读_希赛网.html')) # 读取另存为生成的html文件imgs = soup.find_all('img') # 获取所有img标签for img in imgs:if len(img['alt']) == 0:# 过滤掉img标签中alt属性内容为空的字段continuereal_name = img['alt']if len(real_name) == 9: # 标准化img文件名,全部变为"幻灯片XXX.JPG"形式real_name = real_name[0:3]+'0'+real_name[3:]elif len(real_name) == 8:real_name = real_name[0:3]+'00'+real_name[3:]img_dict[os.path.basename(img['src'])] = real_name# 构造字典,key为下载到本地的文件名,value为易读的待修改后的文件名print(img_dict)os.chdir('tmp') # 切换到tmp目录下for old_file_name, new_file_name in img_dict.items():if os.path.exists(old_file_name): # 若实际文件存在才进行更名try:# 增加异常捕获,alt属性名称存在同名情况,有发生异常风险。os.rename(old_file_name,new_file_name)# 重命令文件except:passif __name__ == "__main__":main()
# content of merge_img2pdf.py# 遍历tmp下所有jpg文件,并在运行目录下生成pdf文件from io import BytesIOfrom PIL import Imageimport osdef get_file_list():file_list = []for file in os.listdir(): # 遍历目录下所有JPG或jpg文件,并保存到file_list列表中,列表中图片顺序根据文件名称排序。if file.endswith('JPG') or file.endswith('jpg'):file_list.append(file)return file_listdef convert_to_pdf(file_list:list):sources = []output = Image.open(file_list[0]) # Image中加入第一张图片print(file_list)file_list.pop(0) # 从列表中去除第一张图片for file in file_list:file = Image.open(file) # 逐张打开图片if file.mode == "RGB":file = file.convert("RGB")sources.append(file) # 并添加到sources列表中os.chdir('..') # 返回程序运行目录output.save("output.pdf","pdf",save_all=True,append_images=sources) # 保存图片到pdf文件中,创建output时已经设置了第一张图片,append_images列表中按顺序保存了其它图片内容。def main():os.chdir('tmp') # 进入tmp目录下file_list = get_file_list()convert_to_pdf(file_list)if __name__ == "__main__":main()

后续优化

  • 目前是通过命令行方式运行,可以考虑通过pyside6做页面。
  • 当前只适配了希赛一个网站,根据后续需求增加程序的适配图片格式。