写完想着记录点什么,就写下了这篇自己看的博客,记录一下心路历程。

运行效果图

用python下载图片 python下载图片添加序号_ide

功能实现

1)多页PDF文档给页面标序号

2)单页PDF可以复制多份。第一个复制的页面标1,第二个复制的页面标2,以此类推

实现思路

之前完成过一个图片标序号的小脚本,PDF标序号的话,可以先转成图片,然后图片标序号,最后把图片整合起来,功能实现以后想着做个界面的东西,好看点,最后把代码打包成exe,直接就能使用了,ok想完说干就干

环境准备

python 3.6 64位(安装PythonMagick需要下载对应版本,不然报错) 用到的库:tkinter,PyPDF2,PythonMagick,reportlab

实现过程

开始整python没多久,没做到任何库随手拿来用的地步,所以就是漫长的百度过程,看别人的教程、博客,仿写改写,然后看API用法熟悉一下

用到的库:tkinter,PyPDF2,PIL

PDF标序号主要参考博客:1)     #主要功能实现参考这个就行

            2)        #图片转PDF

tkinter部分主要参考教程:1)https://morvanzhou.github.io/tutorials/python-basic/tkinter/   #tkinter基础

              2)      #事件绑定

exe打包参考教程:

关键代码



1 import PyPDF2
 2 import PythonMagick
 3 from PIL import Image,ImageDraw,ImageFont
 4 from reportlab.pdfgen import canvas
 5 from reportlab.lib.pagesizes import A4
 6 import os
 7 
 8 def copy_pdf(fn,num,path):  # 拷贝PDF
 9     save_names = []
10     for i in range(1, num+1):
11         save_name = str(i)+'.pdf'
12         save_names.append(save_name)
13     with open(fn,'rb') as pdf1File:
14         pdf1_r = PyPDF2.PdfFileReader(pdf1File)
15         for save_name in save_names:
16             pdfWriter = PyPDF2.PdfFileWriter()
17             pdfxFile = open(os.path.join(path,save_name),'wb')
18             pagObj = pdf1_r.getPage(0)
19             pdfWriter.addPage(pagObj)
20             pdfWriter.write(pdfxFile)
21             pdfxFile.close()
22     return save_names, num
23 
24 def pdf_2_pic(fn,path):    # PDF转换成图片
25     with open(fn,'rb') as pdf1File:
26         pdf_r = PyPDF2.PdfFileReader(pdf1File)
27         npage = pdf_r.getNumPages()
28     if not os.path.exists(path):
29         os.makedirs(path)
30     for p in range(npage):
31         im = PythonMagick.Image(fn+'['+str(p)+']')
32         outfn  = '%03d.jpg' % (p)
33         outfn = os.path.join(path, outfn)
34         im.write(outfn)
35 
36 def pic_add_num(fn,path):   # 图片添加标记
37     for img in [item for item in os.listdir(path) if item.endswith('.jpg')]:
38         im1 = Image.open(os.path.join(path,img))
39         drawimg = ImageDraw.Draw(im1)
40         with open(fn,'rb') as f1:
41             pdf_r = PyPDF2.PdfFileReader(f1)
42             npage = pdf_r.getNumPages()
43         if npage > 1:
44             num = os.path.splitext(img)[0][-3:]
45         else:
46             num = os.path.split(fn)[1].split('.')[0]
47         font = ImageFont.truetype('arial.ttf', 20)
48         drawimg.text((20,20),str(num),font=font,fill='#ff0000')
49         im1.save(os.path.join(path,img))
50 
51 def pic_2_pdf(pdfFileName, inPath):    # 图片转换成PDF
52     c = canvas.Canvas(pdfFileName)
53     (w, h) = A4
54     jpgs = [item for item in os.listdir(inPath) if item.lower().endswith('jpg')]
55     for infn in jpgs:
56         infn = os.path.join(inPath, infn)
57         c.setFillAlpha(1)
58         c.drawImage(infn, 0, 0, w, h)
59         c.showPage()
60     for file in jpgs:
61         os.remove(os.path.join(inPath, file))
62     c.save()
63 
64 def trans_pdf(file_name,save_path,get_num,num=1):
65     if get_num == 0:
66         pns = copy_pdf(file_name, num, save_path)[0]
67         for pn in pns:
68             save_file_path = os.path.join(save_path, pn)
69             pdf_2_pic(save_file_path, save_path)
70             pic_add_num(save_file_path, save_path)
71             pic_2_pdf(save_file_path, save_path)
72     else:
73         pdf_2_pic(file_name, save_path)
74         pic_add_num(file_name, save_path)
75         pic_2_pdf(os.path.join(save_path, os.path.split(file_name)[1]), save_path)
76 
77 if __name__ == '__main__':
78     file_name = input('输入文件完整路径,e.g:<F:\pdf\1.pdf>:')
79     save_path = input('输入生成的PDF文档保存路径,e.g:<F:\pdf>:')
80     get_num = int(input('单页PDF拷贝多份输入0,多页PDF标序列号输入1:'))
81     if get_num == 0:
82         num = int(input('输入PDF拷贝数量:'))
83     trans_pdf(file_name,save_path,get_num,num)
84     print('运行成功')


PDF转换部分函数


import tkinter as tk
from tkinter.filedialog import askopenfilename,askdirectory
from tkinter import messagebox
from tk_pdf_demo_copy import trans_pdf

#gui基础信息
window = tk.Tk()
window.title('二狗之友')
window.resizable(width=False,height=False)
window.geometry('600x95')

#frame布局
fm1 = tk.Frame(window)
fm2 = tk.Frame(window)
fm3 = tk.Frame(window)
fm1.pack(side='left',fill='y',padx=5,pady=10)
fm2.pack(side='left',fill='y',padx=5,pady=10)
fm3.pack(side='left',fill='y',padx=5,pady=10)

font = ('Arial',10)  # 字体

def e1_double_callback(event):
    # 双击弹出文件对话框回调  file_name
    file_name = askopenfilename()
    a1.set(file_name)
    return a1

def e2_double_callback(event):
    # 双击弹出文件对话框回调  save_path
    save_path = askdirectory()
    a2.set(save_path)
    return a2

def options_judge():
    status = True
    file = e1.get()
    save = e2.get()
    get_num = r12.get()
    num = e3.get()
    try:
        e33 = int(e3.get())
    except ValueError:
        tk.messagebox.showinfo('二狗提示', '拷贝个数请输入数字(1-1024)')
    while status:
        if e33 > 1024 or e33 <= 0:
            tk.messagebox.showinfo('二狗提示', '拷贝个数请输入数字(1-1024)')
            break
        elif get_num == 1 and int(num) > 1:
            tk.messagebox.showerror('错误', '选择多页PDF时拷贝个数只能为1')
            break
        else:
            status = False
            break
    return file, save, get_num, int(num),status

def run_command():
    file,save,get_num,num,status = options_judge()
    if status == False:
        trans_pdf(file,save,get_num,num)
        tk.messagebox.showinfo('二狗提示', '创建成功')

#fm1
label1 = tk.Label(fm1,text='PDF路径:',height=1).pack(side='top')
label2 = tk.Label(fm1,text='保存路径:',height=1).pack(side='top')
label3 = tk.Label(fm1,text='拷贝个数:',height=1).pack(side='top')

a1 = tk.StringVar()
e1 = tk.Entry(fm2,font=font,width=38,textvariable=a1)
e1.bind('<Double-Button-1>',e1_double_callback)
e1.pack(side='top',pady=1)  # file_path

a2 = tk.StringVar()
e2 = tk.Entry(fm2,font=font,width=38,textvariable=a2)
e2.bind('<Double-Button-1>',e2_double_callback)
e2.pack(side='top',pady=1)  # save_path

e3 = tk.IntVar()
e3.set(1)
e3 = tk.Entry(fm2,font=font,width=38,textvariable=e3)
e3.pack(side='top',pady=1)  # num

#fm3
r12 = tk.IntVar()
r12.set(0)
r1 = tk.Radiobutton(fm3,text='单页PDF',font=font,variable=r12,value=0,command=options_judge)
r1.pack(side='left')
r2 = tk.Radiobutton(fm3,text='多页PDF',font=font,variable=r12,value=1,command=options_judge)
r2.pack(side='right')
btn = tk.Button(fm3,text='提交',font=font,width=10,command=run_command).pack(side='left')

if __name__ =='__main__':
    window.mainloop()


tkinter gui部分代码



1 def copy_pdf(fn,num,path):  # 拷贝PDF
 2     save_names = []
 3     for i in range(1, num+1):
 4         save_name = str(i)+'.pdf'
 5         save_names.append(save_name)
 6     pdf1File = open(fn, 'rb')
 7     pdf1_r = PyPDF2.PdfFileReader(pdf1File)
 8     for save_name in save_names:
 9         pdfWriter = PyPDF2.PdfFileWriter()
10         pdfxFile = open(os.path.join(path,save_name),'wb')
11         pagObj = pdf1_r.getPage(0)
12         pdfWriter.addPage(pagObj)
13         pdfWriter.write(pdfxFile)
14     pdf1File.close()
15     return save_names, num
16 
17 def pdf_2_pic(fn,path):    # PDF转换成图片
18     pdf_r = PyPDF2.PdfFileReader(open(fn, 'rb'))
19     npage = pdf_r.getNumPages()
20     if not os.path.exists(path):
21         os.makedirs(path)
22     for p in range(npage):
23         im = PythonMagick.Image(fn+'['+str(p)+']')
24         outfn  = '%03d.jpg' % (p)
25         outfn = os.path.join(path, outfn)
26         im.write(outfn)
27 
28 def pic_add_num(fn,path):   # 图片添加标记
29     for img in [item for item in os.listdir(path) if item.endswith('.jpg')]:
30         im1 = Image.open(os.path.join(path,img))
31         drawimg = ImageDraw.Draw(im1)
32         pdf_r = PyPDF2.PdfFileReader(open(fn, 'rb'))
33         npage = pdf_r.getNumPages()
34         if npage > 1:
35             num = os.path.splitext(img)[0][-3:]
36         else:
37             num = os.path.split(fn)[1].split('.')[0]
38         font = ImageFont.truetype('arial.ttf', 20)
39         drawimg.text((20,20),str(num),font=font,fill='#ff0000')
40         im1.save(os.path.join(path,img))
41 
42 def pic_2_pdf(pdfFileName, inPath):    # 图片转换成PDF
43     c = canvas.Canvas(pdfFileName)
44     (w, h) = A4
45     jpgs = [item for item in os.listdir(inPath) if item.lower().endswith('jpg')]
46     for infn in jpgs:
47         infn = os.path.join(inPath, infn)
48         c.setFillAlpha(1)
49         c.drawImage(infn, 0, 0, w, h)
50         c.showPage()
51         asyncio.sleep(1)
52     for file in jpgs:
53         os.remove(os.path.join(inPath, file))
54     c.sav



1 import tkinter as tk
 2 from tkinter.filedialog import askopenfilename,askdirectory
 3 from tkinter import messagebox
 4 from tk_pdf_demo_copy import trans_pdf
 5 
 6 #gui基础信息
 7 window = tk.Tk()
 8 window.title('二狗之友')
 9 window.resizable(width=False,height=False)
10 window.geometry('600x95')
11 
12 #frame布局
13 fm1 = tk.Frame(window)
14 fm2 = tk.Frame(window)
15 fm3 = tk.Frame(window)
16 fm1.pack(side='left',fill='y',padx=5,pady=10)
17 fm2.pack(side='left',fill='y',padx=5,pady=10)
18 fm3.pack(side='left',fill='y',padx=5,pady=10)
19 
20 font = ('Arial',10)  # 字体
21 
22 def e1_double_callback(event):
23     # 双击弹出文件对话框回调  file_name
24     file_name = askopenfilename()
25     a1.set(file_name)
26     return a1
27 
28 def e2_double_callback(event):
29     # 双击弹出文件对话框回调  save_path
30     save_path = askdirectory()
31     a2.set(save_path)
32     return a2
33 
34 
35 def options_judge():
36     status = True
37     file = e1.get()
38     save = e2.get()
39     get_num = r12.get()
40     num = e3.get()
41     try:
42         e33 = int(e3.get())
43     except ValueError:
44         tk.messagebox.showinfo('二狗提示', '拷贝个数请输入数字(1-1024)')
45     while status:
46         if e33 > 1024 or e33 <= 0:
47             tk.messagebox.showinfo('二狗提示', '拷贝个数请输入数字(1-1024)')
48             break
49         elif get_num == 1 and int(num) > 1:
50             tk.messagebox.showerror('错误', '选择多页PDF时拷贝个数只能为1')
51             break
52         else:
53             status = False
54             break
55     return file, save, get_num, int(num),status
56 
57 def run_command():
58     file,save,get_num,num,status = options_judge()
59     if status == False:
60         trans_pdf(file,save,get_num,num)
61         tk.messagebox.showinfo('二狗提示', '创建成功')
62 
63 #fm1
64 label1 = tk.Label(fm1,text='PDF路径:',height=1).pack(side='top')
65 label2 = tk.Label(fm1,text='保存路径:',height=1).pack(side='top')
66 label3 = tk.Label(fm1,text='拷贝个数:',height=1).pack(side='top')
67 
68 a1 = tk.StringVar()
69 e1 = tk.Entry(fm2,font=font,width=38,textvariable=a1)
70 e1.bind('<Double-Button-1>',e1_double_callback)
71 e1.pack(side='top',pady=1)  # file_path
72 
73 a2 = tk.StringVar()
74 e2 = tk.Entry(fm2,font=font,width=38,textvariable=a2)
75 e2.bind('<Double-Button-1>',e2_double_callback)
76 e2.pack(side='top',pady=1)  # save_path
77 
78 e3 = tk.IntVar()
79 e3.set(1)
80 e3 = tk.Entry(fm2,font=font,width=38,textvariable=e3)
81 e3.pack(side='top',pady=1)  # num
82 
83 #fm3
84 r12 = tk.IntVar()
85 r12.set(0)
86 r1 = tk.Radiobutton(fm3,text='单页PDF',font=font,variable=r12,value=0,command=options_judge)
87 r1.pack(side='left')
88 r2 = tk.Radiobutton(fm3,text='多页PDF',font=font,variable=r12,value=1,command=options_judge)
89 r2.pack(side='right')
90 btn = tk.Button(fm3,text='提交',font=font,width=10,command=run_command).pack(side='left')
91 
92 if __name__ =='__main__':
93     window.mainlo



遇到的问题

1)运行出现RunTimeError,自己PC上可以运行,依赖库装完后笔记本上运行出现的错误,思前想后就ghostscript没有安装。安装以后完美运行

2)进程已结束,退出代码-1073741819 (0xC0000005) 。这时候功能实现了,我想转换600多页的一个PDF文档时报的错,百度没有找到好的解决办法,猜测可能是占内存太大异常退出了(目前已解决,但是效率有点慢,待优化ing)

3)

用python下载图片 python下载图片添加序号_Image_02

,遇到这个百度很久也没解决,超出目前能力范围,希望有人以后能告诉我答案,这导致的问题是复制的PDF像素都不高4 )

用python下载图片 python下载图片添加序号_Image_03

https://github.com/mstamy2/PyPDF2/issues/438 ---可以参考这个

应该还遇到其他各种各样问题的,想不起来了,如有人看到这可以评论留言遇到的问题,我看看我有没有遇到

立个flag:下次一定边记录问题边写博客!!!