LoginSignup
0
2

More than 3 years have passed since last update.

DjangoでWebアプリを作ってみる。【vol. 07 有価証券報告書から抜き出した役員情報を加工する。】

Posted at

こちらの記事の続きです。

HTMLからスクレイピングしたデータを加工する。

前回完了時点では以下のように不要なものが混じってます。
主に改行やスペースです。※改行は分かりやすいように「/」に変換しています。
あと数字が全角だったり半角だったりするので統一感がありません。

...
//執行役//
-------------------------------------
//常務///(R&Dプラットフォーム担当、メディカル事業担当)//
-------------------------------------
//勝本 徹//
-------------------------------------
//1957年10月14日生//
-------------------------------------
/ ///////////////1982年4月/////当社入社///////2012年11月/////当社業務執行役員 SVP///////2013年4月/////ソニー・オリンパスメディカルソリューションズ㈱
代表取締役社長///////2016年1月/////ソニー・オリンパスメディカルソリューションズ㈱ 取締役(現在)///////2017年1月/////当社メディカルビジネスグループ長///////2017年4月/////ソニーイメージングプロダクツ&ソリューションズ 代表取締役副社長(現在)///////2018年4月/////当社執行役 EVP///当社R&Dプラットフォー
ム担当、メディカル事業担当(現在)///////2018年6月/////当社執行役 常務(現在)/////// /
-------------------------------------
//*//
-------------------------------------
//1//
...

そこでまず不要なものを削ったり、数字の半角寄せをするメソッドを用意します。

number_translate_dictionary = {"0":"0","1":"1","2":"2","3":"3","4":"4","5":"5","6":"6","7":"7","8":"8","9":"9"}
trans_table = str.maketrans(number_translate_dictionary)

#...(中略)...

def process_item(item):
    return item.translate(trans_table).strip("/")

全角数字から半角数字に変換するために、辞書を用意し、translateメソッドを使用しています。
こちらの記事に記載の内容になります。
そして、stripメソッドを使って項目の前後にある「/」を削っています。

続いて、各項目をモデルに詰め込むためのメソッドを用意します。
ここでは、役員情報が7列で構成されているので、引数であるcolumn_value_listには7項目入っている想定です。

念のため各項目を設定するときにifで確認をしています。
process_itemで項目を加工しつつ、個別の項目によっては追加でreplaceをしています。

from edinet.models import CorporateOfficer

#...(中略)...

def create_corporate_officer(column_value_list):
    corporate_officer = CorporateOfficer()

    if len(column_value_list) > 0:
        corporate_officer.position = process_item(column_value_list[0]).replace("/","")

    if len(column_value_list) > 1:
        corporate_officer.job = process_item(column_value_list[1]).replace("/","")

    if len(column_value_list) > 2:
        corporate_officer.name = process_item(column_value_list[2])

    if len(column_value_list) > 3:
        corporate_officer.birthday = process_item(column_value_list[3])

    if len(column_value_list) > 4:
        corporate_officer.biography = get_biography_value(column_value_list)

    if len(column_value_list) > 5:
        corporate_officer.term = process_item(column_value_list[5])

    if len(column_value_list) > 6:
        corporate_officer.stock = process_item(column_value_list[6])

    return corporate_officer

経歴だけ複数行に渡って構成されているので、別途加工用のメソッドを用意しています。

import re

#...(中略)...

def get_biography_value(column_value_list):
    biography = process_item(column_value_list[4])
    biography_list = biography.split("/")

    number = 1
    value = ""
    for target in biography_list:
        if target.strip() != "":
            if re.search("[0-9]",target):
                number = 1

                if value.strip() != "":
                    value += "\n"

            if number == 1:
                value += target + " "
                number += 1
                continue

            if number == 2:
                value += target
                continue
    return value

一度、「/」でsplitしてリストに変換してから、数字が含まれるものは左辺、それ以外は右辺という形で2017年4月 ソニーイメージングプロダクツ&ソリューションズ 代表取締役副社長(現在)といった経歴の1行を構成していきます。

CorporateOfficerのリストを作って行く処理は、こういった形です。

def get_corporate_officer_list(soup):

    corporate_officer_list = list()

    for table in soup.find_all("table"):
        for tr in table.find_all_next("tr"):

            column_value_list = list()

            if len(tr.find_all("td")) > 7:
                for child in tr.children:
                    if child.name == "td":
                        column_value_list.append(child.get_text().replace('\n', '/'))

            if len(column_value_list) > 0:
                corporate_officer = create_corporate_officer(column_value_list)
                corporate_officer_list.append(corporate_officer)

    return corporate_officer_list

わかりやすさを優先して、一度column_value_listに必要な1行分の項目を詰めて、create_corporate_officerを使って、CorporateOfficerのインスタンスを生成、そしてリストに詰めています。

最終的にこういった形でprintしてみました。

            corporate_officer_list = get_corporate_officer_list(soup) 

            for corporate_officer in corporate_officer_list:
                print("-------------")
                print("【役名】")
                print(corporate_officer.position)
                print("【職名】")
                print(corporate_officer.job)
                print("【氏名】")
                print(corporate_officer.name)
                print("【生年月日】")
                print(corporate_officer.birthday)
                print("【経歴】")
                print(corporate_officer.biography)
                print("【任期】")
                print(corporate_officer.term)
                print("【株式数】")
                print(corporate_officer.stock) 

結果は、こんな感じです。だいぶきれいになりました。

...

【役名】
執行役
【職名】
常務(R&Dプラットフォーム担当、メディカル事業担当)
【氏名】
勝本 徹
【生年月日】
1957年10月14日生
【経歴】
1982年4月 当社入社
2012年11月 当社業務執行役員 SVP
2013年4月 ソニー・オリンパスメディカルソリューションズ㈱ 代表取締役社長
2016年1月 ソニー・オリンパスメディカルソリューションズ㈱ 取締役(現在)
2017年1月 当社メディカルビジネスグループ長
2017年4月 ソニーイメージングプロダクツ&ソリューションズ 代表取締役副社長(現在)
2018年4月 当社執行役 EVP当社R&Dプラットフォーム担当、メディカル事業担当(現在)
2018年6月 当社執行役 常務(現在)
【任期】
*
【株式数】
1

次は、画面に表示してみたいと思います。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2