J'essaye d'extraire le texte inclus dans ce fichier PDF en utilisant Python
.
J'utilise le module PyPDF2 et j'ai le script suivant:
import PyPDF2
pdf_file = open('sample.pdf')
read_pdf = PyPDF2.PdfFileReader(pdf_file)
number_of_pages = read_pdf.getNumPages()
page = read_pdf.getPage(0)
page_content = page.extractText()
print page_content
Lorsque j'exécute le code, j'obtiens la sortie suivante qui est différente de celle incluse dans le document PDF:
!"#$%#$%&%$&'()*%+,-%./01'*23%4
5'%1$#26%3/%7/))/8%&)/26%8#3"%3"*%313/9#&)
%
Comment extraire le texte tel quel dans le document PDF?
pdf_file = open('sample.pdf', 'rb')
?Réponses:
Je cherchais une solution simple à utiliser pour python 3.x et windows. Il ne semble pas y avoir de support de textract , ce qui est malheureux, mais si vous cherchez une solution simple pour windows / python 3, vérifiez le paquet tika , vraiment simple pour lire les fichiers PDF.
from tika import parser # pip install tika raw = parser.from_file('sample.pdf') print(raw['content'])
Notez que Tika est écrit en Java donc vous aurez besoin d'un runtime Java installé
la source
Utilisez textract.
Il prend en charge de nombreux types de fichiers, y compris les PDF
import textract text = textract.process("path/to/file.extension")
la source
textract
est un wrapper pourPoppler:pdftotext
(entre autres).textract
semble être mort ( source ). Utilisez directement pdfminer.six ou pymupdfRegardez ce code:
import PyPDF2 pdf_file = open('sample.pdf', 'rb') read_pdf = PyPDF2.PdfFileReader(pdf_file) number_of_pages = read_pdf.getNumPages() page = read_pdf.getPage(0) page_content = page.extractText() print page_content.encode('utf-8')
La sortie est:
!"#$%#$%&%$&'()*%+,-%./01'*23%4 5'%1$#26%3/%7/))/8%&)/26%8#3"%3"*%313/9#&) %
Utiliser le même code pour lire un pdf de 201308FCR.pdf . La sortie est normale.
Sa documentation explique pourquoi:
def extractText(self): """ Locate all text drawing commands, in the order they are provided in the content stream, and extract the text. This works well for some PDF files, but poorly for others, depending on the generator used. This will be refined in the future. Do not rely on the order of text coming out of this function, as it will change if this function is made more sophisticated. :return: a unicode string object. """
la source
Après avoir essayé textract (qui semblait avoir trop de dépendances) et pypdf2 (qui ne pouvait pas extraire le texte des pdfs avec lesquels j'ai testé) et tika (qui était trop lent), j'ai fini par utiliser
pdftotext
de xpdf (comme déjà suggéré dans une autre réponse) et vient d'appeler directement le binaire de python (vous devrez peut-être adapter le chemin à pdftotext):import os, subprocess SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) args = ["/usr/local/bin/pdftotext", '-enc', 'UTF-8', "{}/my-pdf.pdf".format(SCRIPT_DIR), '-'] res = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output = res.stdout.decode('utf-8')
Il y a pdftotext qui fait fondamentalement la même chose, mais cela suppose pdftotext dans / usr / local / bin alors que je l'utilise dans AWS lambda et que je voulais l'utiliser à partir du répertoire actuel.
Btw: Pour utiliser ceci sur lambda, vous devez placer le binaire et la dépendance
libstdc++.so
dans votre fonction lambda. J'avais personnellement besoin de compiler xpdf. Comme les instructions pour cela feraient exploser cette réponse, je les ai mises sur mon blog personnel .la source
Vous voudrez peut-être utiliser à la place du xPDF éprouvé et des outils dérivés pour extraire du texte car pyPDF2 semble avoir encore divers problèmes avec l'extraction de texte.
La réponse longue est qu'il existe de nombreuses variations dans la manière dont un texte est encodé dans un PDF et qu'il peut nécessiter de décoder la chaîne PDF elle-même, puis peut avoir besoin de mapper avec CMAP, puis peut-être besoin d'analyser la distance entre les mots et les lettres, etc.
Dans le cas où le PDF est endommagé (c'est-à-dire afficher le texte correct mais lorsque la copie donne des déchets) et que vous avez vraiment besoin d'extraire du texte, vous pouvez envisager de convertir le PDF en image (en utilisant ImageMagik ), puis utiliser Tesseract pour obtenir le texte de l'image en utilisant l'OCR.
la source
J'ai essayé de nombreux convertisseurs PDF Python et j'aime mettre à jour cette revue. Tika est l'un des meilleurs. Mais PyMuPDF est une bonne nouvelle de l'utilisateur @ehsaneha.
J'ai fait un code pour les comparer dans: https://github.com/erfelipe/PDFtextExtraction J'espère vous aider.
from tika import parser raw = parser.from_file("///Users/Documents/Textos/Texto1.pdf") raw = str(raw) safe_text = raw.encode('utf-8', errors='ignore') safe_text = str(safe_text).replace("\n", "").replace("\\", "") print('--- safe text ---' ) print( safe_text )
la source
.encode('utf-8', errors='ignore')
Je recommande d'utiliser pymupdf ou
pdfminer.six
.Ces packages ne sont pas maintenus:
pdfminer
(sans .six)Comment lire du texte pur avec pymupdf
Il existe différentes options qui donneront des résultats différents, mais la plus élémentaire est:
import fitz # this is pymupdf with fitz.open("my.pdf") as doc: text = "" for page in doc: text += page.getText() print(text)
la source
Le code ci-dessous est une solution à la question dans Python 3 . Avant d'exécuter le code, assurez-vous d'avoir installé la
PyPDF2
bibliothèque dans votre environnement. S'il n'est pas installé, ouvrez l'invite de commande et exécutez la commande suivante:Code de la solution:
import PyPDF2 pdfFileObject = open('sample.pdf', 'rb') pdfReader = PyPDF2.PdfFileReader(pdfFileObject) count = pdfReader.numPages for i in range(count): page = pdfReader.getPage(i) print(page.extractText())
la source
PyPDF2 dans certains cas ignore les espaces blancs et rend le texte du résultat un désordre, mais j'utilise PyMuPDF et je suis vraiment satisfait que vous puissiez utiliser ce lien pour plus d'informations
la source
pip install pymupdf==1.16.16
. Utiliser cette version spécifique car aujourd'hui la dernière version (17) ne fonctionne pas. J'ai opté pour pymupdf car il extrait les champs d'habillage de texte dans le caractère de nouvelle ligne\n
. J'extrais donc le texte du pdf dans une chaîne avec pymupdf et j'utilise ensuitemy_extracted_text.splitlines()
pour obtenir le texte divisé en lignes, dans une liste.pdftotext est le meilleur et le plus simple! pdftotext réserve également la structure.
J'ai essayé PyPDF2, PDFMiner et quelques autres mais aucun d'entre eux n'a donné un résultat satisfaisant.
la source
Collecting PDFMiner (from pdf2text)
donc je ne comprends pas cette réponse maintenant.Le pdf de plusieurs pages peut être extrait sous forme de texte en un seul tronçon au lieu de donner un numéro de page individuel comme argument en utilisant le code ci-dessous
import PyPDF2 import collections pdf_file = open('samples.pdf', 'rb') read_pdf = PyPDF2.PdfFileReader(pdf_file) number_of_pages = read_pdf.getNumPages() c = collections.Counter(range(number_of_pages)) for i in c: page = read_pdf.getPage(i) page_content = page.extractText() print page_content.encode('utf-8')
la source
Vous pouvez utiliser PDFtoText https://github.com/jalan/pdftotext
PDF en texte conserve l'indentation du format texte, peu importe si vous avez des tableaux.
la source
J'ai un meilleur travail que l'OCR et pour maintenir l'alignement de la page tout en extrayant le texte d'un PDF. Devrait être utile:
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.pdfpage import PDFPage from io import StringIO def convert_pdf_to_txt(path): rsrcmgr = PDFResourceManager() retstr = StringIO() codec = 'utf-8' laparams = LAParams() device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams) fp = open(path, 'rb') interpreter = PDFPageInterpreter(rsrcmgr, device) password = "" maxpages = 0 caching = True pagenos=set() for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages, password=password,caching=caching, check_extractable=True): interpreter.process_page(page) text = retstr.getvalue() fp.close() device.close() retstr.close() return text text= convert_pdf_to_txt('test.pdf') print(text)
la source
codec
argument . J'ai corrigé cela en le supprimant iedevice = TextConverter(rsrcmgr, retstr, laparams=laparams)
En 2020, les solutions ci-dessus ne fonctionnaient pas pour le pdf particulier avec lequel je travaillais. Voici ce qui a fait le tour. Je suis sous Windows 10 et Python 3.8
Fichier pdf de test: https://drive.google.com/file/d/1aUfQAlvq5hA9kz2c9CyJADiY3KpY3-Vn/view?usp=sharing
#pip install pdfminer.six import io from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.pdfpage import PDFPage def convert_pdf_to_txt(path): '''Convert pdf content from a file path to text :path the file path ''' rsrcmgr = PDFResourceManager() codec = 'utf-8' laparams = LAParams() with io.StringIO() as retstr: with TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams) as device: with open(path, 'rb') as fp: interpreter = PDFPageInterpreter(rsrcmgr, device) password = "" maxpages = 0 caching = True pagenos = set() for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages, password=password, caching=caching, check_extractable=True): interpreter.process_page(page) return retstr.getvalue() if __name__ == "__main__": print(convert_pdf_to_txt('C:\\Path\\To\\Test_PDF.pdf'))
la source
Voici le code le plus simple pour extraire du texte
code:
# importing required modules import PyPDF2 # creating a pdf file object pdfFileObj = open('filename.pdf', 'rb') # creating a pdf reader object pdfReader = PyPDF2.PdfFileReader(pdfFileObj) # printing number of pages in pdf file print(pdfReader.numPages) # creating a page object pageObj = pdfReader.getPage(5) # extracting text from page print(pageObj.extractText()) # closing the pdf file object pdfFileObj.close()
la source
J'ai trouvé une solution ici PDFLayoutTextStripper
C'est bien car il peut conserver la mise en page du PDF d'origine .
Il est écrit en Java mais j'ai ajouté une passerelle pour prendre en charge Python.
Exemple de code:
from py4j.java_gateway import JavaGateway gw = JavaGateway() result = gw.entry_point.strip('samples/bus.pdf') # result is a dict of { # 'success': 'true' or 'false', # 'payload': pdf file content if 'success' is 'true' # 'error': error message if 'success' is 'false' # } print result['payload']
Exemple de sortie de PDFLayoutTextStripper :
Vous pouvez voir plus de détails ici Stripper avec Python
la source
Pour extraire le texte du PDF, utilisez le code ci-dessous
import PyPDF2 pdfFileObj = open('mypdf.pdf', 'rb') pdfReader = PyPDF2.PdfFileReader(pdfFileObj) print(pdfReader.numPages) pageObj = pdfReader.getPage(0) a = pageObj.extractText() print(a)
la source
Une manière plus robuste, en supposant qu'il y ait plusieurs PDF ou un seul!
import os from PyPDF2 import PdfFileWriter, PdfFileReader from io import BytesIO mydir = # specify path to your directory where PDF or PDF's are for arch in os.listdir(mydir): buffer = io.BytesIO() archpath = os.path.join(mydir, arch) with open(archpath) as f: pdfFileObj = open(archpath, 'rb') pdfReader = PyPDF2.PdfFileReader(pdfFileObj) pdfReader.numPages pageObj = pdfReader.getPage(0) ley = pageObj.extractText() file1 = open("myfile.txt","w") file1.writelines(ley) file1.close()
la source
Si vous souhaitez extraire du texte d'un tableau, j'ai trouvé que le tabula était facilement implémenté, précis et rapide:
pour obtenir un dataframe pandas:
import tabula df = tabula.read_pdf('your.pdf') df
Par défaut, il ignore le contenu de la page en dehors du tableau. Jusqu'à présent, je n'ai testé que sur un fichier d'une seule page et d'une seule table, mais il existe des kwargs pour accueillir plusieurs pages et / ou plusieurs tables.
installer via:
pip install tabula-py # or conda install -c conda-forge tabula-py
En termes d'extraction de texte directe, voir: https://stackoverflow.com/a/63190886/9249533
la source
J'ajoute du code pour accomplir ceci: cela fonctionne bien pour moi:
# This works in python 3 # required python packages # tabula-py==1.0.0 # PyPDF2==1.26.0 # Pillow==4.0.0 # pdfminer.six==20170720 import os import shutil import warnings from io import StringIO import requests import tabula from PIL import Image from PyPDF2 import PdfFileWriter, PdfFileReader from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.pdfpage import PDFPage warnings.filterwarnings("ignore") def download_file(url): local_filename = url.split('/')[-1] local_filename = local_filename.replace("%20", "_") r = requests.get(url, stream=True) print(r) with open(local_filename, 'wb') as f: shutil.copyfileobj(r.raw, f) return local_filename class PDFExtractor(): def __init__(self, url): self.url = url # Downloading File in local def break_pdf(self, filename, start_page=-1, end_page=-1): pdf_reader = PdfFileReader(open(filename, "rb")) # Reading each pdf one by one total_pages = pdf_reader.numPages if start_page == -1: start_page = 0 elif start_page < 1 or start_page > total_pages: return "Start Page Selection Is Wrong" else: start_page = start_page - 1 if end_page == -1: end_page = total_pages elif end_page < 1 or end_page > total_pages - 1: return "End Page Selection Is Wrong" else: end_page = end_page for i in range(start_page, end_page): output = PdfFileWriter() output.addPage(pdf_reader.getPage(i)) with open(str(i + 1) + "_" + filename, "wb") as outputStream: output.write(outputStream) def extract_text_algo_1(self, file): pdf_reader = PdfFileReader(open(file, 'rb')) # creating a page object pageObj = pdf_reader.getPage(0) # extracting extract_text from page text = pageObj.extractText() text = text.replace("\n", "").replace("\t", "") return text def extract_text_algo_2(self, file): pdfResourceManager = PDFResourceManager() retstr = StringIO() la_params = LAParams() device = TextConverter(pdfResourceManager, retstr, codec='utf-8', laparams=la_params) fp = open(file, 'rb') interpreter = PDFPageInterpreter(pdfResourceManager, device) password = "" max_pages = 0 caching = True page_num = set() for page in PDFPage.get_pages(fp, page_num, maxpages=max_pages, password=password, caching=caching, check_extractable=True): interpreter.process_page(page) text = retstr.getvalue() text = text.replace("\t", "").replace("\n", "") fp.close() device.close() retstr.close() return text def extract_text(self, file): text1 = self.extract_text_algo_1(file) text2 = self.extract_text_algo_2(file) if len(text2) > len(str(text1)): return text2 else: return text1 def extarct_table(self, file): # Read pdf into DataFrame try: df = tabula.read_pdf(file, output_format="csv") except: print("Error Reading Table") return print("\nPrinting Table Content: \n", df) print("\nDone Printing Table Content\n") def tiff_header_for_CCITT(self, width, height, img_size, CCITT_group=4): tiff_header_struct = '<' + '2s' + 'h' + 'l' + 'h' + 'hhll' * 8 + 'h' return struct.pack(tiff_header_struct, b'II', # Byte order indication: Little indian 42, # Version number (always 42) 8, # Offset to first IFD 8, # Number of tags in IFD 256, 4, 1, width, # ImageWidth, LONG, 1, width 257, 4, 1, height, # ImageLength, LONG, 1, lenght 258, 3, 1, 1, # BitsPerSample, SHORT, 1, 1 259, 3, 1, CCITT_group, # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding 262, 3, 1, 0, # Threshholding, SHORT, 1, 0 = WhiteIsZero 273, 4, 1, struct.calcsize(tiff_header_struct), # StripOffsets, LONG, 1, len of header 278, 4, 1, height, # RowsPerStrip, LONG, 1, lenght 279, 4, 1, img_size, # StripByteCounts, LONG, 1, size of extract_image 0 # last IFD ) def extract_image(self, filename): number = 1 pdf_reader = PdfFileReader(open(filename, 'rb')) for i in range(0, pdf_reader.numPages): page = pdf_reader.getPage(i) try: xObject = page['/Resources']['/XObject'].getObject() except: print("No XObject Found") return for obj in xObject: try: if xObject[obj]['/Subtype'] == '/Image': size = (xObject[obj]['/Width'], xObject[obj]['/Height']) data = xObject[obj]._data if xObject[obj]['/ColorSpace'] == '/DeviceRGB': mode = "RGB" else: mode = "P" image_name = filename.split(".")[0] + str(number) print(xObject[obj]['/Filter']) if xObject[obj]['/Filter'] == '/FlateDecode': data = xObject[obj].getData() img = Image.frombytes(mode, size, data) img.save(image_name + "_Flate.png") # save_to_s3(imagename + "_Flate.png") print("Image_Saved") number += 1 elif xObject[obj]['/Filter'] == '/DCTDecode': img = open(image_name + "_DCT.jpg", "wb") img.write(data) # save_to_s3(imagename + "_DCT.jpg") img.close() number += 1 elif xObject[obj]['/Filter'] == '/JPXDecode': img = open(image_name + "_JPX.jp2", "wb") img.write(data) # save_to_s3(imagename + "_JPX.jp2") img.close() number += 1 elif xObject[obj]['/Filter'] == '/CCITTFaxDecode': if xObject[obj]['/DecodeParms']['/K'] == -1: CCITT_group = 4 else: CCITT_group = 3 width = xObject[obj]['/Width'] height = xObject[obj]['/Height'] data = xObject[obj]._data # sorry, getData() does not work for CCITTFaxDecode img_size = len(data) tiff_header = self.tiff_header_for_CCITT(width, height, img_size, CCITT_group) img_name = image_name + '_CCITT.tiff' with open(img_name, 'wb') as img_file: img_file.write(tiff_header + data) # save_to_s3(img_name) number += 1 except: continue return number def read_pages(self, start_page=-1, end_page=-1): # Downloading file locally downloaded_file = download_file(self.url) print(downloaded_file) # breaking PDF into number of pages in diff pdf files self.break_pdf(downloaded_file, start_page, end_page) # creating a pdf reader object pdf_reader = PdfFileReader(open(downloaded_file, 'rb')) # Reading each pdf one by one total_pages = pdf_reader.numPages if start_page == -1: start_page = 0 elif start_page < 1 or start_page > total_pages: return "Start Page Selection Is Wrong" else: start_page = start_page - 1 if end_page == -1: end_page = total_pages elif end_page < 1 or end_page > total_pages - 1: return "End Page Selection Is Wrong" else: end_page = end_page for i in range(start_page, end_page): # creating a page based filename file = str(i + 1) + "_" + downloaded_file print("\nStarting to Read Page: ", i + 1, "\n -----------===-------------") file_text = self.extract_text(file) print(file_text) self.extract_image(file) self.extarct_table(file) os.remove(file) print("Stopped Reading Page: ", i + 1, "\n -----------===-------------") os.remove(downloaded_file) # I have tested on these 3 pdf files # url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Healthcare-January-2017.pdf" url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Sample_Test.pdf" # url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Sazerac_FS_2017_06_30%20Annual.pdf" # creating the instance of class pdf_extractor = PDFExtractor(url) # Getting desired data out pdf_extractor.read_pages(15, 23)
la source
Vous pouvez télécharger tika-app-xxx.jar (dernier) à partir d' ici .
Ensuite, placez ce fichier .jar dans le même dossier que votre fichier de script python.
puis insérez le code suivant dans le script:
import os import os.path tika_dir=os.path.join(os.path.dirname(__file__),'<tika-app-xxx>.jar') def extract_pdf(source_pdf:str,target_txt:str): os.system('java -jar '+tika_dir+' -t {} > {}'.format(source_pdf,target_txt))
L'avantage de cette méthode:
moins de dépendance. Un fichier .jar unique est plus facile à gérer qu'un package python.
support multi-format. La position
source_pdf
peut être le répertoire de tout type de document. (.doc, .html, .odt, etc.)à jour. tika-app.jar est toujours publié avant la version appropriée du paquet tika python.
stable. Il est beaucoup plus stable et bien entretenu (Powered by Apache) que PyPDF.
désavantage:
Un jre-headless est nécessaire.
la source
Si vous l'essayez dans Anaconda sous Windows, PyPDF2 peut ne pas gérer certains des PDF avec une structure non standard ou des caractères Unicode. Je recommande d'utiliser le code suivant si vous avez besoin d'ouvrir et de lire beaucoup de fichiers pdf - le texte de tous les fichiers pdf dans le dossier avec le chemin relatif
.//pdfs//
sera stocké dans la listepdf_text_list
.from tika import parser import glob def read_pdf(filename): text = parser.from_file(filename) return(text) all_files = glob.glob(".\\pdfs\\*.pdf") pdf_text_list=[] for i,file in enumerate(all_files): text=read_pdf(file) pdf_text_list.append(text['content']) print(pdf_text_list)
la source
PyPDF2 fonctionne, mais les résultats peuvent varier. Je vois des résultats assez incohérents lors de l'extraction des résultats.
reader=PyPDF2.pdf.PdfFileReader(self._path) eachPageText=[] for i in range(0,reader.getNumPages()): pageText=reader.getPage(i).extractText() print(pageText) eachPageText.append(pageText)
la source
La première chose à comprendre est le format PDF . Il a une spécification publique écrite en anglais, voir ISO 32000-2: 2017 et lire les plus de 700 pages de la spécification PDF 1.7 . Vous avez certainement au moins besoin de lire la page wikipedia sur PDF
Une fois que vous avez compris les détails du format PDF, extraire du texte est plus ou moins facile (mais qu'en est-il du texte apparaissant en figures ou en images; sa figure 1)? Ne vous attendez pas à écrire seul un extracteur de texte logiciel parfait en quelques semaines ...
Sous Linux, vous pouvez également utiliser pdf2text que vous pouvez extraire de votre code Python.
En général, l'extraction de texte à partir d'un fichier PDF est un problème mal défini. Pour un lecteur humain, un texte pourrait être fait (sous forme de figure) à partir de différents points, ou d'une photo, etc.
Le moteur de recherche Google est capable d'extraire du texte à partir de PDF, mais il aurait besoin de plus d'un demi-milliard de lignes de code source. Avez-vous les ressources nécessaires (en personnel, en budget) pour développer un concurrent?
Une possibilité pourrait être d'imprimer le PDF sur une imprimante virtuelle (par exemple en utilisant GhostScript ou Firefox ), puis d'utiliser des techniques OCR pour extraire du texte.
Je recommanderais plutôt de travailler sur la représentation des données qui a généré ce fichier PDF, par exemple sur le code LaTeX original (ou le code Lout ) ou sur le code OOXML .
Dans tous les cas, vous devez prévoir au moins plusieurs années-personnes de développement logiciel.
la source
[email protected]
mentionner l'URL de cette question