task3 python与word和pdf

一、python与word(仅仅针对遇到的问题)

1.1统揽python操作word(word的文档页面三剑客)

word文档页面结构三剑客,基本过程为:首先创建一个空白文档,然后在空白文档建段落对象,最后针对文字块进行操作。

在这里插入图片描述

创建空白文档用: doc_1 = Document()

增加标题用:doc_1.add_heading() 。另外,标题有0-9的级别范围,0级别的标题有下划线。

创建段落对象用:paragraph_1=doc_1.add_paragraph()
文字块的东西用paragraph_1.add_run(),括号里面为添加的文本内容

1.2字体的设置

字体设置包括全局设置和局部设置:
全局设置:

# 字体设置(全局)
'''只更改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'宋体')

局部设置:

# 设置宋体字样式
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'

设置后的结果为英语字符处对应的字体为Cambira西文字体,中文部分”这是中文“分别对应三种不同的字体

1.3插入图片遇到的问题

在插入图片部分,我遇到一个问题就是一开始插入的图片过大导致图片在插入docx的时候报错:
在这里插入图片描述
解决方法是裁剪图片或者选择更小尺寸的图片

1.4深入体会项目实战

项目实践部分真的很实用,实现了自动化书写邀请函。
代码:

# 导入库
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 qn

workbook = load_workbook(r'excel到word.xlsx')
sheet = workbook.active   #默认的WorkSheet

n = 0   #为了不遍历标题(excel的第一行)
for row in sheet.rows:
    if n:
        company = row[0].value
        office = row[1].value
        name = row[2].value
        date = 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.LEFT
        paragraph_3.paragraph_format.space_after = Inches(1.0)
        paragraph_3.paragraph_format.line_spacing = 1.5

        paragraph_4 = doc.add_paragraph()
        date_word_1 = '邀请时间:'
        paragraph_4.add_run(date_word_1)
        paragraph_4.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
        sign_date = "{}年{}月{}日".format(date.split('-')[0], date.split('-')[1], date.split('-')[2])
        paragraph_4.add_run(sign_date).underline = True
        paragraph_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.rFonts
                r.set(qn('w:eastAsia'), '楷体')
        doc.save( "{}-邀请函.docx".format(name))
    n = n + 1

最终运行结果为生成四份邀请函:
在这里插入图片描述
具有很强的实际意义

1.5 一些零散的知识总结

知识汇总:在操作word的过程中依然用到了模块:最大的模块依然是docx模块,基于此模块可以导入以下子模块(最常用):
在这里插入图片描述
1、进行空白文档的创建,导入模块中的Document

2、进行字体颜色的设置(RGBColor),一些方便的距离模块(Pt,Inches,Cm),方便设置相应的像素。

3、方便进行文本格式的设置:
居中(WD_PARAGRAPH_ALIGNMENT.CENTER),
居左(WD_PARAGRAPH_ALIGNMENT.LEFT),
居右(WD_ALIGN_PARAGRAPH. RIGHT)。

4、字体格式的设置需要导入qn。

5、最后就是各种内置的函数还需要自己去多多总结。

二、python与pdf(测试代码+运行结果)

2.1批量拆分

代码:

import os
from PyPDF2 import PdfFileWriter, PdfFileReader

def 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)

运行结果:
在这里插入图片描述
在这里插入图片描述
期间遇到的问题:

2.2批量合并

代码:

import os
from PyPDF2 import PdfFileReader, PdfFileWriter

def 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)

运行结果:
在这里插入图片描述
拆分后的pdf全部合并生成新的合并后的pdf。

2.3提取文字内容

import os
import pdfplumber

def extract_text_info(filepath):
    """
    提取PDF中的文字
    @param filepath:文件路径
    @return:
    """
    with pdfplumber.open(filepath) as pdf:
        # 获取第3页数据
        page = pdf.pages[2]
        print(page.extract_text())
        
filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
# 提取文字内容
extract_text_info(filepath)

运行结果:
在这里插入图片描述

2.4 提取表格内容(获取第18页数据和第7页数据)

代码:
获取第18页数据

import os
import pandas as pd
import pdfplumber

def 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)

运行结果:
在这里插入图片描述
获取第7页数据
代码:

import os
import pandas as pd
import pdfplumber

def 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('dmeo1.csv', index=False, encoding='gbk')
        
filename = '易方达中小盘混合型证券投资基金2020年中期报告.pdf'
filepath = os.path.join(os.getcwd(), filename)
# 提取表格内容
extract_table_info(filepath)

运行结果:
在这里插入图片描述

2.5 提取pdf中的图片

代码:

import os
import re
import fitz

def 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:
                # 先转换CMYK
                pix = fitz.Pixmap(fitz.csRGB, pix)
            # 存为PNG
            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)

运行结果:
在这里插入图片描述

2.6 转换为图片

代码:

import os
from pdf2image import convert_from_path, convert_from_bytes

def 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的页数)
在这里插入图片描述

2.7 添加水印

代码:

import os
from copy import copy
from PyPDF2 import PdfFileReader, PdfFileWriter

def 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_page
        else:
            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)

运行结果(此处的水印依然是xiaoyi的水印)
在这里插入图片描述

2.8 文档加密与解密

import os
from PyPDF2 import PdfFileReader, PdfFileWriter

def 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='bxj')

运行结果:
在这里插入图片描述

2.9 页面翻转

代码:

import PyPDF2

filename = '易方达中小盘混合型证券投资基金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)

运行结果:
在这里插入图片描述

2.10 一些零散的知识总结

1、操作PDF常用的两个库:PyPDF2(可以更好地读取、写入、分割和合并PDF);pdfplumber(进行PDF内容的读取和表格内容的读取)

2、文字提取的过程中主要用到 extract_text 这个函数,即通过下标对应相应的页码,然后利用此函数进行文字内容的提取

3、提取表格中的文字与提取文字的过程类似,只是将 extract_text 函数换成了 extract_table 函数

4、提取图片的整体逻辑也很巧妙
在这里插入图片描述
用到如下三个模块
在这里插入图片描述
re正则表达式模块令我印象很深刻(课后需要总结与复习),在这里它用来匹配数据是否是图片。

5、将PDF转换成图片。(待继续思考总结)

6、加密还挺有趣的,核心函数为encrypt(),就可以对对应的文档进行加密操作。

7、翻转,主要是rotateClockwise()函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值