文章目录

  • 前言
  • 一、python与word
    • 课前准备
    • 初步认识docx
    • 整体页面结构介绍
    • 字体设置
    • 插入图片与表格
    • 设置页眉页脚
    • 代码延伸
    • 项目实践
  • 二、python和pdf
    • 相关介绍
    • 批量拆分
    • 批量合并
    • 提取文字内容
    • 提取表格内容
    • 提取图片内容
    • 转换为图片
      • 安装 pdf2image
      • 安装组件
      • 添加水印
      • 文档加密与解密
      • 页面旋转
  • 总结

前言

本篇文章主要讲解了python与word和pdf,介绍了在word中如何使用python进行字体设置、插入图片与表格等常规操作,以及在pdf中使用python进行批量合并、拆分以及提取文字内容、表格内容等操作。


一、python与word

课前准备

python 处理 Word 需要用到 python-docx 库,需要注意的是pythonn-docx不支持doc文档,终端执行如下安装命令:

pip3 install python-docx
或
conda install python-docx

初步认识docx

# 导入库
from docx import Document# 新建空白文档
doc_1 = Document()# 添加标题(0相当于文章的题目,默认级别是1,级别范围为0-9)
doc_1.add_heading('新建空白文档标题,级别为0',level = 0)
doc_1.add_heading('新建空白文档标题,级别为1',level = 1)
doc_1.add_heading('新建空白文档标题,级别为2',level = 2)# 新增段落
paragraph_1 = doc_1.add_paragraph('这是第一段文字的开始\n请多多关照!')
# 加粗
paragraph_1.add_run('加粗字体').bold = True
paragraph_1.add_run('普通字体')
# 斜体
paragraph_1.add_run('斜体字体').italic =True# 新段落(当前段落的下方)
paragraph_2 = doc_1.add_paragraph('新起的第二段文字。')# 新段落(指定端的上方)
prior_paragraph = paragraph_1.insert_paragraph_before('在第一段文字前插入的段落')# 添加分页符(可以进行灵活的排版)
doc_1.add_page_break()
# 新段落(指定端的上方)
paragraph_3 = doc_1.add_paragraph('这是第二页第一段文字!')# 保存文件(当前目录下)
doc_1.save('doc_1.docx')



在操作之前,我们需要了解 Word 文档的页面结构 :

  • 文档 - Document
  • 段落 - Paragraph
  • 文字块 - Run

python-docx将整个文章看做是一个Document 对象 ,其基本结构如下:

  • 每个 Document包含许多个代表“段落”的Paragraph 对象,存放在 document.paragraphs 中。
  • 每个 Paragraph都有许多个代表"行内元素"的Run对象,存放在paragraph.runs 中。

python-docx中,run是最基本的单位,每个run对象内的文本样式都是一致的,也就是说,在从docx文件生成文档对象时,python-docx 会根据样式的变化来将文本切分为一个个的Run对象。

整体页面结构介绍

# 导入库
from docx import Document
from docx.shared import RGBColor, Pt,Inches,Cm
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn# 新建文档(Datawhale)
doc_1 = Document()# 字体设置(全局)
'''只更改font.name是不够的,还需要调用._element.rPr.rFonts的set()方法。'''doc_1.styles['Normal'].font.name = u'宋体'
doc_1.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')# 添加标题(0相当于文章的题目,默认级别是1,级别范围为0-9,0时候自动带下划线)
#WD_ALIGN_PARAGRAPH. LEFT:左对齐;
#WD_ALIGN_PARAGRAPH. CENTER:居中对其;
#WD_ALIGN_PARAGRAPH. RIGHT:右对齐;
#WD_ALIGN_PARAGRAPH. JUSTIFY:两端对齐;
heading_1 = doc_1.add_heading('周杰伦',level = 0)
heading_1.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER   #居中对齐,默认居左对齐# 新增段落
paragraph_1 = doc_1.add_paragraph()
'''
设置段落格式:首行缩进0.75cm,居左,段后距离1.0英寸,1.5倍行距。
'''
paragraph_1.paragraph_format.first_line_indent = Cm(0.75)
paragraph_1.paragraph_format.alignment =  WD_PARAGRAPH_ALIGNMENT.LEFT
paragraph_1.paragraph_format.space_after =  Inches(1.0)
paragraph_1.paragraph_format.line_spacing =  1.5text = '中国台湾华语流行歌手、' \'音乐创作家、作曲家、作词人、' \'制作人、杰威尔音乐公司老板之一、导演。' \'近年涉足电影行业。周杰伦是2000年后亚洲流行乐坛最具革命性与指标' \'性的创作歌手,有“亚洲流行天王”之称。他突破原有亚洲音乐的主题、形' \'式,融合多元的音乐素材,创造出多变的歌曲风格,尤以融合中西式曲风的嘻哈' \'或节奏蓝调最为著名,可说是开创华语流行音乐“中国风”的先声。周杰伦的' \'出现打破了亚洲流行乐坛长年停滞不前的局面,为亚洲流行乐坛翻开了新的一页!'r_1 = paragraph_1.add_run(text)
r_1.font.size =Pt(10)    #字号
r_1.font.bold =True       #加粗
r_1.font.color.rgb =RGBColor(255,0,0)      #颜色print(len(paragraph_1.runs))    # 查看段落拥有的run对象数量
print(paragraph_1.runs[0].text)  # 查看对应run对象的文本等属性# 保存文件(当前目录下)
doc_1.save('周杰伦.docx')
1
中国台湾华语流行歌手、音乐创作家、作曲家、作词人、制作人、杰威尔音乐公司老板之一、导演。近年涉足电影行业。周杰伦是2000年后亚洲流行乐坛最具革命性与指标性的创作歌手,有“亚洲流行天王”之称。他突破原有亚洲音乐的主题、形式,融合多元的音乐素材,创造出多变的歌曲风格,尤以融合中西式曲风的嘻哈或节奏蓝调最为著名,可说是开创华语流行音乐“中国风”的先声。周杰伦的出现打破了亚洲流行乐坛长年停滞不前的局面,为亚洲流行乐坛翻开了新的一页!


最小的操作对象为文字块,通过run的指定进行操作。比如字号,颜色等;而再上一个层级–段落是的格式是通过paragraph_format进行设置。

字体设置

通过上个例子,我们已经注意到,字体的设置是全局变量。如果我想在不同的部分进行不同字体的设置,那该怎么办呢?这就需要在应用前操作设置一下。

'''字体设置1.py'''
#导入库
from docx import Document
from docx.oxml.ns import qn
from docx.enum.style import WD_STYLE_TYPEdocument = Document() # 新建docx文档# 设置宋体字样式
style_font = document.styles.add_style('宋体', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '宋体'
document.styles['宋体']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')# 设置楷体字样式
style_font = document.styles.add_style('楷体', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '楷体'
document.styles['楷体']._element.rPr.rFonts.set(qn('w:eastAsia'), u'楷体')# 设置华文中宋字样式
style_font = document.styles.add_style('华文中宋', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '华文中宋'
document.styles['华文中宋']._element.rPr.rFonts.set(qn('w:eastAsia'), u'华文中宋')paragraph1 = document.add_paragraph() # 添加段落
run = paragraph1.add_run(u'aBCDefg这是中文', style='宋体') # 设置宋体样式font = run.font #设置字体
font.name = 'Cambira' # 设置西文字体
paragraph1.add_run(u'aBCDefg这是中文', style='楷体').font.name = 'Cambira'
paragraph1.add_run(u'aBCDefg这是中文', style='华文中宋').font.name = 'Cambira'document.save('字体设置1.docx')

'''字体设置2.py'''
#导入库
from docx import Document
from docx.oxml.ns import qn
from docx.enum.style import WD_STYLE_TYPE#定义字体设置函数
def font_setting(doc,text,font_cn):style_add = doc.styles.add_style(font_cn, WD_STYLE_TYPE.CHARACTER)style_add.font.name = font_cndoc.styles[font_cn]._element.rPr.rFonts.set(qn('w:eastAsia'), font_cn)par = doc.add_paragraph()text = par.add_run(text, style=font_cn)doc = Document()
a = '小朋友 你是否有很多问号'
b = '为什么 别人在那看漫画'
c = '我却在学画画 对着钢琴说话'font_setting(doc,a,'宋体')
font_setting(doc,b,'华文中宋')
font_setting(doc,c,'黑体')doc.save('字体设置2.docx')

字体设置1.py与字体设置2.py的区别在于是否为同一段落,同时字体设置2.py中自定义了一个函数。我们可以在实际工作中看具体场景进行选择。

插入图片与表格

#导入库
import docx
from docx import Document
from docx.shared import Inches#打开文档
doc_1 = Document('周杰伦.docx')   #上面脚本存储的文档
#新增图片
doc_1.add_picture('周杰伦.jpg',width=Inches(1.0), height=Inches(1.0))# 创建3行1列表格
table1 = doc_1.add_table(rows=2, cols=1)
table1.style='Medium Grid 1 Accent 1'  #表格样式很多种,如,Light Shading Accent 1等# 修改第2行第3列单元格的内容为营口
table1.cell(0, 0).text = '营口'
# 修改第3行第4列单元格的内容为人民
table1.rows[1].cells[0].text = '人民'# 在表格底部新增一行
row_cells = table1.add_row().cells
# 新增行的第一列添加内容
row_cells[0].text = '加油'doc_1.save('周杰伦为营口加油.docx')

设置页眉页脚

在python-docx包中则要使用节(section)中的页眉(header)和页脚(footer)对象来具体设置。

from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENTdocument = Document() # 新建文档header = document.sections[0].header # 获取第一个节的页眉
print('页眉中默认段落数:', len(header.paragraphs))
paragraph = header.paragraphs[0] # 获取页眉的第一个段落
paragraph.add_run('这是第一节的页眉') # 添加页面内容
footer = document.sections[0].footer # 获取第一个节的页脚
paragraph = footer.paragraphs[0] # 获取页脚的第一个段落
paragraph.add_run('这是第一节的页脚') # 添加页脚内容'''在docx文档中又添加了2个节,共计3个节,页面和页脚会显示了“与上一节相同”。
如果不使用上一节的内容和样式要将header.is_linked_to_previous的属性或footer.is_linked_to_previous的属性设置为False,
用于解除“链接上一节页眉”或者“链接上一节页脚”。'''
document.add_section() # 添加一个新的节
document.add_section() # 添加第3个节
header = document.sections[1].header # 获取第2个节的页眉
header.is_linked_to_previous = False # 不使用上节内容和样式#对齐设置
header = document.sections[1].header # 获取第2个节的页眉
header.is_linked_to_previous = False # 不使用上节内容和样式
paragraph = header.paragraphs[0]
paragraph.add_run('这是第二节的页眉')
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置页眉居中对齐
document.sections[1].footer.is_linked_to_previous = False
footer.paragraphs[0].add_run('这是第二节的页脚') # 添加第2节页脚内容
footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置第2节页脚居中对齐
header = document.sections[2].header # 获取第3个节的页眉
header.is_linked_to_previous = False # 不使用上节的内容和样式
paragraph = header.paragraphs[0] # 获取页眉中的段落
paragraph.add_run('这是第三节的页眉')
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT # 设置页眉右对齐
document.sections[2].footer.is_linked_to_previous = False
footer.paragraphs[0].add_run('这是第三节的页脚') # 添加第3节页脚内容
footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT # 设置第3节页脚右对齐
document.save('页眉页脚1.docx') # 保存文档
页眉中默认段落数: 1

代码延伸

'''Document的其他常用方法'''
#添加无序列表
document.add_paragraph('前面是圆点', style='List Bullet')
#添加有序列表
document.add_paragraph('前面是数字', style='List Number')
#添加分页符
document.add_page_break()
#添加节
document.add_section()
#设置样式
document.styles.add_style('textstyle', WD_STYLE_TYPE. PARAGRAPH)'''对齐设置'''
from docx.enum.text import WD_ALIGN_PARAGRAPH
#LEFT: 左对齐
#CENTER: 文字居中
#RIGHT: 右对齐
#JUSTIFY: 文本两端对齐'''设置段落行距'''
from docx.shared import Length
# SINGLE :单倍行距(默认)
#ONE_POINT_FIVE : 1.5倍行距
# DOUBLE2 : 倍行距
#AT_LEAST : 最小值
#EXACTLY:固定值
# MULTIPLE : 多倍行距paragraph.line_spacing_rule = WD_LINE_SPACING.EXACTLY #固定值
paragraph_format.line_spacing = Pt(18) # 固定值18磅
paragraph.line_spacing_rule = WD_LINE_SPACING.MULTIPLE #多倍行距
paragraph_format.line_spacing = 1.75 # 1.75倍行间距'''设置字体属性'''
from docx.shared import RGBColor,Pt
#all_caps:全部大写字母
#bold:加粗
#color:字体颜色#double_strike:双删除线
#hidden : 隐藏
#imprint : 印记
#italic : 斜体
#name  :字体
#shadow  :阴影
#strike  :  删除线
#subscript  :下标
#superscript  :上标
#underline  :下划线

项目实践

参会人名单:

邀请函:

根据参会人名单,利用python批量生成邀请函。

# 导入库
from openpyxl import load_workbook
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import RGBColor, Pt,Inches,Cm
from docx.oxml.ns import qnpath = r'F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF'
# 路径为Excel 文件所在的位置,可按实际情况更改workbook = load_workbook(path + r'\excel到word.xlsx')
sheet = workbook.active   #默认的WorkSheetn = 0   #为了不遍历标题(excel的第一行)
for row in sheet.rows:if n:company = row[0].valueoffice = row[1].valuename = row[2].valuedate = str(row[3].value).split()[0]print(company, office, name, date)doc = Document()heading_1 = '邀 请 函'paragraph_1 = doc.add_heading(heading_1, level=1)# 居中对齐paragraph_1.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER# 单独修改较大字号for run in paragraph_1.runs:run.font.size = Pt(17)greeting_word_1 = '尊敬的'greeting_word_2 = '公司'greeting_word_3 = ',您好:'paragraph_2 = doc.add_paragraph()paragraph_2.add_run(greeting_word_1)r_1 = paragraph_2.add_run(company)r_1.font.bold = True  # 加粗r_1.font.underline = True    #下划线paragraph_2.add_run(greeting_word_2)r_2 = paragraph_2.add_run(office)r_2.font.bold = True  # 加粗r_2.font.underline = True    #下划线r_3 = paragraph_2.add_run(name)r_3.font.bold = True  # 加粗r_3.font.underline = True    #下划线paragraph_2.add_run(greeting_word_3)paragraph_3 = doc.add_paragraph()paragraph_3.add_run('现诚挚的邀请您于2021年10月27日参加DataWhale主办的享受开源2050活动,地点在北京鸟巢,希望您届时莅临参加。')paragraph_3.paragraph_format.first_line_indent = Cm(0.75)paragraph_3.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFTparagraph_3.paragraph_format.space_after = Inches(1.0)paragraph_3.paragraph_format.line_spacing = 1.5paragraph_4 = doc.add_paragraph()date_word_1 = '邀请时间:'paragraph_4.add_run(date_word_1)paragraph_4.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHTsign_date = "{}年{}月{}日".format(date.split('-')[0], date.split('-')[1], date.split('-')[2])paragraph_4.add_run(sign_date).underline = Trueparagraph_4.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT#设置全文字体for paragraph in doc.paragraphs:for run in paragraph.runs:run.font.color.rgb = RGBColor(0, 0, 0)run.font.name = '楷体'r = run._element.rPr.rFontsr.set(qn('w:eastAsia'), '楷体')doc.save(path + "\{}-邀请函.docx".format(name))n = n + 1
阿里 数据工程师 刘云 2022-07-17
腾讯 数据分析师 刘雨 2022-07-18
京东 数据架构师 刘二 2022-07-19
百度 算法工程师 苏苏 2022-07-20

本案例也可适用于批量生产固定格式的word,如工资条,通知单等,面对这种相似且重复的任务,python的自动化运行能大幅提升当前的工作效率。

二、python和pdf

相关介绍

Python 操作 PDF 会用到两个库,分别是:PyPDF2 和 pdfplumber.

其中 PyPDF2 可以更好的读取、写入、分割、合并PDF文件,而 pdfplumber 可以更好的读取 PDF 文件中内容和提取 PDF 中的表格。

对应的官网分别是:

PyPDF2:https://pythonhosted.org/PyPDF2/

pdfplumber:https://github.com/jsvine/pdfplumber

由于这两个库都不是 Python 的标准库,所以在使用之前都需要单独安装。

win+r 后输入 cmd 打开 command 窗口,依次输入如下命令进行安装:

pip install PyPDF2

pip install pdfplumber

安装完成后显示 success 则表示安装成功。

批量拆分

将一个完整的 PDF 拆分成几个小的 PDF,因为主要涉及到 PDF 整体的操作,所以本小节需要用到 PyPDF2 这个库。

拆分的大概思路如下:

  • 读取 PDF 的整体信息、总页数等;
  • 遍历每一页内容,以每个 step 为间隔将 PDF 存成每一个小的文件块;
  • 将小的文件块重新保存为新的 PDF 文件。

需要注意的是,在拆分的过程中,可以手动设置间隔,例如:每5页保存成一个小的 PDF 文件。

import os
from PyPDF2 import PdfFileWriter, PdfFileReaderdef split_pdf(filename, filepath, save_dirpath, step=5):"""拆分PDF为多个小的PDF文件,@param filename:文件名@param filepath:文件路径@param save_dirpath:保存小的PDF的文件路径@param step: 每step间隔的页面生成一个文件,例如step=5,表示0-4页、5-9页...为一个文件@return:"""if not os.path.exists(save_dirpath):os.mkdir(save_dirpath)pdf_reader = PdfFileReader(filepath)# 读取每一页的数据pages = pdf_reader.getNumPages()for page in range(0, pages, step):pdf_writer = PdfFileWriter()# 拆分pdf,每 step 页的拆分为一个文件for index in range(page, page+step):if index < pages:pdf_writer.addPage(pdf_reader.getPage(index))# 保存拆分后的小文件save_path = os.path.join(save_dirpath, filename+str(int(page/step)+1)+'.pdf')print(save_path)with open(save_path, "wb") as out:pdf_writer.write(out)print("文件已成功拆分,保存路径为:"+save_dirpath)filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
save_dirpath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告【拆分】')
split_pdf(filename, filepath, save_dirpath, step=5)
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf1.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf2.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf3.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf4.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf5.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf6.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf7.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf8.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf9.pdf
F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】\易方达中小盘混合型证券投资基金2020年中期报告.pdf10.pdf
文件已成功拆分,保存路径为:F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告【拆分】

以“易方达中小盘混合型证券投资基金2020年中期报告”为例,整个 PDF 文件一共 46 页,每5页为间隔,最终生成了10个小的 PDF 文件。

批量合并

比起拆分来,合并的思路更加简单:

  • 确定要合并的 文件顺序
  • 循环追加到一个文件块中;
  • 保存成一个新的文件。
import os
from PyPDF2 import PdfFileReader, PdfFileWriterdef concat_pdf(filename, read_dirpath, save_filepath):"""合并多个PDF文件@param filename:文件名@param read_dirpath:要合并的PDF目录@param save_filepath:合并后的PDF文件路径@return:"""pdf_writer = PdfFileWriter()# 对文件名进行排序list_filename = os.listdir(read_dirpath)list_filename.sort(key=lambda x: int(x[:-4].replace(filename, "")))for filename in list_filename:print(filename)filepath = os.path.join(read_dirpath, filename)# 读取文件并获取文件的页数pdf_reader = PdfFileReader(filepath)pages = pdf_reader.getNumPages()# 逐页添加for page in range(pages):pdf_writer.addPage(pdf_reader.getPage(page))# 保存合并后的文件with open(save_filepath, "wb") as out:pdf_writer.write(out)print("文件已成功合并,保存路径为:"+save_filepath)filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
read_dirpath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告【拆分】')
save_filepath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告-合并后.pdf')
concat_pdf(filename, read_dirpath, save_filepath)
易方达中小盘混合型证券投资基金2020年中期报告.pdf1.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf2.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf3.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf4.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf5.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf6.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf7.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf8.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf9.pdf
易方达中小盘混合型证券投资基金2020年中期报告.pdf10.pdf
文件已成功合并,保存路径为:F:\桌面\office-automation-main-20220709160400\office-automation-main\Task03-Python与Word和PDF\易方达中小盘混合型证券投资基金2020年中期报告-合并后.pdf

提取文字内容

涉及到具体的 PDF 内容操作,本小节需要用到 pdfplumber 这个库。

在进行文字提取的时候,主要用到 extract_text 这个函数。

import os
import pdfplumberdef extract_text_info(filepath):"""提取PDF中的文字@param filepath:文件路径@return:"""with pdfplumber.open(filepath) as pdf:# 获取第2页数据page = pdf.pages[1]print(page.extract_text())filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
# 提取文字内容
extract_text_info(filepath)
易方达中小盘混合型证券投资基金2020年中期报告
1重要提示及目录
1.1  重要提示
基金管理人的董事会、董事保证本报告所载资料不存在虚假记载、误导性陈述或重大遗漏,并
对其内容的真实性、准确性和完整性承担个别及连带的法律责任。本中期报告已经三分之二以上独
立董事签字同意,并由董事长签发。
基金托管人中国银行股份有限公司根据本基金合同规定,于2020年8月26日复核了本报告中
的财务指标、净值表现、利润分配情况、财务会计报告、投资组合报告等内容,保证复核内容不存
在虚假记载、误导性陈述或者重大遗漏。
基金管理人承诺以诚实信用、勤勉尽责的原则管理和运用基金资产,但不保证基金一定盈利。
基金的过往业绩并不代表其未来表现。投资有风险,投资者在作出投资决策前应仔细阅读本基
金的招募说明书及其更新。
本报告中财务资料未经审计。
本报告期自2020年1月1日起至6月30日止。
第2页共46页

可以看到,直接通过下标即可定位到相应的页码,从而通过 extract_text 函数提取该页的所有文字。

而如果想要提取所有页的文字,只需要改成:

with pdfplumber.open(filepath) as pdf:# 获取全部数据for page in pdf.pagesprint(page.extract_text())

提取表格内容

同样的,本节是对具体内容的操作,所以也需要用到 pdfplumber 这个库。

和提取文字十分类似的是,提取表格内容只是将 extract_text 函数换成了 extract_table 函数。

import os
import pandas as pd
import pdfplumberdef extract_table_info(filepath):"""提取PDF中的图表数据@param filepath:@return:"""with pdfplumber.open(filepath) as pdf:# 获取第18页数据page = pdf.pages[17]# 如果一页有一个表格,设置表格的第一行为表头,其余为数据table_info = page.extract_table()df_table = pd.DataFrame(table_info[1:], columns=table_info[0])df_table.to_csv('dmeo.csv', index=False, encoding='gbk')filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
# 提取表格内容
extract_table_info(filepath)


上面代码可以获取到第 18 页的第一个表格内容,并且将其保存为 csv 文件存在本地。

但是,如果说第 18 页有多个表格内容呢?

因为读取的表格会被存成二维数组,而多个二维数组就组成一个三维数组。

遍历这个三维数组,就可以得到该页的每一个表格数据,对应的将 extract_table 函数 改成 extract_tables 即可。

import os
import pandas as pd
import pdfplumberdef extract_table_info(filepath):"""提取PDF中的图表数据@param filepath:@return:"""with pdfplumber.open(filepath) as pdf:# 获取第7页数据page = pdf.pages[6]# 如果一页有多个表格,对应的数据是一个三维数组tables_info = page.extract_tables()for index in range(len(tables_info)):# 设置表格的第一行为表头,其余为数据df_table = pd.DataFrame(tables_info[index][1:], columns=tables_info[index][0])df_table.to_csv('dmeo.csv', index=False, encoding='gbk')filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
# 提取表格内容
extract_table_info(filepath)

提取图片内容

提取 PDF 中的图片和将 PDF 转存为图片是不一样的(下一小节),需要区分开。

提取图片:顾名思义,就是将内容中的图片都提取出来;
转存为图片:则是将每一页的 PDF 内容存成一页一页的图片.

转存为图片中,需要用到一个模块叫 fitz,fitz 的最新版 1.18.13,非最新版的在部分函数名称上存在差异,代码中会标记出来。

使用 fitz 需要先安装 PyMuPDF 模块,安装方式如下:

pip install PyMuPDF

提取图片的整体逻辑如下:

  • 使用 fitz 打开文档,获取文档详细数据;
  • 遍历每一个元素,通过正则找到图片的索引位置;
  • 使用 Pixmap 将索引对应的元素生成图片;
  • 通过 size 函数过滤较小的图片。
import os
import re
import fitzdef extract_pic_info(filepath, pic_dirpath):"""提取PDF中的图片@param filepath:pdf文件路径@param pic_dirpath:要保存的图片目录路径@return:"""if not os.path.exists(pic_dirpath):os.makedirs(pic_dirpath)# 使用正则表达式来查找图片check_XObject = r"/Type(?= */XObject)"check_Image = r"/Subtype(?= */Image)"img_count = 0"""1. 打开pdf,打印相关信息"""pdf_info = fitz.open(filepath)# 1.16.8版本用法 xref_len = doc._getXrefLength()# 最新版本xref_len = pdf_info.xref_length()# 打印PDF的信息print("文件名:{}, 页数: {}, 对象: {}".format(filepath, len(pdf_info), xref_len-1))"""2. 遍历PDF中的对象,遇到是图像才进行下一步,不然就continue"""for index in range(1, xref_len):# 1.16.8版本用法 text = doc._getXrefString(index)# 最新版本text = pdf_info.xref_object(index)is_XObject = re.search(check_XObject, text)is_Image = re.search(check_Image, text)# 如果不是对象也不是图片,则不操作if is_XObject or is_Image:img_count += 1# 根据索引生成图像pix = fitz.Pixmap(pdf_info, index)pic_filepath = os.path.join(pic_dirpath, 'img_' + str(img_count) + '.png')"""pix.size 可以反映像素多少,简单的色素块该值较低,可以通过设置一个阈值过滤。以阈值 10000 为例过滤"""# if pix.size < 10000:#     continue"""三、 将图像存为png格式"""if pix.n >= 5:# 先转换CMYKpix = fitz.Pixmap(fitz.csRGB, pix)# 存为PNG#pix.writePNG(pic_filepath)pix.save(pic_filepath)filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
pic_dirpath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告【文中图片】')
# 提取图片内容
extract_pic_info(filepath, pic_dirpath)

转换为图片

安装 pdf2image

首先需要安装对应的库,最新的 pdf2image 库版本应该是 1.14.0。

它的github地址为:https://github.com/Belval/pdf2image。

安装方式如下:

pip install pdf2image

安装组件

对于不同的平台,需要安装相应的组件,这里以 windows 平台和 mac 平台为例:

Windows 平台

对于 windows 用户需要安装 poppler for Windows,安装链接是:http://blog.alivate.com.au/poppler-windows/

另外,还需要添加环境变量, 将 bin 文件夹的路径添加到环境变量 PATH 中

注意这里配置之后需要重启一下电脑才会生效,不然会报如下错误:

Mac

对于 mac 用户,需要安装 poppler for Mac,具体可以参考这个链接:http://macappstore.org/poppler/

import os
from pdf2image import convert_from_path, convert_from_bytesdef convert_to_pic(filepath, pic_dirpath):"""每一页的PDF转换成图片@param filepath:pdf文件路径@param pic_dirpath:图片目录路径@return:"""print(filepath)if not os.path.exists(pic_dirpath):os.makedirs(pic_dirpath)images = convert_from_bytes(open(filepath, 'rb').read())# images = convert_from_path(filepath, dpi=200)for image in images:# 保存图片pic_filepath = os.path.join(pic_dirpath, 'img_'+str(images.index(image))+'.png')image.save(pic_filepath, 'PNG')# PDF转换为图片
#convert_to_pic(filepath, pic_dirpath)filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
pic_dirpath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告【转换为图片】')
# PDF转换为图片
convert_to_pic(filepath, pic_dirpath)

添加水印

PDF 中添加水印,首先需要一个水印PDF文件,然后依次通过 mergePage 操作将每一页的 PDF 文件合并到水印文件上,据此,每一页的 PDF 文件将是一个带有水印的 PDF 文件。

最后,将每一页的水印 PDF 合并成一个 PDF 文件即可。

生成水印

生成水印的方式比较多,例如在图片添加水印,然后将图片插入到 word 中,最后将 word 保存成 PDF 文件即可

生成一张 A4 纸大小的空白图片,参考这篇文章:Python 批量加水印!轻松搞定! 给图片添加水印。

然后将图片插入到 word 中并最终生成一个水印 PDF 文档。

import os
from copy import copy
from PyPDF2 import PdfFileReader, PdfFileWriterdef add_watermark(filepath, save_filepath, watermark_filepath):"""添加水印@param filepath:PDF文件路径@param save_filepath:最终的文件保存路径@param watermark_filepath:水印PDF文件路径@return:""""""读取PDF水印文件"""# 可以先生成一个空白A4大小的png图片,通过 https://mp.weixin.qq.com/s/_oJA6lbsdMlRRsBf6DPxsg 教程的方式给图片加水印,将图片插入到word中并最终生成一个水印PDF文档watermark = PdfFileReader(watermark_filepath)watermark_page = watermark.getPage(0)pdf_reader = PdfFileReader(filepath)pdf_writer = PdfFileWriter()for page_index in range(pdf_reader.getNumPages()):current_page = pdf_reader.getPage(page_index)# 封面页不添加水印if page_index == 0:new_page = current_pageelse:new_page = copy(watermark_page)new_page.mergePage(current_page)pdf_writer.addPage(new_page)# 保存水印后的文件with open(save_filepath, "wb") as out:pdf_writer.write(out)filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
save_filepath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告-水印.pdf')
watermark_filepath = os.path.join(os.getcwd(), 'watermark.pdf')
# 添加水印
add_watermark(filepath, save_filepath, watermark_filepath)

文档加密与解密

import os
from PyPDF2 import PdfFileReader, PdfFileWriterdef encrypt_pdf(filepath, save_filepath, passwd='xiaoyi'):"""PDF文档加密@param filepath:PDF文件路径@param save_filepath:加密后的文件保存路径@param passwd:密码@return:"""pdf_reader = PdfFileReader(filepath)pdf_writer = PdfFileWriter()for page_index in range(pdf_reader.getNumPages()):pdf_writer.addPage(pdf_reader.getPage(page_index))# 添加密码pdf_writer.encrypt(passwd)with open(save_filepath, "wb") as out:pdf_writer.write(out)filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
save_filepath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告-加密后.pdf')
# 文档加密
encrypt_pdf(filepath, save_filepath, passwd='xiaoyi')

针对已经加密的 PDF 文件,也可以使用 decrypt 函数进行解密操作:

def decrypt_pdf(filepath, save_filepath, passwd='xiaoyi'):"""解密 PDF 文档并且保存为未加密的 PDF@param filepath:PDF文件路径@param save_filepath:解密后的文件保存路径@param passwd:密码@return:"""pdf_reader = PdfFileReader(filepath)# PDF文档解密pdf_reader.decrypt('xiaoyi')pdf_writer = PdfFileWriter()for page_index in range(pdf_reader.getNumPages()):pdf_writer.addPage(pdf_reader.getPage(page_index))with open(save_filepath, "wb") as out:pdf_writer.write(out)filename = '易方达中小盘混合型证券投资基金2020年中期报告-加密后.pdf'
filepath = os.path.join(os.getcwd(), filename)
save_filepath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告-解密后.pdf')
# 文档解密
decrypt_pdf(filepath, save_filepath, passwd='xiaoyi')

解密完成后的 PDF 文档打开后不再需要输入密码,如需加密可再次执行加密代码。

页面旋转

利用 rotateClockwise()和 rotateCounterClockwise()方法可以对pdf页面进行90度及其倍数的旋转。

import PyPDF2filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
save_filepath = os.path.join(os.getcwd(), '易方达中小盘混合型证券投资基金2020年中期报告-旋转.pdf')
pdf_reader = PdfFileReader(filepath)
page = pdf_reader.getPage(0)
page.rotateClockwise(90)
pdf_writer = PdfFileWriter()
pdf_writer.addPage(page)
with open(save_filepath, "wb") as out:pdf_writer.write(out)

总结

本篇文章主要讲解了python与word和pdf,介绍了在word中如何使用python进行字体设置、插入图片与表格等常规操作,以及在pdf中使用python进行批量合并、拆分以及提取文字内容、表格内容等操作,从讲解到代码实操,再到项目实践,收获颇丰!

Task 03:python与word和pdf相关推荐

  1. Task 03 python与word

    3.0 课前准备 python 处理 Word 需要用到 python-docx 库,终端执行如下安装命令: pyhton pip3 install python-docx 或 conda insta ...

  2. python处理word或者pdf文件_利用python程序生成word和PDF文档的方法

    一.程序导出word文档的方法 将web/html内容导出为world文档,再java中有很多解决方案,比如使用Jacob.Apache POI.Java2Word.iText等各种方式,以及使用fr ...

  3. Python从Word/PPT/PDF中抽取图片

    Python从Word/PPT/PDF中抽取图片 PS 1:也是从网上各个帖子中学习的代码,因此代码的格式以及内容有粘贴网上其他大神的代码,如有侵权请告知删除 2:本次设计意在用pyinstaller ...

  4. 【python操作word和pdf】

    python操作word和pdf 一.python操作word 1.python新建word文档及常规操作 2.python对word的字体设置 3.python向word插入图片和表格 4.pyth ...

  5. Task 03 python自动化之word操作

    1.课前准备 """学习路径均来源于DataWhale"" python 处理 Word 需要用到 python-docx 库,终端执行如下安装命令: ...

  6. python制作word转PDF工具

    工作需要,要将大量的word文件转为PDF文件,但是WPS动不动收费还强制加水印,所以就自己简单做了一个 1.运行案例 2.所需模块 pip install pypiwin32 pip install ...

  7. python生成word 带目录_利用python程序生成word和PDF文档的方法

    一.程序导出word文档的方法 将web/html内容导出为world文档,再java中有很多解决方案,比如使用Jacob.Apache POI.Java2Word.iText等各种方式,以及使用fr ...

  8. python读写word、pdf文档

    处理PDF和Word文档 用于处理PDF的模块是PyPDF2. 处理Word文档是python-docx模块,要安装python-docx,但是导入模块时是写import docx. 1.从PDF提取 ...

  9. python操作word、pdf问题汇总

    问题1. pyPdf2操作pdf出现: 'latin-1' codec can't encode characters in position 8-9: ordinal not in range(25 ...

  10. Word处理控件Aspose.Words功能演示:在 Python 中将 Word DOCX 或 DOC 转换为 PDF

    Word 到PDF是最流行和执行最广泛的文档转换之一.DOCX或DOC文件在打印或共享之前会转换为 PDF 格式.在本文中,我们将在 Python 中自动将 Word 转换为 PDF.步骤和代码示例将 ...

最新文章

  1. Iptables 表和链之间的关系【未完成】
  2. 2059-authentication plugin 'caching_sha2_passwordcnnot bt loaded :mysql8.0数据库链接不上:
  3. EventHandler, EventArgs
  4. Centos7使用yum安装MySQL5.6的正确姿势
  5. python正则r的作用_Python正则表达式,这一篇就够了!
  6. [eclipse]Syntax error on token ;,{ expected after this token
  7. Java 使用Commons-fileupload组件实现上传
  8. 电脑记事本增强版notepad++
  9. Android主板串口线接法,9针rs232串口接线图以及接线方法
  10. 控制网平差(C++实现)
  11. linux uwf开放80端口,SELinux - osc_a3uwfsx7的个人空间 - OSCHINA - 中文开源技术交流社区...
  12. autoit java_AutoIt3客户端和Java服务器端TCP通信
  13. 微信小程序——云开发|计费方式调整大家怎么看?
  14. 苹果M1 Mac 如何卸载 iPhone 和 iPad 应用程序?
  15. 千兆光模块的类型都有哪些?
  16. 【Unity3D插件】KGFMapSystem插件分享《快速制作小地图插件》
  17. Halcon OCR字符识别
  18. 最好用的Python网页抓取工具包!
  19. 每个程序员都必须知道的Unicode以及字节码最基础的知识
  20. 面经分享!一线互联网公司面试及求职建议

热门文章

  1. 使用云函数+云调用,四步实现微信支付
  2. 微擎支持html微信支付,微信小程序云开发:现已原生支持微信支付
  3. php搭建聊天室,php聊天室_用PHP MySQL搭建聊天室
  4. 高斯滤波器讲解(python实现)
  5. Euraka学习笔记
  6. 奥维地图电脑端手机端不能用了,有没有可替代的地图工具
  7. u2000网管服务器系统安装,U2000网管预安装后无法登陆
  8. latex中png、pdf和eps格式的图片文件转换
  9. 【推荐】PHP各种开源网站系统、cms系统一览[持续更新]
  10. Linux | 文件系统 | Ext2fs