Files
aki_prj23_transparenzregister/Jupyter/API-tests/Bundesanzeiger/notebook.ipynb

28 KiB

Daten Extraktion aus dem Bundesanzeiger

In order to run this notebooks, download the deutschland library source code from: TrisNol/deutschland and place it in the Jupyter/API-tests/Bundesanzeiger/deutschland directory. Since the PR adding the required features to the main repo has not been completet as of of yet (see: PR) we have to include it in another way...

Vorbereitung

In [5]:
import pandas as pd
from deutschland.bundesanzeiger import Bundesanzeiger
C:\Users\trist\AppData\Roaming\Python\Python310\site-packages\requests\__init__.py:102: RequestsDependencyWarning: urllib3 (1.26.12) or chardet (5.1.0)/charset_normalizer (2.0.12) doesn't match a supported version!
  warnings.warn("urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
In [6]:
ba = Bundesanzeiger()
reports = ba.get_reports("Atos IT-Dienstleistung und Beratung GmbH")
print(reports.keys())
dict_keys(['040860c00ef9020cfb6db2f58a163256', '9eb401c5af2f0289b8207233bf852b81', 'b14d979ea9f42367d413589050bd04e5', 'ecb8c1011456ea0d40f87e850fc216bf', '3a7c6c1f1d1b89bf5ceb165f0ee88053', '03b2e6aac2f2da2c0c5e8f23de9caec4', 'a5f8dc87fa797e7d2f8fb88c49a23c36', '9a3a8a3e84290ee650cbccf32323b3d7', '6c0fcc20a58aaa18a9d13f35a51e3996', 'bf276d441c339e787e22385d2b69b277', '90a79d28f3c11a2122d2827d2bf6acda', '88c785ce3b3c580dcc285661c7790cca', 'd3064baa8246c3ed02e30b5038200edc', '5bf92eed2808b484c005409764b825b7', 'fece6303c991a280850be1900ff78f8f', '26b0624c60cdbf647f3d45f4917ec6ea', '9f98bee55f598908cca60b6a47e5d49d', '99267bb7474e6d1d5d9e091ba5ef3ee8', '102738ef4b91408ed043d84fe785b50b', '94711f3e509518d073e1760d97550347'])
In [7]:
report_contents = []
for key in reports.keys():
    report_contents.append(reports[key])
In [8]:
df_reports = pd.DataFrame(report_contents)
df_reports.head()
Out[8]:
<style scoped=""> .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </style>
date name company report raw_report
0 2023-03-17 Aufsichtsrat Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\n\n\n\nAtos IT-Dienstl... <div class="publication_container">\n <div cla...
1 2022-03-25 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtos IT-Dienstleistun... <div class="publication_container">\n <div cla...
2 2021-03-11 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtos IT-Dienstleistun... <div class="publication_container">\n <div cla...
3 2020-03-24 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtosIT-Dienstleistung... <div class="publication_container">\n <div cla...
4 2018-12-11 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtos IT-Dienstleistun... <div class="publication_container">\n <div cla...
In [9]:
df_reports["type"] = df_reports.name.apply(lambda name: name.split(" ")[0])
df_reports.head()
Out[9]:
<style scoped=""> .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </style>
date name company report raw_report type
0 2023-03-17 Aufsichtsrat Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\n\n\n\nAtos IT-Dienstl... <div class="publication_container">\n <div cla... Aufsichtsrat
1 2022-03-25 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtos IT-Dienstleistun... <div class="publication_container">\n <div cla... Jahresabschluss
2 2021-03-11 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtos IT-Dienstleistun... <div class="publication_container">\n <div cla... Jahresabschluss
3 2020-03-24 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtosIT-Dienstleistung... <div class="publication_container">\n <div cla... Jahresabschluss
4 2018-12-11 Jahresabschluss zum Geschäftsjahr vom 01.01.20... Atos IT-Dienstleistung und Beratung GmbH \n\n\n\n \n\n\n\n\n\n\n\nAtos IT-Dienstleistun... <div class="publication_container">\n <div cla... Jahresabschluss
In [10]:
df_jahresabschluss = df_reports.loc[df_reports.type == "Jahresabschluss"]
df_jahresabschluss["jahr"] = df_jahresabschluss.name.apply(
    lambda name: name.split(" ")[-1].split(".")[-1]
)
df_jahresabschluss = df_jahresabschluss.drop(["name", "report", "type"], axis=1)
df_jahresabschluss.head()
C:\Users\trist\AppData\Local\Temp\ipykernel_6460\963182859.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  df_jahresabschluss['jahr'] = df_jahresabschluss.name.apply(
Out[10]:
<style scoped=""> .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </style>
date company raw_report jahr
1 2022-03-25 Atos IT-Dienstleistung und Beratung GmbH <div class="publication_container">\n <div cla... 2020
2 2021-03-11 Atos IT-Dienstleistung und Beratung GmbH <div class="publication_container">\n <div cla... 2019
3 2020-03-24 Atos IT-Dienstleistung und Beratung GmbH <div class="publication_container">\n <div cla... 2018
4 2018-12-11 Atos IT-Dienstleistung und Beratung GmbH <div class="publication_container">\n <div cla... 2017
6 2018-01-03 Atos IT-Dienstleistung und Beratung GmbH <div class="publication_container">\n <div cla... 2016

Daten Extraktion

In [11]:
from bs4 import BeautifulSoup
from io import StringIO
In [12]:
sample_report = df_jahresabschluss.iloc[0].raw_report

Wirtschaftsprüfer

In [14]:
import re


def extract_auditors(report: str) -> list:
    auditor_regex = r"[a-z A-Z,.'-]+, Wirtschaftsprüfer"
    hits = re.findall(auditor_regex, report)
    return [hit.replace(", Wirtschaftsprüfer", "").lstrip() for hit in hits]
In [15]:
extract_auditors(sample_report)
Out[15]:
['Eckhard Lewe', 'Renate Hermsdorf']
In [16]:
def extract_auditor_company(report: str) -> str:
    soup = BeautifulSoup(report, features="html.parser")
    temp = soup.find_all("b")
    for elem in temp:
        br = elem.findChildren("br")
        if len(br) > 0:
            return elem.text.split("\n")[1].strip()
    return None
In [17]:
extract_auditor_company(sample_report)
Out[17]:
'Warth & Klein Grant Thornton AG'

Aufsichtsrat

TODO

Bilanz bzw. GuV

In [18]:
def get_bilanz(report: str) -> any:
    result = {}
    soup = BeautifulSoup(report, features="html.parser")
    for pos in ["Aktiva", "Passiva"]:
        tag = soup.find("b", string=re.compile(pos))
        if tag:
            pos_results = pd.read_html(
                StringIO(str(tag.findNext("table", {"class": "std_table"})))
            )[0]
            result[pos] = pos_results
    return result


bilanz = get_bilanz(sample_report)
bilanz["Passiva"].head()
Out[18]:
<style scoped=""> .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </style>
Unnamed: 0 Anhang 2020 TEUR Vorjahr TEUR
0 1. Umsatzerlöse (1) 69.819 77.429
1 2. Veränderung des Bestandes an unfertigen Lei... NaN -41.000 -66.000
2 3. Sonstige betriebliche Erträge (2) 489.000 1.816
3 4. Materialaufwand NaN NaN NaN
4 a) Aufwendungen für bezogene Waren NaN -1.220 -3.003
In [19]:
def get_tables(raw_report: str) -> list:
    soup = BeautifulSoup(raw_report, features="html.parser")
    tables = soup.find_all("table", {"class": "std_table"})
    dfs = []
    for table in tables:
        for df in pd.read_html(StringIO(str(table))):
            dfs.append(df)
    return dfs


for df in get_tables(sample_report):
    print(df.columns)

tables = get_tables(sample_report)
Index(['Gesellschafterbeschluss', 'Shareholder Resolution'], dtype='object')
Index(['Unnamed: 0', 'Anhang', '31.12.2020  TEUR', 'Vorjahr  TEUR'], dtype='object')
Index(['Unnamed: 0', 'Anhang', '2020  TEUR', 'Vorjahr  TEUR'], dtype='object')
Index(['Aufgliederung nach Tätigkeitsbereichen', '2020  TEUR',
       'Vorjahr  TEUR'],
      dtype='object')
Index(['Aufgliederung nach Inland und Ausland', '2020  TEUR', 'Vorjahr  TEUR'], dtype='object')
Index(['Unnamed: 0', '31.12.2020  TEUR', 'Vorjahr  TEUR'], dtype='object')
Index(['Unnamed: 0', '31.12.2020  TEUR', 'Vorjahr  TEUR'], dtype='object')
Index(['Unnamed: 0', '31.12.2020'], dtype='object')
Index(['Unnamed: 0', 'TEUR'], dtype='object')
Index(['Unnamed: 0', 'TEUR'], dtype='object')
Index(['Unnamed: 0', 'TEUR'], dtype='object')
Int64Index([0, 1, 2], dtype='int64')
Index(['Unnamed: 0', 'TEUR'], dtype='object')
Index(['Unnamed: 0', '31.12.2020  TEUR', 'Vorjahr  TEUR'], dtype='object')
Index(['Unnamed: 0', '2020 Anzahl MA', 'Vorjahr Anzahl MA'], dtype='object')
MultiIndex([('Art des Geschäfts',           'Unnamed: 0_level_1'),
            ('Art der Beziehung',       'Gesellschafterin  TEUR'),
            ('Art der Beziehung', 'Verbundene Unternehmen  TEUR')],
           )
Int64Index([0, 1], dtype='int64')
MultiIndex([(                   'Unnamed: 0_level_0', ...),
            ('Anschaffungs- oder Herstellungskosten', ...),
            ('Anschaffungs- oder Herstellungskosten', ...),
            ('Anschaffungs- oder Herstellungskosten', ...),
            ('Anschaffungs- oder Herstellungskosten', ...)],
           )
MultiIndex([('Unnamed: 0_level_0',                      'Unnamed: 0_level_1'),
            (    'Abschreibungen',                   'Stand 01.01.2020  EUR'),
            (    'Abschreibungen', 'Abschreibungen des Geschäftsjahres  EUR'),
            (    'Abschreibungen',                  'Abgänge Umbuchung  EUR'),
            (    'Abschreibungen',                   'Stand 31.12.2020  EUR')],
           )
MultiIndex([('Unnamed: 0_level_0',    'Unnamed: 0_level_1'),
            (         'Buchwerte', 'Stand 31.12.2020  EUR'),
            (         'Buchwerte', 'Stand 31.12.2019  EUR')],
           )
Index(['Nichtfinanzieller Leistungsindikator', 'Unnamed: 1', '2020', '2019',
       '2018'],
      dtype='object')
Index(['Gewinn- und Verlustrechnung', '2020  TEUR', 'Vorjahr  TEUR',
       'Veränderung  TEUR'],
      dtype='object')
Index(['Bilanz', '31.12.2020  TEUR', 'Vorjahr  TEUR', 'Veränderung  TEUR'], dtype='object')
Index(['Bericht des Aufsichtsrats', 'Report of the Supervisory Board'], dtype='object')