web-dev-qa-db-ja.com

テキストをテキストから抽出する方法 PDF ファイル?

this PDFファイルに含まれているテキストをPythonを使って抽出しようとしています。

私は PyPDF2 モジュールを使っていて、次のスクリプトを持っています。

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

コードを実行すると、PDFドキュメントに含まれているものとは異なる次の出力が表示されます。

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

PDFドキュメントのテキストをそのまま抽出する方法を教えてください。

97
Simplicity

Python 3.xとwindowsに使用する簡単な解決策を探していました。残念ながら、 textract からのサポートはないようですが、windows/python 3の簡単な解決策を探しているなら、 tika パッケージをご利用ください。 PDFを読む

from tika import parser

raw = parser.from_file('sample.pdf')
print(raw['content'])
68
DJK

Textractを使う.

PDFを含む多くの種類のファイルをサポートしています

import textract
text = textract.process("path/to/file.extension")
39
Jakobovski

このコードを見てください。

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#&)
%

同じコードを使用して 201308FCR.pdf から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.
    """
38
Quinn

Textract(依存関係が多すぎるように思われる)とpypdf2(私がテストしたpdfからテキストを抽出できなかった)とtika(これは遅すぎた)を試した後、xpdfのpdftotextを使いました。そして直接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 は基本的に同じですが、これは/ usr/local/binにあるpdftotextを想定しているのに対し、私はこれをAWS lambdaで使用しており、現在のディレクトリから使用したいと思いました。

ところで:これをラムダで使うためには、バイナリとlibstdc++.soへの依存関係をあなたのラムダ関数に入れる必要があります。私は個人的にxpdfをコンパイルする必要がありました。これのための指示がこの答えを爆破するので私はそれらを 私の個人的なブログに載せます

16
hansaplast

PyPDF2はまだテキストの抽出に さまざまな問題 を持っているように思われるので、代わりに時間を証明した xPDF と派生ツールを使ってテキストを抽出することをお勧めします。

長い答えは、テキストがPDF内でエンコードされる方法には多くのバリエーションがあり、それはPDF文字列自体をデコードする必要があるかもしれないということです。単語と文字などの間の距離を分析する必要がある.

PDFが破損している場合(つまり正しいテキストを表示するがコピーするときにゴミが出る場合)、本当にテキストを抽出する必要がある場合は、PDFをイメージに変換することを検討します。 OCRを使用して画像からテキストを取得するには、 ImageMagik )を使用してから Tesseract を使用します。

9
Eugene

以下のコードは 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())
5

以下のコードを使用して、引数として個々のページ番号を指定する代わりに、複数ページの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')
4
Yogi

あなたはPDFtoTextを使用することができます https://github.com/jalan/pdftotext

PDFからテキストへの変換はテキスト形式のインデントを保持します。テーブルがあっても関係ありません。

3
Máxima Alekz

PyPDF2は空白を無視して結果のテキストをめちゃくちゃにすることがありますが、私はPyMuPDFを使用していますし、このリンクを使用できることに本当に満足しています link

3
ehsaneha

これがテキストを抽出するための最も簡単なコードです。

コード:

# 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()
2
Infinity

pdftotext は、最も簡単でシンプルなものです。 pdftotextも構造を予約しています。

私はPyPDF2、PDFMiner、その他いくつかを試しましたが、どれも満足のいく結果を出しませんでした。

2
Dharam

私はたくさんのPython PDFコンバータを試してみました、Tikaが一番です。

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

Here から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パッケージよりも早くリリースされます。

安定しています。これはPyPDFよりもはるかに安定しており、手入れが行き届いています(Apacheによって供給)。

不利益:

ヘッドレスが必要です。

1
pah8J

私はこれを達成するためのコードを追加しています。それは私のためにうまく働いています:

# 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)
1
Ritesh Shanker

PyPDF2は動作しますが、結果は異なる場合があります。その結果の抽出から非常に矛盾した結果が出ています。

reader=PyPDF2.pdf.PdfFileReader(self._path)
eachPageText=[]
for i in range(0,reader.getNumPages()):
    pageText=reader.getPage(i).extractText()
    print(pageText)
    eachPageText.append(pageText)
0
bmc

Windows上のAnacondaで試してみると、PyPDF2は非標準の構造またはUnicode文字を含むPDFの一部を処理しない場合があります。多数のpdfファイルを開いて読み取る必要がある場合は、次のコードを使用することをお勧めします。相対パス.//pdfs//を持つフォルダー内のすべてのpdfファイルのテキストは、リストpdf_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)
0
Gibron

私はここで解決策を見つけました PDFLayoutTextStripper

元のPDF のレイアウトを維持できるので、良い方法です。

これはJavaで書かれていますが、Pythonをサポートするためにゲートウェイを追加しました。

サンプルコード:

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

PDFLayoutTextStripper からの出力例: enter image description here

詳細はこちらをご覧ください。{ Stripper with Python

0
Tho