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

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

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

2回答

5766閲覧

正規表現を使ってPDFのテキストを抽出したい

hiroki_0926

総合スコア18

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

2クリップ

投稿2017/09/02 15:08

###実現したいこと
https://teratail.com/questions/90447
上記の続きで質問をさせて頂きます。

正規表現を使って、下記に記載したデータのうち、太字にしているテキストのみを抽出したいのですが、どのように書いたら良いでしょうか?
恐らく、LTTextBoxHorizontal()のあとにくる "432.591"(これは座標?)を使うとよいのではないかとは思うのですが。。

正規表現について全く理解出来ておらず、初歩的な質問でごめんなさい。

###得られているデータ
<LTTextBoxHorizontal(0) 29.270,548.169,174.710,561.719 '◎マーケット概況 (2017/8/22)\n'>
<LTTextBoxHorizontal(1) 72.111,373.722,180.732,391.944 'ムンバイ SENSEX30種 31,291.85\nブラジル ボベスパ指数 70,011.25\n
'>
<LTTextBoxHorizontal(2) 67.671,365.082,180.732,374.784 'FTSE/JSE アフリカ トップ40指数 49,588.44\n'>
<LTTextBoxHorizontal(3) 98.029,533.845,112.242,541.066 '指標\n'>
<LTTextBoxHorizontal(4) 72.471,467.936,137.782,526.874 '日経平均株価\n日経225シカゴ(先物)\nTOPIX(東証株価指数)\nジャ
スダック指数\nNYダウ 工業株30種\nナスダック 総合指数\nMSCIカナダ指数\n'>

<途中省略>

<LTTextBoxHorizontal(47) 475.911,408.778,536.711,417.622 'S&P先進国REIT指数\n'>
<LTTextBoxHorizontal(48) 487.190,391.618,525.431,408.382 'WTI原油先物\nNY金先物\n'>
<LTTextBoxHorizontal(49) 435.231,471.371,460.759,481.839 '為替※4\n'>
<LTTextBoxHorizontal(50) 435.111,412.331,460.795,420.931 'リート\n'>
<LTTextBoxHorizontal(51) 439.431,395.171,456.476,403.771 '商品\n'>
<LTTextBoxHorizontal(52) 432.591,345.965,806.637,380.140 '【株式】\n●国内株は小幅に下落。北朝鮮を巡る地政学リスクや米ト
ランプ政権の混迷を警戒し、日経平均の終値は5月1日以来、3か月半ぶ\nりの安値を付けた。
\n●米国株は上昇。前日まで下げが続い
たハイテク株などへの値ごろ感に着目した買い、および税制改革への期待が相場を押し上げた。
\n'>
<LTTextBoxHorizontal(53) 432.591,300.725,804.984,334.900 '【債券】\n●国内債は小幅に下落。20年債入札の結果発表を前に持ち
高整理の売りが先行したものの、入札の結果が順調だったことから相\n場は堅調に推移した。
\n●米国債は下落。税制改革への期待か
ら米国株が上昇したことを受けて、米国債には売りが広がった。
\n'>
<LTTextBoxHorizontal(54) 432.591,246.485,805.164,289.540 '【為替】\n●東京時間では、1ドル=109円35銭近辺、1ユーロ=128円95
銭近辺で終了。日本の長期金利は上昇したものの、米国の金利上昇と\n比べ相対的に小さく、日米金利差の拡大を受けて、円売り・米
ドル買いが優勢となった。
\n●欧米時間では、1ドル=109円60銭近辺、1ユーロ128円90銭近辺で終了。米国株の上昇および日米金利差
の拡大観測が円売り・\n米ドル買いを誘った。
\n'>
<LTTextBoxHorizontal(55) 432.591,210.245,583.778,226.180 '【リート・商品】\n●東証REIT指数、原油先物は上昇。金先物は下落
\n'>
<LTTextBoxHorizontal(56) 30.590,187.506,116.022,197.425 '◎主な指標・イベント\n'>
<LTTextBoxHorizontal(57) 132.111,189.289,293.289,195.914 '※主な指標・イベントは予告無く変更されることがあります。\n'>
<以下省略>

###ソースコード
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfparser import PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfparser import PDFPage
from pdfminer.pdfdevice import PDFDevice
from pdfminer.converter import PDFPageAggregator
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.layout import LTTextBoxHorizontal

fp = open(PDF_file, 'rb')

parser = PDFParser(fp)
document = PDFDocument()
parser.set_document(document)

password=""
document.set_parser(parser)
document.initialize(password)

rsrcmgr = PDFResourceManager()

laparams = LAParams()

device = PDFPageAggregator(rsrcmgr, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)

pages = list(document.get_pages())
page_1 = pages[0]

interpreter.process_page(page_1)

layout = device.get_result()

for l in layout:
if isinstance(l, LTTextBoxHorizontal):
#print(l)
print(l.get_text())

###補足情報
windows7、python3.6.1を使用しています。

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

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

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

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

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

mdj

2017/09/04 04:17

改行はデータ取得した状態で「\n」という文字列なんでしょうか?もしくは書き込む際に「\n」として書いたのでしょうか。後者であれば全てのテキストデータを変数に結合してから、 <LTTextBoxHorizontal\([0-9]+?\) [0-9\., ]+? '(【.+)'> とかで group(1) の値を得るなどがあるかと思います。実際のPDFを見ないと正しく取得できる正規表現はわからないので、調整していただければと思います。
hiroki_0926

2017/09/04 07:07

分かりづらくて、ごめんなさい。\nは取得したデータの文字列です。
mdj

2017/09/04 07:59

「\n」は文字列ということで承知いたしました。それでは1行取得した毎に <LTTextBoxHorizontal\([0-9]+?\) [0-9\., ]+? '(【.+)'> としても同じです。can110さんがご回答をされていますのでそちらをご使用されるのが良いかと思いますが、「\n」の指定を「\\n」(エスケープ)にする必要があるかと思います。
guest

回答2

0

ベストアンサー

提示データ中の\nは実際に改行文字として回答します。
re.DOTALLを指定することで、任意の1文字.にて改行も含めることができます。
また、必要な部分のみ.groupで抽出しています。
抽出後の文字にも、改行や不要と思われる空白文字が含まれていますが、不要であれば.replaceなどで適宜取り除いてください。

参考:Python: 正規表現で複数行マッチングの置換を行う

実行例

Python

1lines = [ 2 "<LTTextBoxHorizontal(47) 475.911,408.778,536.711,417.622 'S&P先進国REIT指数\n'>", 3 "<LTTextBoxHorizontal(48) 487.190,391.618,525.431,408.382 'WTI原油先物\nNY金先物\n'>", 4 "<LTTextBoxHorizontal(49) 435.231,471.371,460.759,481.839 '為替※4\n'>", 5 "<LTTextBoxHorizontal(50) 435.111,412.331,460.795,420.931 'リート\n'>", 6 "<LTTextBoxHorizontal(51) 439.431,395.171,456.476,403.771 '商品\n'>", 7 "<LTTextBoxHorizontal(52) 432.591,345.965,806.637,380.140 '【株式】\n●国内株は小幅に下落。北朝鮮を巡る地政学リスクや米ト ランプ政権の混迷を警戒し、日経平均の終値は5月1日以来、3か月半ぶ\nりの安値を付けた。\n●米国株は上昇。前日まで下げが続い たハイテク株などへの値ごろ感に着目した買い、および税制改革への期待が相場を押し上げた。\n'>", 8 "<LTTextBoxHorizontal(53) 432.591,300.725,804.984,334.900 '【債券】\n●国内債は小幅に下落。20年債入札の結果発表を前に持ち 高整理の売りが先行したものの、入札の結果が順調だったことから相\n場は堅調に推移した。\n●米国債は下落。税制改革への期待か ら米国株が上昇したことを受けて、米国債には売りが広がった。\n'>", 9 "<LTTextBoxHorizontal(54) 432.591,246.485,805.164,289.540 '【為替】\n●東京時間では、1ドル=109円35銭近辺、1ユーロ=128円95 銭近辺で終了。日本の長期金利は上昇したものの、米国の金利上昇と\n比べ相対的に小さく、日米金利差の拡大を受けて、円売り・米 ドル買いが優勢となった。\n●欧米時間では、1ドル=109円60銭近辺、1ユーロ128円90銭近辺で終了。米国株の上昇および日米金利差 の拡大観測が円売り・\n米ドル買いを誘った。\n'>", 10 "<LTTextBoxHorizontal(55) 432.591,210.245,583.778,226.180 '【リート・商品】\n●東証REIT指数、原油先物は上昇。金先物は下落 。\n'>", 11 "<LTTextBoxHorizontal(56) 30.590,187.506,116.022,197.425 '◎主な指標・イベント\n'>", 12 "<LTTextBoxHorizontal(57) 132.111,189.289,293.289,195.914 '※主な指標・イベントは予告無く変更されることがあります。\n'>", 13] 14 15import re 16r = re.compile( r"'((【株式】|【債券】|【為替】|【リート・商品】).*?)'\n>",flags=(re.MULTILINE | re.DOTALL)) 17 18for l in lines: 19 print('=====') 20 print(l) 21 print('=====') 22 ret = r.search(l) 23 if ret: 24 s = ret.group(1) 25 print('-----') 26 print(s) 27 print('-----')

結果例

===== <LTTextBoxHorizontal(47) 475.911,408.778,536.711,417.622 'S&P先進国REIT指数 '> ===== ===== <LTTextBoxHorizontal(48) 487.190,391.618,525.431,408.382 'WTI原油先物 NY金先物 '> ===== ===== <LTTextBoxHorizontal(49) 435.231,471.371,460.759,481.839 '為替※4 '> ===== ===== <LTTextBoxHorizontal(50) 435.111,412.331,460.795,420.931 'リート '> ===== ===== <LTTextBoxHorizontal(51) 439.431,395.171,456.476,403.771 '商品 '> ===== ===== <LTTextBoxHorizontal(52) 432.591,345.965,806.637,380.140 '【株式】 ●国内株は小幅に下落。北朝鮮を巡る地政学リスクや米ト ランプ政権の混迷を警戒し、 日経平均の終値は5月1日以来、3か月半ぶ りの安値を付けた。 ●米国株は上昇。前日まで下げが続い たハイテク株などへの値ごろ感に着目した買い、 および税制改革への期待が相場を押し上げた。 '> ===== ----- 【株式】 ●国内株は小幅に下落。北朝鮮を巡る地政学リスクや米ト ランプ政権の混迷を警戒し、 日経平均の終値は5月1日以来、3か月半ぶ りの安値を付けた。 ●米国株は上昇。前日まで下げが続い たハイテク株などへの値ごろ感に着目した買い、 および税制改革への期待が相場を押し上げた。 ----- ===== <LTTextBoxHorizontal(53) 432.591,300.725,804.984,334.900 '【債券】 ●国内債は小幅に下落。20年債入札の結果発表を前に持ち 高整理の売りが先行したもの の、入札の結果が順調だったことから相 場は堅調に推移した。 ●米国債は下落。税制改革への期待か ら米国株が上昇したことを受けて、米国債には売 りが広がった。 '> ===== ----- 【債券】 ●国内債は小幅に下落。20年債入札の結果発表を前に持ち 高整理の売りが先行したもの の、入札の結果が順調だったことから相 場は堅調に推移した。 ●米国債は下落。税制改革への期待か ら米国株が上昇したことを受けて、米国債には売 りが広がった。 ----- ===== <LTTextBoxHorizontal(54) 432.591,246.485,805.164,289.540 '【為替】 ●東京時間では、1ドル=109円35銭近辺、1ユーロ=128円95 銭近辺で終了。日本の長期金 利は上昇したものの、米国の金利上昇と 比べ相対的に小さく、日米金利差の拡大を受けて、円売り・米 ドル買いが優勢となった。 ●欧米時間では、1ドル=109円60銭近辺、1ユーロ128円90銭近辺で終了。米国株の上昇お よび日米金利差 の拡大観測が円売り・ 米ドル買いを誘った。 '> ===== ----- 【為替】 ●東京時間では、1ドル=109円35銭近辺、1ユーロ=128円95 銭近辺で終了。日本の長期金 利は上昇したものの、米国の金利上昇と 比べ相対的に小さく、日米金利差の拡大を受けて、円売り・米 ドル買いが優勢となった。 ●欧米時間では、1ドル=109円60銭近辺、1ユーロ128円90銭近辺で終了。米国株の上昇お よび日米金利差 の拡大観測が円売り・ 米ドル買いを誘った。 ----- ===== <LTTextBoxHorizontal(55) 432.591,210.245,583.778,226.180 '【リート・商品】 ●東証REIT指数、原油先物は上昇。金先物は下落 。 '> ===== ----- 【リート・商品】 ●東証REIT指数、原油先物は上昇。金先物は下落 。 ----- ===== <LTTextBoxHorizontal(56) 30.590,187.506,116.022,197.425 '◎主な指標・イベント '> ===== ===== <LTTextBoxHorizontal(57) 132.111,189.289,293.289,195.914 '※主な指標・イベントは 予告無く変更されることがあります。 '> =====

文字列データ中の「\n」がそのままの文字列である場合

以下のような、より単純な正規表現で抽出できます。
「\n」を取り除きたい場合は、以下に示すように.replaceで取り除けます。

Python

1lines = [ 2 r"<LTTextBoxHorizontal(47) 475.911,408.778,536.711,417.622 'S&P先進国REIT指数\n'>", 3 r"<LTTextBoxHorizontal(48) 487.190,391.618,525.431,408.382 'WTI原油先物\nNY金先物\n'>", 4 r"<LTTextBoxHorizontal(49) 435.231,471.371,460.759,481.839 '為替※4\n'>", 5 r"<LTTextBoxHorizontal(50) 435.111,412.331,460.795,420.931 'リート\n'>", 6 r"<LTTextBoxHorizontal(51) 439.431,395.171,456.476,403.771 '商品\n'>", 7 r"<LTTextBoxHorizontal(52) 432.591,345.965,806.637,380.140 '【株式】\n●国内株は小幅に下落。北朝鮮を巡る地政学リスクや米ト ランプ政権の混迷を警戒し、日経平均の終値は5月1日以来、3か月半ぶ\nりの安値を付けた。\n●米国株は上昇。前日まで下げが続い たハイテク株などへの値ごろ感に着目した買い、および税制改革への期待が相場を押し上げた。\n'>", 8 r"<LTTextBoxHorizontal(53) 432.591,300.725,804.984,334.900 '【債券】\n●国内債は小幅に下落。20年債入札の結果発表を前に持ち 高整理の売りが先行したものの、入札の結果が順調だったことから相\n場は堅調に推移した。\n●米国債は下落。税制改革への期待か ら米国株が上昇したことを受けて、米国債には売りが広がった。\n'>", 9 r"<LTTextBoxHorizontal(54) 432.591,246.485,805.164,289.540 '【為替】\n●東京時間では、1ドル=109円35銭近辺、1ユーロ=128円95 銭近辺で終了。日本の長期金利は上昇したものの、米国の金利上昇と\n比べ相対的に小さく、日米金利差の拡大を受けて、円売り・米 ドル買いが優勢となった。\n●欧米時間では、1ドル=109円60銭近辺、1ユーロ128円90銭近辺で終了。米国株の上昇および日米金利差 の拡大観測が円売り・\n米ドル買いを誘った。\n'>", 10 r"<LTTextBoxHorizontal(55) 432.591,210.245,583.778,226.180 '【リート・商品】\n●東証REIT指数、原油先物は上昇。金先物は下落 。\n'>", 11 r"<LTTextBoxHorizontal(56) 30.590,187.506,116.022,197.425 '◎主な指標・イベント\n'>", 12 r"<LTTextBoxHorizontal(57) 132.111,189.289,293.289,195.914 '※主な指標・イベントは予告無く変更されることがあります。\n'>", 13] 14 15import re 16r = re.compile( r"'((【株式】|【債券】|【為替】|【リート・商品】).*?)'>") 17 18for l in lines: 19 ret = r.search(l) 20 if ret: 21 s = ret.group(1) 22 s = s.replace( r'\n', '') # 「\n」を除去 23 print('-----') 24 print(s) 25 print('-----')

結果例

----- 【株式】●国内株は小幅に下落。北朝鮮を巡る地政学リスクや米ト ランプ政権の混迷を 警戒し、日経平均の終値は5月1日以来、3か月半ぶりの安値を付けた。●米国株は上昇。 前日まで下げが続い たハイテク株などへの値ごろ感に着目した買い、および税制改革へ の期待が相場を押し上げた。 ----- ----- 【債券】●国内債は小幅に下落。20年債入札の結果発表を前に持ち 高整理の売りが先行 したものの、入札の結果が順調だったことから相場は堅調に推移した。●米国債は下落。税制改革への期待か ら米国株が上昇したことを受けて、米国債には売りが広がった。 ----- ----- 【為替】●東京時間では、1ドル=109円35銭近辺、1ユーロ=128円95 銭近辺で終了。日本 の長期金利は上昇したものの、米国の金利上昇と比べ相対的に小さく、日米金利差の拡大を受けて、円売り・米 ドル買いが優勢となった。●欧米時間では、1ドル=109円60銭近辺 、1ユーロ128円90銭近辺で終了。米国株の上昇および日米金利差 の拡大観測が円売り・米ドル買いを誘った。 ----- ----- 【リート・商品】●東証REIT指数、原油先物は上昇。金先物は下落 。 -----

投稿2017/09/04 04:50

編集2017/09/04 08:55
can110

総合スコア38262

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

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

hiroki_0926

2017/09/04 08:13

度々ありがとうございます。 スクリプト内にlines=[~~]をベタ打ちすると、can110さんの結果例通り出ました。 ただし、pdfを直接みるようにすると、 ret = r.search(l)に対して "expected string or bytes-like object"のエラーメッセージが出るようです。str()関数をどこかに入れる必要があるのでしょうか? ---------- for lines in layout: for l in lines: print('=====') print(l) print('=====') ret = r.search(l) if ret: s = ret.group(1) print('-----') print(s) print('-----')
can110

2017/09/04 08:23

質問に記載されているコードでのl.get_text()の戻り値は文字列でしょうか? であるなら ret = r.search(l.get_text()) とすべきかと思います。
can110

2017/09/04 08:56

また、「\n」は改行文字ではなく、単なる2文字の文字列である場合の回答も追記しました。
hiroki_0926

2017/09/06 06:39

ret = r.search(l.get_text())にしてもworkしませんでした。 なので一旦、textのみを抽出し、正規表現をかけました。 正規表現がスマートじゃないですが、欲しい箇所を抽出することが出来ました。ありがとうございました。 ------------------- r = re.compile( r"((【株式】|【債券】|【為替】).*?。.*?●.*?。.*?。)",flags=(re.MULTILINE | re.DOTALL))
guest

0

python

1#!/usr/bin/env python 2import re 3 4lines = l.get_text() 5pattern = r"【.*" 6matched = re.findall(pattern , lines) 7print(matched) 8print(len(matched))

初心者の正規表現
Pythonでの正規表現の使い方

投稿2017/09/03 02:48

NCC1701

総合スコア1680

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

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

hiroki_0926

2017/09/04 00:26

早速回答頂きありがとうございます。 教えて頂いたものでトライしてみたのですが、下記のようになり、うまくいかなかったです。 [] [] <中略> [] [] [’【株式】’] [’【債券】’] [’【為替】’] [’【リート・商品】’] [] [] <後略> ____ また、pattern = r"●.*"、とした場合は [’●国内株は小幅に下落。北朝鮮を巡る地政学リスクや米ト ランプ政権の混迷を警戒し、日経平均の終値は5月1日以来、3か月半ぶ’] といったようにPDF内で改行された部分で終わってしまいます。
NCC1701

2017/09/04 07:39

データを完全に再現はできないので、修正は必要になるはずです。 (PDFデータ自体が手元にありませんし、テキスト抽出もできないし、文字コード、改行コードも一致してないかもしれません) ポイントとなるのは正規表現の部分なので、リファレンス等を参考に修正してください。 なお以下のように検証してます。 1. 「得られているデータ」をそのままコピペでテキストファイルに保存 2. 次のスクリプトで実行 #!/usr/bin/env python # -*- coding: utf-8 -*- import re f = open('test.txt') #ここが違います lines = f.read() #ここが違います f.close() #ここが違います pattern = r"【.*" matched = re.findall(pattern , lines) print(matched) print(len(matched)) 環境:macOS(UNIX)、python2、python3
hiroki_0926

2017/09/06 06:35

リファレンスなどを参考にし、なんとか出来ました。 どうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問