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

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

ただいまの
回答率

88.21%

pythonを使ってPDFファイルからデータを抽出したい

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 114

samankoar

score 4

初めてスクラピングやっています
このURL [https://www.jpx.co.jp/listing/stocks/new/nlsgeu000005bzt3-att/03Broad-Minded-Outline.pdf]のデータを表に入れ込みたいです。仕事上で頻繁にやる作業なので自動化をはかりたい。

import pdfplumber
import re
import requests
from bs4 import BeautifulSoup
from datetime import datetime as dt
import pandas as pd

url = 'https://www.jpx.co.jp/listing/stocks/new/nlsgeu000005bzt3-att/03Broad-Minded-Outline.pdf'

def download_file(url):
    local_filename = url.split('/')[-1]

    with requests.get(url) as r:
        with open(local_filename, 'wb') as f:
            f.write(r.content)

    return local_filename

ap = download_file(url)
ap

with pdfplumber.open(ap) as pdf:
    page = pdf.pages[0]
    text = page.extract_text()

print(text)

for line in text.split('\n'):
    print(line)
    el_num = line.split()
    print(el_num)

ここまで何とかググりながらたどり着いたが、この後はもうわかりません。ヒントなど教えていただければと思います。
例えば 最初の行を二つのセルに分けたいです

  1. 会 社 名    2. ブロードマインド株式会社
    2列のデータフレームを作れたらいいと思います

splitをかけた後、1文字づつになっているものが1列目 複数で一塊になっているのが2列目でしょうがreの使い方をイマイチわからない

どうぞよろしくお願いします

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

中点が文字化けするので、手抜きの処理です。

import pdfplumber
import re
import requests
import pandas as pd

items = '''会 社 名
( 英 訳 名 )
上 場 予 定 日
市 場 区 分
既 上 場 市 場
代 表 者 の 役 職 氏 名
本 店 所 在 地
Tel
(最寄りの連絡場所)
ホームページアドレス
設 立 年 月 日
事 業 の 内 容
業 種 別 分 類.*コ ー ド
銘 柄 略 称
銘 柄 順 位
発 行 可 能 株 式 総 数
発 行 済 株 式 総 数
上場時発行済株式総数
資 本 金
1 単 元 の 株 式 数
事 業 年 度
定 時 株 主 総 会
基 準 日
剰余金の配当の基準日
株 主 名 簿 管 理 人
監 査 人
幹 事 取 引 参 加 者'''

item_list = items.split('\n')
item_list2 = item_list.copy()
item_list2[12] = '業 種 別 分 類 コ ー ド'

url = 'https://www.jpx.co.jp/listing/stocks/new/nlsgeu000005bzt3-att/03Broad-Minded-Outline.pdf'

def download_file(url):
    local_filename = url.split('/')[-1]
    with requests.get(url) as r:
        with open(local_filename, 'wb') as f:
            f.write(r.content)
    return local_filename

ap = download_file(url)
ap

with pdfplumber.open(ap) as pdf:
    page = pdf.pages[0]
    text = page.extract_text()

#print(text)

i = 0
contents = []
for line in text.split('\n')[4:]:
    item = item_list[i]
    m = re.match('('+item_list[i]+')(.+)', line)
    if m:
        contents.append([m.groups()[1].strip()])
        i = i+1
        if i >= len(item_list):
            break
    else:
        contents[-1].append(line.strip())

df = pd.DataFrame({'items':item_list2, 'contents':['\n'.join(x) for x in contents]})


実行結果は以下です。

>>> print(df)
              items                                           contents
0             会 社 名                                       ブロードマインド株式会社
1         ( 英 訳 名 )                            (Broad-Minded Co.,Ltd.)
2         上 場 予 定 日                                         20213263           市 場 区 分                                               マザーズ
4         既 上 場 市 場                                                 なし
5   代 表 者 の 役 職 氏 名                                       代表取締役社長 伊藤 清
6         本 店 所 在 地                        〒1500022 東京都渋谷区恵比寿南一丁目557               Tel                                       0368598358
8        (最寄りの連絡場所)                                               (同上)
9        ホームページアドレス                          https://www.b-minded.com/
10        設 立 年 月 日                                          20021911        事 業 の 内 容  個人及び法人向けに保険代理店業、住宅ローン代理業、金融商品仲介\n業、宅地建物取引業に係るソ...
12  業 種 別 分 類 コ ー ド                 保険業・7343(新証券コード(ISIN)JP3831510007)
13          銘 柄 略 称                                         M-ブロードマインド
14          銘 柄 順 位                                       M-アイペットHDの次位
15  発 行 可 能 株 式 総 数                                        18,280,00016    発 行 済 株 式 総 数                           4,570,000株(2021219日現在)
17       上場時発行済株式総数  5,170,000株\n(注)1.公募分を含む。\n2.新株予約権の権利行使により増加する可...
18            資 本 金                            283,790千円(2021219日現在)
19    1 単 元 の 株 式 数                                               10020          事 業 年 度                                        41日から33121      定 時 株 主 総 会                                      毎事業年度終了後3ヵ月以内
22            基 準 日                                              33123       剰余金の配当の基準日                                        930日、33124    株 主 名 簿 管 理 人                                         三菱UFJ信託銀行㈱
25            監 査 人                                         太陽有限責任監査法人
26    幹 事 取 引 参 加 者                                             みずほ証券㈱

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/02/24 19:00

    @ppaul ご回答ありがとうございました。確かにdfとして出てきました。ただ最初のitemsをどうとればいいのかわからないです。同じサイトの英語版、例えば https://www.jpx.co.jp/english/listing/stocks/new/b5b4pj000003yozk-att/03Broad-Minded-OutlineEN.pdf にitemsの作成に苦節しています。変なとこに改行があったり…単純に i = 0
    contents = []
    for line in text.split('\n’)[6:]:
    item = item_list[i]
    m = re.match('('+item_list[i]+')(.+)', line)
    if m:
    contents.append([m.groups()[1].strip()])
    i = i+1
    if i >= len(item_list):
    break
    else:
    contents[-1].append(line.strip())

    df = pd.DataFrame({'items':item_list2, 'contents':['\n'.join(x) for x in contents]}) でいけません。またもアドバイス頂ければありがたいです

    キャンセル

0

天下の日本取引所が提出させるデータ。
どの法人を見てもフォーマットはきっちり固まってるみたい(どの項目が並んでいるか、が法人によりほとんどバラつきがない)なんで、
まずは
coporation = line.replace("会 社 名","").lstrip()

とかでちまちまやった方が楽なんじゃないでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る