Извлечение данных из PDF с использованием python [duplicate]

Он мог бы сформировать связанный список. Просто контракт Map требует, чтобы он заменил запись:

V put(K key, V value)

Связывает указанное значение с указанным ключом на этой карте (дополнительная операция). Если в карте ранее содержалось сопоставление для ключа, старое значение заменяется указанным значением. (Предполагается, что отображение m содержит отображение для ключа k тогда и только тогда, когда m.containsKey (k) вернет true.)

blockquote>

http://docs.oracle .com / javase / 6 / docs / api / java / util / Map.html

Для карты для хранения списков значений она должна быть Multimap. Вот Google: http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Multimap.html

A которая похожа на карту, но которая может связывать несколько значений с одним ключом. Если вы дважды вызываете put (K, V) с одним и тем же ключом, но с разными значениями, мультимап содержит сопоставления с ключом для обоих значений.

blockquote>

Редактирование: разрешение столкновений

Это немного по-другому. Столкновение происходит, когда два разных ключа имеют один и тот же хеш-код, или два ключа с разными хэш-кодами оказываются в одном и том же ковше в базовом массиве.

Рассмотрим источник HashMap (бит и фрагменты удалены):

public V put(K key, V value) {
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    // i is the index where we want to insert the new element
    addEntry(hash, key, value, i);
    return null;
}

void addEntry(int hash, K key, V value, int bucketIndex) {
    // take the entry that's already in that bucket
    Entry e = table[bucketIndex];
    // and create a new one that points to the old one = linked list
    table[bucketIndex] = new Entry<>(hash, key, value, e);
}

Для тех, кому интересно, как Entry класс в HashMap начинает вести себя как список, оказывается, что HashMap определяет свой собственный статический Entry ], который реализует Map.Entry. Вы можете сами убедиться, просмотрев исходный код:

GrepCode для HashMap

50
задан Simplicity 17 January 2016 в 12:16
поделиться

12 ответов

Посмотрите на этот код:

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')

Выход:

!"#$%#$%&%$&'()*%+,-%./01'*23%4
5'%1$#26%3/%7/))/8%&)/26%8#3"%3"*%313/9#&)
%

Используя тот же код для чтения pdf из 201308FCR.pdf . Выход нормальный.

Его документация объясняет, почему:

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.
    """
26
ответ дан Chris 29 August 2018 в 00:32
поделиться

Ищет простое решение для python 3.x и windows. Кажется, не поддерживается поддержка textract , что является неудачным, но если вы ищете простое решение для windows / python 3, посмотрите пакет tika , действительно прямой вперед для чтения pdf-файлов

from tika import parser

raw = parser.from_file('sample.pdf')
print(raw['content'])
8
ответ дан DJK 29 August 2018 в 00:32
поделиться

PyPDF2 в некоторых случаях игнорирует пробелы и делает текст результата беспорядочным, но я использую PyMuPDF, и я действительно доволен, что вы можете использовать эту ссылку для получения дополнительной информации

1
ответ дан ehsaneha 29 August 2018 в 00:32
поделиться

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

. Долгий ответ заключается в том, что существует множество вариантов того, как текст кодируется внутри PDF и что он может потребоваться для декодирования самой строки PDF, тогда может потребоваться сопоставить с CMAP, тогда может потребоваться проанализировать расстояние между словами и буквами и т. д.

В случае повреждения PDF-файла (т. е. отображения правильного текста, но при копировании он дает мусор), и вам действительно нужно извлечь текст, тогда вы можете захотеть преобразовать PDF в изображение (используя ImageMagik ), а затем используйте Tesseract , чтобы получить текст с изображения с помощью OCR.

6
ответ дан Eugene M 29 August 2018 в 00:32
поделиться

Я добавляю код для этого: он отлично работает для меня:

# 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)
2
ответ дан Girish Gupta 29 August 2018 в 00:32
поделиться

Попробовав textract (который, казалось, слишком много зависимостей) и pypdf2 (который не смог извлечь текст из pdf-файлов, которые я тестировал) и tika (который был слишком медленным), я закончил использование pdftotext из xpdf (как уже предлагаемый в другом ответе) и просто вызвал двоичный код из python напрямую (вам может понадобиться адаптировать путь к 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')

Существует pdftotext , который в основном делает то же самое но это предполагает pdftotext в / usr / local / bin, тогда как я использую это в AWS лямбда и хочу использовать его из текущего каталога.

Btw: для использования этого на лямбда вам нужно поставить двоичный и зависимость от libstdc++.so в вашей лямбда-функции. Мне лично нужно было компилировать xpdf. Поскольку инструкции для этого взорвут этот ответ, я поместил их в свой личный блог .

6
ответ дан hansaplast 29 August 2018 в 00:32
поделиться

Вот простейший код для извлечения кода

:

      # 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()
1
ответ дан Infinity 29 August 2018 в 00:32
поделиться

Использовать textract.

Он поддерживает множество типов файлов, включая файлы PDF

import textract
text = textract.process("path/to/file.extension")
27
ответ дан Jakobovski 29 August 2018 в 00:32
поделиться

Вы можете использовать PDFtoText https://github.com/jalan/pdftotext

PDF, чтобы текст сохранял отступ текстового формата, не имеет значения, есть ли у вас таблицы.

3
ответ дан Máxima Alekz 29 August 2018 в 00:32
поделиться

Вы можете скачать tika-app-xxx.jar (последний) из Здесь .

Затем поместите этот .jar-файл в ту же папку вашего файла сценария python.

затем вставьте следующий код в скрипт:

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))

Преимущество этого метода:

меньше зависимости. Один файл .jar проще управлять пакетом python.

поддержка нескольких форматов. Позиция source_pdf может быть каталогом любого документа. (.doc, .html, .odt и т. д.)

. tika-app.jar всегда выпускает ранее, чем соответствующая версия пакета tika python.

стабильный.

Недостаток:

Необходим jre-headless.

1
ответ дан pah8J 29 August 2018 в 00:32
поделиться

Нижеприведенный код является решением вопроса на Python 3. Перед запуском кода убедитесь, что вы установили библиотеку PyPDF2 в свою среду. Если не установлено, откройте командную строку и выполните следующую команду:

pip3 install PyPDF2

Код решения:

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())
2
ответ дан Steffi Keran Rani J 29 August 2018 в 00:32
поделиться

Многостраничный pdf-файл может быть извлечен как текст на одном уровне, а не указывать номер страницы в качестве аргумента, используя ниже код

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')
3
ответ дан Yogi 29 August 2018 в 00:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: