Python中有不少处理PDF文件的第三方库,如果只是简单的拼接、裁剪、加水印的话,笔者推荐使用PyPDF2(最新的有一个PyPdf4,差别不大,语法基本通用),纯Python库,用起来简单又方便,说明文档从头到尾看一遍都花不了多久。

这个库最大的一个坑就是解密文件,不过也有解决办法,文章正文中会给出具体方案。如果不想踩这个坑的读者可以直接去学另一个库pikepdf,该库是基于qpdf的,没有文件解密方面的困扰,同时功能也比PyPDF2更全。笔者之所以没有用该库,是因为之前已经学过了PyPDF2,懒得学新的。

该库的官方文档中只有各个类的定义说明,没有相关的示例演示,部分功能还需要实际操作或者阅读源码才能彻底搞清楚,笔者这里根据自己的测试结果挑选了一些使用频率较高的功能整合成了一篇快速开始文档供读者参考。

官方英文文档地址:

https://pythonhosted.org/PyPDF2/

演示素材下载地址:

链接:https://pan.baidu.com/s/1ma1WFGJW3vYWqGzS6d2kEw

提取码:qzqk

读取PDF文件

读取文件有两种形式,一种是直接传入文件对象(必须以二进制形式读取),另一种是传入文件路径的字符串,推荐使用第一种:

import PyPDF2 as pdf

input = open('example.pdf', 'rb')
pr = pdf.PdfFileReader(input)
...
input.close()
with open('example.pdf', 'rb') as input:
    pr = pdf.PdfFileReader(input)
    ...
input = 'example.pdf'
pr = pdf.PdfFileReader(input)
...

执行上述操作之后可以通过如下命令检验文件是否被加密:

pr.isEncrypted
>>>
True

若结果为True则需要输入密码对文档进行解密操作。PDF文件有两种密码,打开密码和修改密码,此处只需要其中的任意一个即可:

pr.decrypt('weizhineng')
>>>
Traceback (most recent call last):
  File "", line 1, in 
  File "C:\Users\acec-pc\AppData\Local\Programs\Python\Python38-32\lib\site-packages\PyPDF2\pdf.py", line 1987, in decryptreturn self._decrypt(password)
  File "C:\Users\acec-pc\AppData\Local\Programs\Python\Python38-32\lib\site-packages\PyPDF2\pdf.py", line 1996, in _decryptraise NotImplementedError("only algorithm code 1 and 2 are supported")
NotImplementedError: only algorithm code 1 and 2 are supported

由于PyPDF2许久没有进行过大的更新,其对PDF文件的解密算法也停留在几年前,目前主流的PDF加密文件基本都无法正常解密。

如果碰到与上面类似的解密错误可以引入qpdf这一命令行工具包,通过Python中的os.system() 来调用相关命令先对PDF解密后再重新使用PyPDF2读取解密后的文件。

读者可以从下面的qpdf官方网站下载工具包后解压使用,推荐解压后将其中bin文件夹的地址添加到系统环境变量中,方便命令行调用。

http://qpdf.sourceforge.net/

使用qpdf解密PDF文件的命令行语句格式如下:

qpdf --password=[密码] --decrypt [待解密文件的路径] [解密后输出文件的路径]

示例如下:

qpdf --password=weizhineng --decrypt example.pdf out.pdf

Python中可以使用如下函数统一读取文件:

import os
import PyPDF2 as pdf
from tempfile import TemporaryFile

def read_pdf(filename, password = None):
    # 读取PDF文件,创建PdfFileReader实例
    # 参数:
    # filename(str)-PDF文件路径
    # password(str)-PDF文件密码(可选参数)
    # 返回值:
    # pr(PdfFileReader)-从该文件创建的PdfFileReader实例
    file = open(filename, 'rb')
    temp1 = TemporaryFile()#创建临时文件
    temp1.write(file.read())#向临时文件中写入文件内容
    pr = pdf.PdfFileReader(temp1)
    file.close()
    if pr.isEncrypted:
        if password == None:
            password = ''
        try:
            command = 'qpdf --password=%s --decrypt %s temp.pdf' % (password, filename)#qpdf解密命令
            os.system(command)
            temp2 = TemporaryFile()
            temp_pdf = open('temp.pdf', 'rb')
            temp2.write(temp_pdf.read())
            pr = pdf.PdfFileReader(temp2)
            temp_pdf.close()
            os.remove('temp.pdf')#删除命令行指令解密生成的解密文件
        except:
            raise ImportError(u'文件密码错误')
    return pr

filename = 'example.pdf'
password = 'weizhineng'
pr = read_pdf(filename, password)

获取文档信息

检索PDF文件的文档信息,如果PDF文件使用元数据流而不是文档信息字典的形式则此功能失效:

doc_info = pr.getDocumentInfo()
print(doc_info)
>>>
{'/Author': 'acec-pc', '/Comments': '', '/Company': '', '/CreationDate': "D:20200725174707+09'47'", '/Creator': 'WPS 文字', '/Keywords': '', '/ModDate': "D:20200725174707+09'47'", '/Producer': '', '/SourceModified': "D:20200725174707+09'47'", '/Subject': '', '/Title': '', '/Trapped': '/False'}

获取文档页数

获取PDF文件的总页数:

num_pages = pr.getNumPages()
# num_pages = pr.numPages
print(num_pages)
>>>
2

获取文档大纲

获取PDF文件的大纲:

outlines = pr.getOutlines()
# outlines = pr.outlines
print(outlines)
>>>
[{'/Title': 'Example', '/Page': IndirectObject(6, 0), '/Type': '/XYZ', '/Left': 90, '/Top': 752.9, '/Zoom': 0}, [{'/Title': 'Section 1', '/Page': IndirectObject(6, 0), '/Type': '/XYZ', '/Left': 90, '/Top': 699, '/Zoom': 0}, {'/Title': 'Section 2', '/Page': IndirectObject(6, 0), '/Type': '/XYZ', '/Left': 90, '/Top': 220.6, '/Zoom': 0}, {'/Title': 'Section 3', '/Page': IndirectObject(34, 0), '/Type': '/XYZ', '/Left': 90, '/Top': 769.9, '/Zoom': 0}]]

获取文档中页面

根据索引数字获取PDF文档中对应页面:

single_page = pr.getPage(0)
print(type(single_page))
>>>
<class 'PyPDF2.pdf.PageObject'>

获取单页尺寸

可以通过PageObject的mediaBox属性获取页面的尺寸参数,长和宽的单位皆为用户默认空间单位(default user space units),一般来讲就是points:

width = single_page.mediaBox.getWidth()
height = single_page.mediaBox.getHeight()
print(width, height)
>>>
595.3 841.9

一般PDF文件都适用如下定义:

1 pt = 1 / 72 inch
1 inch = 25.4 mm

简单换算一下即可得到上述示例中的页面尺寸为A4(即210 mm×297 mm),其他规格尺寸均可按此方法进行换算。

获取单页中文本内容

按照在内容流中提供的顺序找到所有文本绘制命令,然后提取文本。 这对于某些PDF文件效果很好,但对其他PDF文件效果不佳,具体取决于所使用的生成器。 将来会对此进行完善。 不要依赖此功能产生的文本顺序,因为如果此功能变得更复杂,它将改变。示例如下:

single_page.extractText()
>>>
'&Ì˝ª7-'

此方法检索到的文本内容经常出现乱码现象,甚至有时什么都检索不到。如果读者真的有读取PDF中文本内容的需求,最好采用更加健壮的其他方法。笔者在此有两个推荐:

  • pdfminer:专门用于PDF解析的Python第三方库。
  • pdftotext:开源工具包,可以通过命令行控制。

获取多页最容易想到的方法就是使用for语句,结合上面的getNumPages()以及getPage()方法;另一种就是使用该库作者定义好的类(原理也是使用上面提到的那两个方法),支持遍历、切片、索引等操作:

type(pr.pages)
>>>
<class 'PyPDF2.utils.ConvertFunctionsToVirtualList'>
for page in pr.pages:
    print(type(page))
>>>
<class 'PyPDF2.pdf.PageObject'>
<class 'PyPDF2.pdf.PageObject'>
pr.pages[0] == pr.getPage(0)
>>>
True
len(pr.pages) == pr.numPages
>>>
True

PageObject对象可以通过如下代码进行缩放:

single_page.scale(0.5, 1)#横、纵坐标缩放指定倍数
single_page.scaleBy(0.5)#横、纵坐标同时缩放相同倍数
single_page.scaleTo(419.5, 595.3)#缩放到指定宽和高

PageObject对象可以通过如下代码进行旋转:

single_page.rotateClockwise(90)#顺时针旋转,角度为90倍数
single_page.rotateCounterClockwise(90)#逆时针旋转,角度为90倍数

PageObject可以通过调整mediaBox四个角的坐标值来对页面大小进行裁剪,默认坐标系示意如下:

注意:如果页面经历过旋转操作,坐标系也会一同旋转,横版页面进行页面裁剪前最好先确认一下坐标系方向。

以裁剪右半部分页面为例,代码如下:

width = single_page.mediaBox.getWidth()
height = single_page.mediaBox.getHeight()
single_page.mediaBox.lowerLeft = (width/2, 0)
single_page.mediaBox.lowerRight = (width, 0)
single_page.mediaBox.upperLeft = (width/2, height)
single_page.mediaBox.upperRight = (width, height)

合并页面(加水印)

可以将两个页面合并为一个页面,被合并页面(即参数页面)会被置于上层。这一功能最常见的应用就是添加水印,进行添加水印操作之前首先需要准备水印PDF文件,推荐使用Word或者PS制作后转换为PDF。示例如下:

water_page = read_pdf('watermark.pdf').getPage(0)
water_page.mergePage(single_page)

注意:此处两个页面的顺序一定不能搞反,不然会出现水印遮盖住正文的现象。按照上面的代码顺序的话,最终合成页的尺寸会与水印文件一致,因此如果两个页面尺寸大小不一致的话最好先行调整大小,以免出现不想看到的情况。

输出PDF文件

创建PdfFileWriter实例

要输出PDF文件首先需要创建一个PdfFileWriter实例:

pw = pdf.PdfFileWriter()

通过PdfFileReader读取修改过后的PageObject可以添加到PdfFileWriter中用于最终输出文件:

pw.addPage(single_page)#在文件最后添加页面
pw.insertPage(water_page, 0)#在指定页数插入页面

添加空白页方法:

pw.addBlankPage(width = None, height = None)#在文件最后添加空白页
pw.insertBlankPage(width = None, height = None, index = 0)#在指定页数插入空白页

插入方法默认在文件开头插入与文件最后一页尺寸相同的空白页,也可以指定宽、高和插入位置。如果当前文件中没有页面且没有指定空白页尺寸,则会报错。

批量导入页面

PdfFileWriter可以一次导入PdfFileReader中的所有页面,默认添加到文件末尾:

pw.appendPagesFromReader(pr)

添加密码只需要一行代码,不过只能添加128位或者40位的加密算法,重要文档的话还是使用别的软件来加密比较好:

#pw.encrypt(user_pwd, owner_pwd = None, use_128bit = True)
pw.encrypt('weizhineng')

保存文件的方法非常简单:

with open('out.pdf', 'wb') as out:
    pw.write(out)

比较常用的操作,运行代码之前最好先确认待添加水印文件和水印文件的页面尺寸是否相同。

import os
import PyPDF2 as pdf
from tempfile import TemporaryFile

def read_pdf(filename, password = None):
    # 读取PDF文件,创建PdfFileReader实例
    # 参数:
    # filename(str)-PDF文件路径
    # password(str)-PDF文件密码(可选参数)
    # 返回值:
    # pr(PdfFileReader)-从该文件创建的PdfFileReader实例
    file = open(filename, 'rb')
    temp1 = TemporaryFile()#创建临时文件
    temp1.write(file.read())#向临时文件中写入文件内容
    pr = pdf.PdfFileReader(temp1)
    file.close()
    if pr.isEncrypted:
        if password == None:
            password = ''
        try:
            command = 'qpdf --password=%s --decrypt %s temp.pdf' % (password, filename)#qpdf解密命令
            os.system(command)
            temp2 = TemporaryFile()
            temp_pdf = open('temp.pdf', 'rb')
            temp2.write(temp_pdf.read())
            pr = pdf.PdfFileReader(temp2)
            temp_pdf.close()
            os.remove('temp.pdf')#删除命令行指令解密生成的解密文件
        except:
            raise ImportError(u'文件密码错误')
    return pr

def watermark(original_file, watermark_file, password1 = None, password2 = None):
    # 为目标文件添加水印,返回PdfFileWriter实例
    # 注意:输出文档页面尺寸与水印文件页面尺寸相同
    # 参数:
    # original_file(str)-待添加水印文件
    # watermark_file(str)-水印文件
    # password1(str)-待添加水印文件密码
    # password2(str)-水印文件密码
    # 返回值:
    # pw(PdfFileWriter)-添加水印后的文件
    pr1 = read_pdf(original_file, password1)
    pw = pdf.PdfFileWriter()
    for page in pr1.pages:
        watermark_page = read_pdf(watermark_file, password2).getPage(0)
        watermark_page.mergePage(page)
        pw.addPage(watermark_page)
    return pw

if __name__ == '__main__':
    original_file = 'example.pdf'
    password1 = 'weizhineng'
    watermark_file = 'watermark.pdf'
    pw = watermark(original_file, watermark_file, password1)
    with open('out.pdf', 'wb') as out:
        pw.write(out)

扫描件偶尔会出现一页纸上有左右两页的情况,阅读起来较为麻烦,这时候可以将其左右裁开,方法也很简单。

import copy

def divide_two(page, mode = 'LR', ratio = 0.5):
    # 将一个PageObject实例分为左右或上下两个PageObject实例,可设置左右或上下部分的占比
    # 参数:
    # page(PageObject)-待分割的页面
    # mode(str)-分割模式,LR代表左右分割,UD代表上下分割
    # ratio(float)-分割后左侧或上侧页面所占比例
    # 返回值:
    # page1, page2(tuple)-page1左侧或上侧部分页面,page2右侧或下侧部分页面
    page1 = copy.copy(page)#创建页面副本
    page2 = copy.copy(page)
    width = float(page.mediaBox.getWidth())#获取页面当前宽度
    height = float(page.mediaBox.getHeight())#获取页面当前高度
    if mode == 'LR':#左右分割模式
        page1.mediaBox.lowerLeft = (0, 0)
        page1.mediaBox.lowerRight = (width * ratio, 0)
        page1.mediaBox.upperLeft = (0, height)
        page1.mediaBox.upperRight = (width * ratio, height)
        page2.mediaBox.lowerLeft = (width * ratio, 0)
        page2.mediaBox.lowerRight = (width, 0)
        page2.mediaBox.upperLeft = (width * ratio, height)
        page2.mediaBox.upperRight = (width, height)
    elif mode == 'UD':#上下分割模式
        page1.mediaBox.lowerLeft = (0, height * (1 - ratio))
        page1.mediaBox.lowerRight = (width, height * (1 - ratio))
        page1.mediaBox.upperLeft = (0, height)
        page1.mediaBox.upperRight = (width, height)
        page2.mediaBox.lowerLeft = (0 ,0)
        page2.mediaBox.lowerRight = (width, 0)
        page2.mediaBox.upperLeft = (0, height * (1 - ratio))
        page2.mediaBox.upperRight = (width, height * (1 - ratio))
    else:
        raise SyntaxError(u'裁剪模式错误,LR或UD')
    return page1, page2

if __name__ == '__main__':
    filename = 'example.pdf'
    password = 'weizhineng'
    pr = read_pdf(filename, password)
    pw = pdf.PdfFileWriter()
    for page in pr.pages:
        page1, page2 = divide_two(page, 'LR', 0.5)
        pw.addPage(page1)
        pw.addPage(page2)
    with open('out.pdf', 'wb') as out:
        pw.write(out)

有时需要对页面尺寸进行缩放,例如上面示例中页面分割后,但是直接使用scale可能会让页面上内容的横纵比发生变化,笔者在下面对常用的缩放功能进行了函数封装:

def smart_scale(page, page_size, scale_width = None, scale_height = None, location = 'M', lower_left = None):
    # 将缩放到指定尺寸的页面内容放入指定尺寸的页面的指定位置,返回新页面
    # 参数:
    # page(PageObject)-待缩放页面
    # page_size(tuple)-最终返回页面的尺寸(宽,高)元组
    # scale_width(float)-页面内容缩放至的宽度。
    #     与scale_height配合使用,两者都为None时
    #     默认保持页面内容纵横比缩放至最终页面所能呈现的最大尺寸。
    #     两参数给定一个时另一参数默认按照原始纵横比计算得到
    # scale_height(float)-页面内容缩放至的高度
    # location(str)-缩放后的页面内容在最终页面中的位置,默认居中
    #     有效位置参数如下:
    #     M     上下居中,左右居中
    #     U     向上对齐,左右居中
    #     D     向下对齐,左右居中
    #     L     上下居中,向左对齐
    #     R     上下居中,向右对齐
    #     UL    对齐左上角点
    #     UR    对齐右上角点
    #     DL    对齐左下角点
    #     DR    对齐右下角点
    # lower_left(tuple)-指定页面内容左下角点在最终页面上的(x,y)坐标。
    #     可选参数,生效时无效化location参数
    # 返回值:
    # final_page(PageObject)-缩放后的最终页面
    page1 = copy.copy(page)
    width = float(page1.mediaBox.getWidth())#获取页面当前宽度
    height = float(page1.mediaBox.getHeight())#获取页面当前高度
    # 先对页面内容进行缩放
    if scale_width == None and scale_height == None:
        if page_size[0] / width > page_size[1] / height:
            scale_width = page_size[1] / height * width
            scale_height = page_size[1]
        else:
            scale_width = page_size[0]
            scale_height = page_size[0] / width * height
    else:
        if scale_width == None:
            scale_width = scale_height / height * width
        elif scale_height == None:
            scale_height = scale_width / width * height
    page1.scaleTo(scale_width, scale_height)
    # 然后对页面尺寸和位置进行调整
    if lower_left == None:
        if location == 'M':
            page1.mediaBox.lowerLeft = ((scale_width - page_size[0]) / 2, (scale_height - page_size[1]) / 2)
            page1.mediaBox.lowerRight = ((scale_width + page_size[0]) / 2, (scale_height - page_size[1]) / 2)
            page1.mediaBox.upperLeft = ((scale_width - page_size[0]) / 2, (scale_height + page_size[1]) / 2)
            page1.mediaBox.upperRight = ((scale_width + page_size[0]) / 2, (scale_height + page_size[1]) / 2)
        elif location == 'U':
            page1.mediaBox.lowerLeft = ((scale_width - page_size[0]) / 2, scale_height - page_size[1])
            page1.mediaBox.lowerRight = ((scale_width + page_size[0]) / 2, scale_height - page_size[1])
            page1.mediaBox.upperLeft = ((scale_width - page_size[0]) / 2, scale_height)
            page1.mediaBox.upperRight = ((scale_width + page_size[0]) / 2, scale_height)
        elif location == 'D':
            page1.mediaBox.lowerLeft = ((scale_width - page_size[0]) / 2, 0)
            page1.mediaBox.lowerRight = ((scale_width + page_size[0]) / 2, 0)
            page1.mediaBox.upperLeft = ((scale_width - page_size[0]) / 2, page_size[1])
            page1.mediaBox.upperRight = ((scale_width + page_size[0]) / 2, page_size[1])
        elif location == 'L':
            page1.mediaBox.lowerLeft = (0, (scale_height - page_size[1]) / 2)
            page1.mediaBox.lowerRight = (page_size[0], (scale_height - page_size[1]) / 2)
            page1.mediaBox.upperLeft = (0, (scale_height + page_size[1]) / 2)
            page1.mediaBox.upperRight = (page_size[0], (scale_height + page_size[1]) / 2)
        elif location == 'R':
            page1.mediaBox.lowerLeft = (scale_width - page_size[0], (scale_height - page_size[1]) / 2)
            page1.mediaBox.lowerRight = (scale_width, (scale_height - page_size[1]) / 2)
            page1.mediaBox.upperLeft = (scale_width - page_size[0], (scale_height + page_size[1]) / 2)
            page1.mediaBox.upperRight = (scale_width, (scale_height + page_size[1]) / 2)
        elif location == 'UL':
            page1.mediaBox.lowerLeft = (0, scale_height - page_size[1])
            page1.mediaBox.lowerRight = (page_size[0], scale_height - page_size[1])
            page1.mediaBox.upperLeft = (0, scale_height)
            page1.mediaBox.upperRight = (page_size[0], scale_height)
        elif location == 'UR':
            page1.mediaBox.lowerLeft = (scale_width - page_size[0], scale_height - page_size[1])
            page1.mediaBox.lowerRight = (scale_width, scale_height - page_size[1])
            page1.mediaBox.upperLeft = (scale_width - page_size[0], scale_height)
            page1.mediaBox.upperRight = (scale_width, scale_height)
        elif location == 'DL':
            page1.mediaBox.lowerLeft = (0, 0)
            page1.mediaBox.lowerRight = (page_size[0], 0)
            page1.mediaBox.upperLeft = (0, page_size[1])
            page1.mediaBox.upperRight = (page_size[0], page_size[1])
        elif location == 'DR':
            page1.mediaBox.lowerLeft = (scale_width - page_size[0], 0)
            page1.mediaBox.lowerRight = (scale_width, 0)
            page1.mediaBox.upperLeft = (scale_width - page_size[0], page_size[1])
            page1.mediaBox.upperRight = (scale_width, page_size[1])
        else:
            raise SyntaxError(u'location参数错误')
    else:
        page1.mediaBox.lowerLeft = (-1 * lower_left[0], -1 * lower_left[1])
        page1.mediaBox.lowerRight = (page_size[0] - lower_left[0], -1 * lower_left[1])
        page1.mediaBox.upperLeft = (-1 * lower_left[0], page_size[1] - lower_left[1])
        page1.mediaBox.upperRight = (page_size[0] - lower_left[0], page_size[1] - lower_left[1])
    return page1

if __name__ == '__main__':
    filename = 'example.pdf'
    password = 'weizhineng'
    pr = read_pdf(filename, password)
    pw = pdf.PdfFileWriter()
    for page in pr.pages:
        page1 = smart_scale(page, (500, 1000), scale_height = 800, location = 'M')
        pw.addPage(page1)
    with open('out.pdf', 'wb') as out:
        pw.write(out)

使用上一节中页面分割函数后再使用此缩放函数可以让最终切割出的PDF文件更加美观且规范。

PyPDF2其实自带一个PdfFileMerger类,但是笔者按照它的示例代码操作后却只能得到页数相等的空白文档,不过其实也无所谓,使用PdfFileReader和PdfFileWriter两个类也可以完成一样的操作,代码如下:

if __name__ == '__main__':
    # 读取两个需要合并的PDF文件
    pr1 = read_pdf('example.pdf', 'weizhineng')
    pr2 = read_pdf('watermark.pdf')
    pw = pdf.PdfFileWriter()
    # 需要导入部分页面时采用此种方法
    # 通过range来指定需要的页面
    for i in range(pr1.getNumPages()):
        pw.addPage(pr1.getPage(i))
    # 需要导入全部页面时采用此种方法
    pw.appendPagesFromReader(pr2)
    # 保存为PDF文件
    with open('out.pdf', 'wb') as out:
        pw.write(out)
Python中有不少处理PDF文件的第三方库,如果只是简单的拼接、裁剪、加水印的话,笔者推荐使用PyPDF2(最新的有一个PyPdf4,差别不大,语法基本通用),纯Python库,用起来简单又方便,说明文档从头到尾看一遍都花不了多久。这个库最大的一个坑就是解密文件,不过也有解决办法,文章正文中会给出具体方案。如果不想踩这个坑的读者可以直接去学另一个库pikepdf,该库是基于qpdf的,... 需求:生成 pdf 格式的证书,证书其实是有个模板的(下面测试我随便做了一个),不过内容(主要是证书上的文字)需要自己动态填写 语言: python 引入库: PyPDF2 - 负责读写和合并 pdf ; ( PyPDF2 1.26.0) reportlab - 负责绘画(创建)生成一个新的 pdf (reportlab 3.5.67) 基于 Python 3.6.8 思路:使用reportlab的canvas根据坐标(以左下角为原点,使得整个 pdf page在第一象限. 下面两句话是本文的重点,文中的内容都是围绕下面两句话展开的 1. 乱码 的本质是字符的编码格式与显示字符的环境编码格式不一致引起的。这句话告诉我们要解决 乱码 问题,我们需要知道两个信息,一个是字符本身是什么编码,另一个就是显示字符的环境编码是什么,两者必须一致,才能显示出正确的内容。 2.在 python 中,对于任何Unicode类型编码的字符,打印时会自动根据环境编码转为特定编码后再显示。 接下来,看看字符在 python 代码中是如何被编码的。在不 from PyPDF2 import Pdf FileReader, Pdf FileWriter def split_ pdf (fileName, result, start=0, end=None): #打开原始 pdf 文件 pdf _src = Pdf FileReader(fileName) if end is None: #获取页数 end = pdf _src.getNumPages() with open( 有监督学习:有标签。输入数据有标注。 无监督学习:无标签。输入数据无标注。 两者有不同之处:有监督学习分训练集和测试集,在训练集中找规律,在测试集中用找到的规律测试找的对不对;无监督学习没有训练集,在这组数据里自行寻找规律。 何时采用何种方法:从定义出发,有训练样本参考则考虑采用监督学习 线性回归是回归问题中的一种,研究因变量和. 先说说项目背景,本菜鸡是搞故障诊断的,所以免不了用上一些统计学的知识,看过之前我的Blog的都会发现,T2T^2T2 和 SPESPESPE 在故障诊断邻域或者说是再小范围一点,在过程监控邻域,是很好用且很关键的两个统计量,用于监测过程中的一些有故障的检测点或者区间,会有阈值限,超过阈值的则判断为故障,反而,则为正常。具体可以看->这里。 之前尝试过很多