Lors de la rédaction d'un rapport, il devenait gênant de découper et d'enregistrer des images (schémas électriques, etc.) à partir du pdf envoyé au format pdf, et de simplement copier le tableau. Les applications et le code utiles qui les font ne sont pas sortis en un coup d'œil. Alors faisons-le. L'extraction de table n'a pas fonctionné, mais j'ai pu obtenir les valeurs, donc la charge a été réduite (; ^ _ ^ A)
Je le mets aussi sur git donc si ça va https://github.com/kzrn3318/create_img_excel_from_pdf
Installation des bibliothèques requises
pip install pypdf2
pip install pillow
pip install PyMuPDF
pip install fitz
pip install pandas
pip install camelot-py[cv]
Si vous n'avez pas ghostscript au moment de l'exécution, vous pouvez obtenir une erreur. Dans ce cas, veuillez installer ghostscript. Comme il s'agit de windows10 au moment de la création du code, il peut ne pas fonctionner avec d'autres systèmes d'exploitation en raison de la chaîne de caractères du chemin, dans ce cas, veuillez réécrire afin que le chemin du code puisse être appliqué. Nous n'avons pas confirmé l'opération avec d'autres os.
Ci-dessous le code
main.py
import PyPDF2
from PIL import Image
import sys,os
import glob
import fitz
import camelot
import pandas as pd
def create_dir(img_dir , pdf_dir , excel_dir):
img_dir_glob = glob.glob(str(img_dir))
pdf_dir_glob = glob.glob(str(pdf_dir))
excel_dir_glob = glob.glob(str(excel_dir))
if len(pdf_dir_glob) > 0:
pass
else:
os.mkdir(str(pdf_dir))
if len(img_dir_glob) > 0:
pass
else:
os.mkdir(str(img_dir))
if len(excel_dir_glob) > 0:
pass
else:
os.mkdir(str(excel_dir))
def create_page_pdf(pdf,page_count,pdf_dir):
pdf_writer = PyPDF2.PdfFileWriter()
pdf_writer.addPage(pdf.getPage(page_count))
with open(".\\"+str(pdf_dir)+"\pdf{}.pdf".format(page_count),"wb") as f:
pdf_writer.write(f)
def create_png(pdf_path,page_count,img_dir):
pdf = fitz.open(pdf_path)
for num in range(len(pdf)):
num_count = 0
for image in pdf.getPageImageList(num):
num_count += 1
xref = image[0]
pix = fitz.Pixmap(pdf,xref)
if pix.n < 5:
pix.writePNG(".\\"+str(img_dir)+"\img{}_{}.png ".format(page_count,num_count))
else:
pix = fitz.Pixmap(fitz.csRGB,xref)
pix.writePNG(".\\"+str(img_dir)+"\img{}_{}.png ".format(page_count,num_count))
pix = None
pdf.close()
def create_excel(pdf_path,excel_dir,data_count):
datas = camelot.read_pdf(pdf_path,split_text=True)
data_count = data_count
for data in datas:
data_count += 1
df = data.df
with pd.ExcelWriter(".\\"+str(excel_dir)+"\\from_pdf_{}.xlsx".format(data_count)) as file:
df.to_excel(file,sheet_name="sheet1",index=False,header=False)
return data_count
if __name__ == "__main__":
args = sys.argv
print([i for i in args])
if len(args) >= 5:
print("Reçu un argument.")
pdf_file = args[1]
pdf_dir = args[2]
img_dir = args[3]
excel_dir = args[4]
else:
try:
pdf_file = args[1]
print("Étant donné que l'argument n'a pas été spécifié, la valeur par défaut est utilisée.")
except:
raise ValueError("Au moins un fichier pdf doit être l'argument. Lorsque vous spécifiez le répertoire de sortie, spécifiez quatre arguments.")
pdf_dir ="pdf_list"
img_dir="img_list"
excel_dir="excel_data"
pdf = PyPDF2.PdfFileReader(pdf_file)
print("Répertoire d'images:"+str(img_dir))
print("Répertoire pdf de chaque page:"+str(pdf_dir))
print("Répertoire de données Excel:"+str(excel_dir))
create_dir(img_dir,pdf_dir,excel_dir)
page_count = 0
for page in pdf.pages:
create_page_pdf(pdf,page_count,pdf_dir)
page_count += 1
path_list = glob.glob(".\\"+pdf_dir+"\*.pdf")
page_count = 0
data_count = 0
for path in path_list:
page_count += 1
create_png(path,page_count,img_dir)
data_count = create_excel(path,excel_dir,data_count)
print("Sortie de traitement\n")
La méthode d'exécution est la suivante, veuillez exécuter dans le même répertoire que le pdf cible. Au moment de l'exécution, un répertoire pour sauvegarder le pdf paginé, un répertoire pour sauvegarder l'image extraite du pdf, et un répertoire pour extraire le tableau du pdf et l'enregistrer sont créés. Vous pouvez les spécifier avec des arguments de ligne de commande.
python main.py (Cible.pdf) (répertoire paginé pdf) (répertoire d'images d'extraction pdf) (répertoire d'extraction de table pdf)
Exemple
python main.py train1.pdf pdf_dir img_dir excel_dir
Dans l'exemple ci-dessus, le pdf est enregistré pour chaque division de page directement sous pdf_dir. Enregistrez l'image extraite dans img_dir. Enregistrez la table extraite dans excel_dir converti en excel.
import PyPDF2
from PIL import Image
import sys,os
import glob
import fitz
import camelot
import pandas as pd
Comme vous pouvez le voir, les gens qui écrivent habituellement python le voient souvent. Importez chaque package.
def create_dir(img_dir , pdf_dir , excel_dir):
img_dir_glob = glob.glob(str(img_dir))
pdf_dir_glob = glob.glob(str(pdf_dir))
excel_dir_glob = glob.glob(str(excel_dir))
if len(pdf_dir_glob) > 0:
pass
else:
os.mkdir(str(pdf_dir))
if len(img_dir_glob) > 0:
pass
else:
os.mkdir(str(img_dir))
if len(excel_dir_glob) > 0:
pass
else:
os.mkdir(str(excel_dir))
Il s'agit d'une fonction de création de répertoire qui détermine si l'argument reçu existe déjà et le crée s'il n'existe pas.
def create_page_pdf(pdf,page_count,pdf_dir):
pdf_writer = PyPDF2.PdfFileWriter()
pdf_writer.addPage(pdf.getPage(page_count))
with open(".\\"+str(pdf_dir)+"\pdf{}.pdf".format(page_count),"wb") as f:
pdf_writer.write(f)
C'est une fonction qui divise le pdf original en pages et enregistre chacune. Créez un pdf (numéro de page) .pdf directement sous pdf_dir.
def create_png(pdf_path,page_count,img_dir):
pdf = fitz.open(pdf_path)
for num in range(len(pdf)):
num_count = 0
for image in pdf.getPageImageList(num):
num_count += 1
xref = image[0]
pix = fitz.Pixmap(pdf,xref)
if pix.n < 5:
pix.writePNG(".\\"+str(img_dir)+"\img{}_{}.png ".format(page_count,num_count))
else:
pix = fitz.Pixmap(fitz.csRGB,xref)
pix.writePNG(".\\"+str(img_dir)+"\img{}_{}.png ".format(page_count,num_count))
pix = None
pdf.close()
Enregistrez l'image extraite directement sous img_dir au format .png. Le nom du fichier sera img (numéro de page) _ (numéro d'image sur la page) .png.
def create_excel(pdf_path,excel_dir,data_count):
datas = camelot.read_pdf(pdf_path,split_text=True)
data_count = data_count
for data in datas:
data_count += 1
df = data.df
with pd.ExcelWriter(".\\"+str(excel_dir)+"\\from_pdf_{}.xlsx".format(data_count)) as file:
df.to_excel(file,sheet_name="sheet1",index=False,header=False)
return data_count
Enregistrez le fichier Excel converti directement sous excel_dir.
def create_excel(pdf_path,excel_dir,data_count):
datas = camelot.read_pdf(pdf_path,split_text=True)
data_count = data_count
for data in datas:
data_count += 1
df = data.df
with pd.ExcelWriter(".\\"+str(excel_dir)+"\\from_pdf_{}.xlsx".format(data_count)) as file:
df.to_excel(file,sheet_name="sheet1",index=False,header=False)
return data_count
if __name__ == "__main__":
args = sys.argv
print([i for i in args])
if len(args) >= 5:
print("Reçu un argument.")
pdf_file = args[1]
pdf_dir = args[2]
img_dir = args[3]
excel_dir = args[4]
else:
try:
pdf_file = args[1]
print("Étant donné que l'argument n'a pas été spécifié, la valeur par défaut est utilisée.")
except:
raise ValueError("Au moins un fichier pdf doit être l'argument. Lorsque vous spécifiez le répertoire de sortie, spécifiez quatre arguments.")
pdf_dir ="pdf_list"
img_dir="img_list"
excel_dir="excel_data"
pdf = PyPDF2.PdfFileReader(pdf_file)
print("Répertoire d'images:"+str(img_dir))
print("Répertoire pdf de chaque page:"+str(pdf_dir))
print("Répertoire de données Excel:"+str(excel_dir))
create_dir(img_dir,pdf_dir,excel_dir)
page_count = 0
for page in pdf.pages:
create_page_pdf(pdf,page_count,pdf_dir)
page_count += 1
path_list = glob.glob(".\\"+pdf_dir+"\*.pdf")
page_count = 0
data_count = 0
for path in path_list:
page_count += 1
create_png(path,page_count,img_dir)
data_count = create_excel(path,excel_dir,data_count)
print("Sortie de traitement\n")
C'est la partie exécution de main.py. Chaque nom de répertoire est obtenu à partir de l'argument de ligne de commande et exécuté.
Jusqu'à présent, j'avais l'habitude de découper du pdf, mais je pense que c'est devenu beaucoup plus facile. pyPDF2 et camelot avaient très peu de rayures et étaient difficiles (-_-;) Il semble qu'il y ait encore des améliorations dans l'extraction de table, mais cela semble difficile à extraire car cela est dû à la structure et au style d'écriture du pdf. Ce code est créé en supposant que le pdf exporté est utilisé. Veuillez noter que nous n'avons pas testé si le livre d'instructions PDF numérisé par Adobe Scan, etc.
Recommended Posts