Модуль Python для преобразования PDF в текст

Каковы лучшие модули Python для преобразования PDF-файлов в текст?

    13 Solutions collect form web for “Модуль Python для преобразования PDF в текст”

    Попробуйте PDFMiner. Он может извлекать текст из файлов PDF в формате HTML, SGML или «Tagged PDF».

    http://www.unixuser.org/~euske/python/pdfminer/index.html

    Формат Tagged PDF кажется самым чистым, и удаление XML-тегов оставляет только голой текст.

    Пакет PDFMiner изменился с момента публикации кода .

    EDIT (снова):

    PDFMiner снова обновлен в версии 20100213

    Вы можете проверить версию, которую вы установили, следующим образом:

     >>> import pdfminer >>> pdfminer.__version__ '20100213' 

    Вот обновленная версия (с комментариями о том, что я изменил / добавил):

     def pdf_to_csv(filename): from cStringIO import StringIO #<-- added so you can copy/paste this to try it from pdfminer.converter import LTTextItem, TextConverter from pdfminer.pdfparser import PDFDocument, PDFParser from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter class CsvConverter(TextConverter): def __init__(self, *args, **kwargs): TextConverter.__init__(self, *args, **kwargs) def end_page(self, i): from collections import defaultdict lines = defaultdict(lambda : {}) for child in self.cur_item.objs: if isinstance(child, LTTextItem): (_,_,x,y) = child.bbox #<-- changed line = lines[int(-y)] line[x] = child.text.encode(self.codec) #<-- changed for y in sorted(lines.keys()): line = lines[y] self.outfp.write(";".join(line[x] for x in sorted(line.keys()))) self.outfp.write("\n") # ... the following part of the code is a remix of the # convert() function in the pdfminer/tools/pdf2text module rsrc = PDFResourceManager() outfp = StringIO() device = CsvConverter(rsrc, outfp, codec="utf-8") #<-- changed # becuase my test documents are utf-8 (note: utf-8 is the default codec) doc = PDFDocument() fp = open(filename, 'rb') parser = PDFParser(fp) #<-- changed parser.set_document(doc) #<-- added doc.set_parser(parser) #<-- added doc.initialize('') interpreter = PDFPageInterpreter(rsrc, device) for i, page in enumerate(doc.get_pages()): outfp.write("START PAGE %d\n" % i) interpreter.process_page(page) outfp.write("END PAGE %d\n" % i) device.close() fp.close() return outfp.getvalue() 

    Изменить (еще раз):

    Вот обновление для последней версии в pypi , 20100619p1 . Короче говоря, я заменил LTTextItem на LTChar и передал экземпляр LAParams в конструктор CsvConverter.

     def pdf_to_csv(filename): from cStringIO import StringIO from pdfminer.converter import LTChar, TextConverter #<-- changed from pdfminer.layout import LAParams from pdfminer.pdfparser import PDFDocument, PDFParser from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter class CsvConverter(TextConverter): def __init__(self, *args, **kwargs): TextConverter.__init__(self, *args, **kwargs) def end_page(self, i): from collections import defaultdict lines = defaultdict(lambda : {}) for child in self.cur_item.objs: if isinstance(child, LTChar): #<-- changed (_,_,x,y) = child.bbox line = lines[int(-y)] line[x] = child.text.encode(self.codec) for y in sorted(lines.keys()): line = lines[y] self.outfp.write(";".join(line[x] for x in sorted(line.keys()))) self.outfp.write("\n") # ... the following part of the code is a remix of the # convert() function in the pdfminer/tools/pdf2text module rsrc = PDFResourceManager() outfp = StringIO() device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams()) #<-- changed # becuase my test documents are utf-8 (note: utf-8 is the default codec) doc = PDFDocument() fp = open(filename, 'rb') parser = PDFParser(fp) parser.set_document(doc) doc.set_parser(parser) doc.initialize('') interpreter = PDFPageInterpreter(rsrc, device) for i, page in enumerate(doc.get_pages()): outfp.write("START PAGE %d\n" % i) if page is not None: interpreter.process_page(page) outfp.write("END PAGE %d\n" % i) device.close() fp.close() return outfp.getvalue() 

    EDIT (еще один раз):

    Обновлено для версии 20110515 (спасибо Oeufcoque Penteano!):

     def pdf_to_csv(filename): from cStringIO import StringIO from pdfminer.converter import LTChar, TextConverter from pdfminer.layout import LAParams from pdfminer.pdfparser import PDFDocument, PDFParser from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter class CsvConverter(TextConverter): def __init__(self, *args, **kwargs): TextConverter.__init__(self, *args, **kwargs) def end_page(self, i): from collections import defaultdict lines = defaultdict(lambda : {}) for child in self.cur_item._objs: #<-- changed if isinstance(child, LTChar): (_,_,x,y) = child.bbox line = lines[int(-y)] line[x] = child._text.encode(self.codec) #<-- changed for y in sorted(lines.keys()): line = lines[y] self.outfp.write(";".join(line[x] for x in sorted(line.keys()))) self.outfp.write("\n") # ... the following part of the code is a remix of the # convert() function in the pdfminer/tools/pdf2text module rsrc = PDFResourceManager() outfp = StringIO() device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams()) # becuase my test documents are utf-8 (note: utf-8 is the default codec) doc = PDFDocument() fp = open(filename, 'rb') parser = PDFParser(fp) parser.set_document(doc) doc.set_parser(parser) doc.initialize('') interpreter = PDFPageInterpreter(rsrc, device) for i, page in enumerate(doc.get_pages()): outfp.write("START PAGE %d\n" % i) if page is not None: interpreter.process_page(page) outfp.write("END PAGE %d\n" % i) device.close() fp.close() return outfp.getvalue() 

    Поскольку ни один из этих решений не поддерживает последнюю версию PDFMiner, я написал простое решение, которое вернет текст pdf с помощью PDFMiner. Это будет работать для тех, кто получает импортные ошибки с process_pdf

     import sys from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.pdfpage import PDFPage from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter from pdfminer.layout import LAParams from cStringIO import StringIO def pdfparser(data): fp = file(data, 'rb') rsrcmgr = PDFResourceManager() retstr = StringIO() codec = 'utf-8' laparams = LAParams() device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams) # Create a PDF interpreter object. interpreter = PDFPageInterpreter(rsrcmgr, device) # Process each page contained in the document. for page in PDFPage.get_pages(fp): interpreter.process_page(page) data = retstr.getvalue() print data if __name__ == '__main__': pdfparser(sys.argv[1]) 

    pyPDF отлично работает (при условии, что вы работаете с хорошо сформированными PDF-файлами). Если все, что вам нужно, это текст (с пробелами), вы можете просто сделать:

     import pyPdf pdf = pyPdf.PdfFileReader(open(filename, "rb")) for page in pdf.pages: print page.extractText() 

    Вы также можете легко получить доступ к метаданным, данным изображения и т. Д.

    Комментарий в примечаниях extractText:

    Найдите все команды рисования текста в порядке их предоставления в потоке содержимого и извлеките текст. Это хорошо работает для некоторых файлов PDF, но плохо для других, в зависимости от используемого генератора. Это будет усовершенствовано в будущем. Не полагайтесь на порядок текста, выходящий из этой функции, так как он изменится, если эта функция станет более сложной.

    Независимо от того, является ли это проблемой, зависит от того, что вы делаете с текстом (например, если порядок не имеет значения, это нормально, или если генератор добавляет текст в поток в том порядке, в котором он будет отображаться, это прекрасно) , У меня есть код извлечения pyPdf в ежедневном использовании без каких-либо проблем.

    Pdftotext . Программа с открытым исходным кодом (часть Xpdf), которую вы могли бы вызвать из python (не то, что вы просили, но может быть полезно). Я использовал его без проблем. Я думаю, что Google использует его на рабочем столе Google.

    Вы также можете легко использовать pdfminer в качестве библиотеки. У вас есть доступ к модели содержимого pdf и вы можете создать собственное извлечение текста. Я сделал это, чтобы преобразовать содержимое PDF в текст с разделителями с запятой, используя следующий код.

    Функция просто сортирует объекты содержимого TextItem в соответствии с их координатами y и x и выводит элементы с той же координатой y, что и одна текстовая строка, разделяя объекты на одной и той же строке на «;» персонажи.

    Используя этот подход, я смог извлечь текст из pdf, который ни один другой инструмент не смог извлечь из него контент, подходящий для дальнейшего синтаксического анализа. Другие инструменты, которые я пытался, включают pdftotext, ps2ascii и онлайн-инструмент pdftextonline.com.

    pdfminer – бесценный инструмент для извлечения pdf-файлов.

     def pdf_to_csv(filename): from pdflib.page import TextItem, TextConverter from pdflib.pdfparser import PDFDocument, PDFParser from pdflib.pdfinterp import PDFResourceManager, PDFPageInterpreter class CsvConverter(TextConverter): def __init__(self, *args, **kwargs): TextConverter.__init__(self, *args, **kwargs) def end_page(self, i): from collections import defaultdict lines = defaultdict(lambda : {}) for child in self.cur_item.objs: if isinstance(child, TextItem): (_,_,x,y) = child.bbox line = lines[int(-y)] line[x] = child.text for y in sorted(lines.keys()): line = lines[y] self.outfp.write(";".join(line[x] for x in sorted(line.keys()))) self.outfp.write("\n") # ... the following part of the code is a remix of the # convert() function in the pdfminer/tools/pdf2text module rsrc = PDFResourceManager() outfp = StringIO() device = CsvConverter(rsrc, outfp, "ascii") doc = PDFDocument() fp = open(filename, 'rb') parser = PDFParser(doc, fp) doc.initialize('') interpreter = PDFPageInterpreter(rsrc, device) for i, page in enumerate(doc.get_pages()): outfp.write("START PAGE %d\n" % i) interpreter.process_page(page) outfp.write("END PAGE %d\n" % i) device.close() fp.close() return outfp.getvalue() 

    ОБНОВЛЕНИЕ :

    Вышеприведенный код написан на старой версии API, см. Мой комментарий ниже.

    slate – это проект, который упрощает использование PDFMiner в библиотеке:

     >>> with open('example.pdf') as f: ... doc = slate.PDF(f) ... >>> doc [..., ..., ...] >>> doc[1] 'Text from page 2...' 

    Мне нужно было преобразовать определенный PDF в обычный текст в модуль python. Я использовал PDFMiner 20110515, после прочтения их инструмента pdf2txt.py я написал этот простой фрагмент:

     from cStringIO import StringIO from pdfminer.pdfinterp import PDFResourceManager, process_pdf from pdfminer.converter import TextConverter from pdfminer.layout import LAParams def to_txt(pdf_path): input_ = file(pdf_path, 'rb') output = StringIO() manager = PDFResourceManager() converter = TextConverter(manager, output, laparams=LAParams()) process_pdf(manager, converter, input_) return output.getvalue() 

    Повторное копирование pdf2txt.py кода, который поставляется с pdfminer; вы можете сделать функцию, которая будет идти по пути к pdf; необязательно, outtype (txt | html | xml | tag) и выбирает команду командной строки pdf2txt {'-o': '/path/to/outfile.txt' …}. По умолчанию вы можете позвонить:

     convert_pdf(path) 

    Будет создан текстовый файл, родной брат в файловой системе, в исходный pdf.

     def convert_pdf(path, outtype='txt', opts={}): import sys from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter, TagExtractor from pdfminer.layout import LAParams from pdfminer.pdfparser import PDFDocument, PDFParser from pdfminer.pdfdevice import PDFDevice from pdfminer.cmapdb import CMapDB outfile = path[:-3] + outtype outdir = '/'.join(path.split('/')[:-1]) debug = 0 # input option password = '' pagenos = set() maxpages = 0 # output option codec = 'utf-8' pageno = 1 scale = 1 showpageno = True laparams = LAParams() for (k, v) in opts: if k == '-d': debug += 1 elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') ) elif k == '-m': maxpages = int(v) elif k == '-P': password = v elif k == '-o': outfile = v elif k == '-n': laparams = None elif k == '-A': laparams.all_texts = True elif k == '-D': laparams.writing_mode = v elif k == '-M': laparams.char_margin = float(v) elif k == '-L': laparams.line_margin = float(v) elif k == '-W': laparams.word_margin = float(v) elif k == '-O': outdir = v elif k == '-t': outtype = v elif k == '-c': codec = v elif k == '-s': scale = float(v) # CMapDB.debug = debug PDFResourceManager.debug = debug PDFDocument.debug = debug PDFParser.debug = debug PDFPageInterpreter.debug = debug PDFDevice.debug = debug # rsrcmgr = PDFResourceManager() if not outtype: outtype = 'txt' if outfile: if outfile.endswith('.htm') or outfile.endswith('.html'): outtype = 'html' elif outfile.endswith('.xml'): outtype = 'xml' elif outfile.endswith('.tag'): outtype = 'tag' if outfile: outfp = file(outfile, 'w') else: outfp = sys.stdout if outtype == 'txt': device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams) elif outtype == 'xml': device = XMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams, outdir=outdir) elif outtype == 'html': device = HTMLConverter(rsrcmgr, outfp, codec=codec, scale=scale, laparams=laparams, outdir=outdir) elif outtype == 'tag': device = TagExtractor(rsrcmgr, outfp, codec=codec) else: return usage() fp = file(path, 'rb') process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password) fp.close() device.close() outfp.close() return 

    Кроме того, существует PDFTextStream, который является коммерческой библиотекой Java, которая также может использоваться с Python.

    Я использовал pdftohtml с аргументом «-xml», прочитал результат с помощью subprocess.Popen (), который даст вам координату x, y координату, ширину, высоту и шрифт каждого «фрагмента» текста в pdf. Я думаю, что это то, что «evince», вероятно, использует слишком, потому что одни и те же сообщения об ошибках выводятся из строя.

    Если вам нужно обрабатывать столбчатые данные, это немного усложняется, поскольку вам нужно придумать алгоритм, который подходит вашему файлу PDF. Проблема в том, что программы, которые делают PDF-файлы, на самом деле не обязательно выкладывают текст в любом логическом формате. Вы можете попробовать простые алгоритмы сортировки, и это работает иногда, но могут быть небольшие «отставшие» и «страйки», фрагменты текста, которые не попадают в порядок, который, по вашему мнению, они … так что вам нужно проявить творческий подход.

    Мне потребовалось около 5 часов, чтобы разобраться в том, как я работал над pdf. Но сейчас он работает очень хорошо. Удачи.

    PDFminer дал мне, пожалуй, одну строку [стр. 1 из 7 …] на каждой странице pdf-файла, с которой я попытался.

    Лучший ответ, который у меня есть до сих пор, – pdftoipe, или код c ++, основанный на Xpdf.

    см. мой вопрос о том, как выглядит выход pdftoipe.

    Нашли это решение сегодня. Отлично работает для меня. Даже предоставление PDF-страниц для изображений PNG. http://www.swftools.org/gfx_tutorial.html

     
    Interesting Posts for Van-Lav

    Как преобразовать тики в datetime в Python?

    Клавиши слова поиска Python для ввода поиска

    Как сохранить индекс при использовании слияния pandas

    как фильтровать поиск по значениям, которые недоступны

    Использование предварительно подготовленного inception_resnet_v2 с Tensorflow

    Komodo Edit – завершение кода для Django?

    Можно ли получить полный исходный код веб-сайта, включая css, только указав URL-адрес веб-сайта? + Python

    HttpError 401 «Login Required» при использовании Calendar v3 api python для вставки события

    save () запрещено для предотвращения потери данных из-за несохраненного связанного объекта

    pandas: заполнить столбец несколькими массивами numpy

    __init __ () получил неожиданный аргумент ключевого слова 'user'

    Python ImportError – что здесь не так?

    Как сохранить словарь объектов в Python?

    Как node.js может быть быстрее c и java? Сравнительный пример: node.js, c, java и python

    Изменение нечислового списка на числовое?

    Python - лучший язык программирования в мире.