質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3026閲覧

指定した座標の範囲内にあるpdfのテキストを抽出したい

zy70

総合スコア4

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2023/05/01 05:57

編集2023/05/01 06:12

初学者です。
お力添えのほど、よろしくお願いいたします。

実現したいこと

pdfの中で、指定した範囲内にあるテキストを抽出したいと考えています。

発生している問題・エラーメッセージ

テキストの文字が1ブロックになっている場合(表現が適切か分かりませんが)は読み取れますが、
複数に分かれている場合に出力できません。(文末に補足の画像を掲載しました)

コード from pdfminer.high_level import extract_text from pdfminer.layout import LAParams, LTTextBoxHorizontal, LTTextLineHorizontal from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.pdfpage import PDFPage from pdfminer.converter import PDFPageAggregator x1, y1, x2, y2 = 100,100,200,200 #範囲を指定 with open('/rename/image.pdf', 'rb') as pdf_file: # PDFファイルを開く resource_manager = PDFResourceManager() # PDFMinerのリソースマネージャーを初期化 laparams = LAParams() device = PDFPageAggregator(resource_manager, laparams=laparams) interpreter = PDFPageInterpreter(resource_manager, device) for page in PDFPage.get_pages(pdf_file): # ページごとに処理 interpreter.process_page(page) layout = device.get_result() for lt_obj in layout: # ページ内のテキストをチェック if isinstance(lt_obj, (LTTextBoxHorizontal, LTTextLineHorizontal)): x, y, _, _ = lt_obj.bbox if x1 <= x <= x2 and y1 <= y <= y2: text = lt_obj.get_text().strip() print(text) ### 試したこと 検出された複数のテキストに対して、OCRさせたい両端の座標を入力すればよいのではないかと想定して試しましたが、 結果はダメでした。(補足情報欄にイメージを掲載しました) なお、pdf内のテキストの座標は、以下のコードを実行して取得しました。 python コード from pdfminer.pdfparser import PDFParser from pdfminer.pdfdocument import PDFDocument from pdfminer.pdfpage import PDFPage from pdfminer.pdfpage import PDFTextExtractionNotAllowed from pdfminer.pdfinterp import PDFResourceManager from pdfminer.pdfinterp import PDFPageInterpreter from pdfminer.layout import LAParams from pdfminer.converter import PDFPageAggregator # PDFファイルのパスを指定 pdf_file_path = "/image.pdf" # PDFファイルをバイナリ形式で開く with open(pdf_file_path, 'rb') as fp: # PDFパーサーを作成 parser = PDFParser(fp) # PDFドキュメントを作成 document = PDFDocument(parser) # パスワードが設定されていないことを確認 if not document.is_extractable: raise PDFTextExtractionNotAllowed # PDFリソースマネージャーを作成 rsrcmgr = PDFResourceManager() # ページの解析パラメータを設定 laparams = LAParams() # ページの集約器を作成 device = PDFPageAggregator(rsrcmgr, laparams=laparams) # ページの解析器を作成 interpreter = PDFPageInterpreter(rsrcmgr, device) # 全ページに対して処理を行う for page in PDFPage.create_pages(document): # ページの内容を解析 interpreter.process_page(page) # 解析結果からレイアウトを取得 layout = device.get_result() # レイアウトからテキストの座標を取得し表示 for element in layout: if hasattr(element, "get_text"): print("Text: ", element.get_text()) print("Position: ", element.bbox) ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2023-05-01/54c27e34-4305-406e-9f76-2a352685d139.png)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2023/05/01 06:08

提示コードがどこまで意図したとおりに動作しているか? たとえば「ページ内のテキストをチェック」において - isinstanceは意図した型チェックができているか - x,yには意図した座標が入っているか といったことをprint文を挿入するなどして確認した結果を記載すると 回答得られやすくなるかと思います。
zy70

2023/05/01 06:19

can110様 アドバイスありがとうございます そのようにいたします。
zy70

2023/05/01 09:18

can110様 アドバイスいただいた通りコードを見直し、文末にif文を追加することで実現できました。 ありがとうございました。 from pdfminer.pdfparser import PDFParser from pdfminer.pdfdocument import PDFDocument from pdfminer.pdfpage import PDFPage from pdfminer.pdfpage import PDFTextExtractionNotAllowed from pdfminer.pdfinterp import PDFResourceManager from pdfminer.pdfinterp import PDFPageInterpreter from pdfminer.layout import LAParams from pdfminer.converter import PDFPageAggregator # PDFファイルのパスを指定 pdf_file_path = "/sample.pdf" x_left_bottom_val = 390 y_left_bottom_val = 620 x_right_top_val = 520 y_right_top_val = 740 # PDFファイルをバイナリ形式で開く with open(pdf_file_path, 'rb') as fp: # PDFパーサーを作成 parser = PDFParser(fp) # PDFドキュメントを作成 document = PDFDocument(parser) # パスワードが設定されていないことを確認 if not document.is_extractable: raise PDFTextExtractionNotAllowed # PDFリソースマネージャーを作成 rsrcmgr = PDFResourceManager() # ページの解析パラメータを設定 laparams = LAParams() # ページの集約器を作成 device = PDFPageAggregator(rsrcmgr, laparams=laparams) # ページの解析器を作成 interpreter = PDFPageInterpreter(rsrcmgr, device) # 全ページに対して処理を行う for page in PDFPage.create_pages(document): # ページの内容を解析 interpreter.process_page(page) # 解析結果からレイアウトを取得 layout = device.get_result() # レイアウトからテキストの座標を取得し表示 for element in layout: if hasattr(element, "get_text"): x1, y1, x2, y2 = element.bbox if x1 > x_left_bottom_val and y1 > y_left_bottom_val and x2 < x_right_top_val and y2 < y_right_top_val: print("Text: ", element.get_text()) # print("Position: ", element.bbox)
guest

回答1

0

自己解決

can110様にアドバイスいただいた通りコードを見直し、文末にif文を追加することで実現できました。

from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfpage import PDFTextExtractionNotAllowed
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.layout import LAParams
from pdfminer.converter import PDFPageAggregator

PDFファイルのパスを指定

pdf_file_path = "/sample.pdf"
x_left_bottom_val = 390
y_left_bottom_val = 620
x_right_top_val = 520
y_right_top_val = 740

PDFファイルをバイナリ形式で開く

with open(pdf_file_path, 'rb') as fp:
# PDFパーサーを作成
parser = PDFParser(fp)
# PDFドキュメントを作成
document = PDFDocument(parser)
# パスワードが設定されていないことを確認
if not document.is_extractable:
raise PDFTextExtractionNotAllowed
# PDFリソースマネージャーを作成
rsrcmgr = PDFResourceManager()
# ページの解析パラメータを設定
laparams = LAParams()
# ページの集約器を作成
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
# ページの解析器を作成
interpreter = PDFPageInterpreter(rsrcmgr, device)
# 全ページに対して処理を行う
for page in PDFPage.create_pages(document):
# ページの内容を解析
interpreter.process_page(page)
# 解析結果からレイアウトを取得
layout = device.get_result()
# レイアウトからテキストの座標を取得し表示
for element in layout:
if hasattr(element, "get_text"):
x1, y1, x2, y2 = element.bbox
if x1 > x_left_bottom_val and y1 > y_left_bottom_val and x2 < x_right_top_val and y2 < y_right_top_val:
print("Text: ", element.get_text())
# print("Position: ", element.bbox)

投稿2023/05/01 09:23

zy70

総合スコア4

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問