Dans le 5ème article du Calendrier de l'Avent, j'essaierai d'extraire les informations souhaitées des données XBRL acquises par l'API EDINET. Cette fois, j'ai essayé de cibler le salaire moyen et l'âge moyen des entreprises que l'on voit souvent dans la recherche d'emploi.
(Le programme de cet article est fourni tel quel sans aucune garantie, et XBRL Japan assumera toute la responsabilité de tous les inconvénients ou problèmes pouvant survenir à la suite de l'utilisation de ce programme, quelle qu'en soit la cause. Je ne le supporterai pas.)
Il s'agit d'un programme en langage Python qui décompresse et analyse le fichier zip (y compris les données XBRL) acquis par l'API EDINET, extrait des informations telles que le salaire du rapport sur les titres, puis génère les informations nécessaires sous forme de CSV. (Tous les codes sont répertoriés dans "3. Code source") Les éléments à extraire des données XBRL sont indiqués dans le tableau ci-dessous.
article | Nom d'élément défini dans XBRL | Exemple d'acquisition |
---|---|---|
EDINETCODE | EDINETCodeDEI | E00004 |
Nom de la compagnie | FilerNameInJapaneseDEI | Kaneko Seedling Co., Ltd. |
Salaire annuel moyen (yen) | AverageAnnualSalaryInformationAboutReportingCompanyInformationAboutEmployees | 5,554,933 |
Années de service moyennes (années) | AverageLengthOfServiceYearsInformationAboutReportingCompanyInformationAboutEmployees | 13.0 |
Années de service moyennes (mois) | AverageLengthOfServiceMonthsInformationAboutReportingCompanyInformationAboutEmployees | - |
Âge moyen (années) | AverageAgeYearsInformationAboutReportingCompanyInformationAboutEmployees | 42.2 |
Âge moyen (mois) | AverageAgeMonthsInformationAboutReportingCompanyInformationAboutEmployees | - |
Nombre d'employés (personnes) | NumberOfEmployees | 625 |
D'autres points caractéristiques sont décrits ci-dessous. ○ Utilisez la liste de codes EDINET pour identifier le «secteur» de l'entreprise ○ Il ne correspond pas à l'acquisition du «poste d'extension unique» de la société ○ Un analyseur OSS appelé «Arelle» a été utilisé pour l'analyse XBRL. ○ S'il existe une ancienneté moyenne (mois) et un âge moyen (mois), «conversion annuelle» (arrondie à la deuxième décimale).
Veuillez prendre les mesures suivantes avant d'exécuter le programme. De plus, il est nécessaire d'installer au préalable d'autres bibliothèques. En fonction de l'environnement d'exécution, modifiez la méthode de codage et de spécification de chemin selon le cas.
Utilisez "Trouvons les données décrites dans XBRL", "Collectons les données décrites dans XBRL", etc. pour télécharger le fichier zip (y compris les données XBRL) depuis EDINET. Le salaire annuel moyen (yen) et les autres éléments sont des éléments nouvellement ajoutés sur EDINET, donc pour le moment, 2019 Téléchargez les données XBRL divulguées après le 1er avril.
Installez l'analyseur XBRL appelé Arelle. Lorsque ʻArelle` charge une instance, il analyse l'ensemble DTS, y compris les informations de taxonomie externe. Par conséquent, il convient à l'utilisation de données XBRL avancées, mais si vous n'utilisez que des instances, son traitement prend du temps, pensez donc à le remplacer par la bibliothèque XML OSS ou l'analyseur que vous développez. ..
L'article qiita contient également des informations sur la façon d'installer Arelle et d'autres analyseurs en cours de développement, je vais donc en énumérer quelques-uns ici. ・ Analyse XBRL qui ne part pas de zéro (utilisation d'Arelle)
Il peut être téléchargé à partir de la «liste de codes EDINET» au bas de la page après la transition de l'onglet [Télécharger] du site EDINET. Cette liste est répertoriée avec ʻEDINET CODE et l'industrie. Par conséquent, en utilisant cette liste, vous pouvez également acquérir le type d'entreprise de l'entreprise.
○ Choisissez un dossier de stockage pour lire la liste de codes EDINET téléchargée.
edinetcodedlinfo_filepath = 'C://Users//xxx//Desktop//xbrlReport//EdinetcodeDlInfo.csv'
○ Décidons du dossier pour stocker le fichier zip acquis par l'API EDINET.
zip_dir = 'C://Users//xxx//Desktop//xbrlReport//SR//'
xbrl_file_expressions = 'C://Users//xxx//Desktop//xbrlReport//SR//XBRL//PublicDoc//*.xbrl'
○ Choisissez le dossier et le nom de fichier pour la sortie CSV.
employee_frame.to_csv("C://Users//xxx//Desktop//xbrlReport//xbrl_qiita.csv", encoding='cp932')
Décompressez le fichier zip obtenu par l'API EDINET et récupérez la liste des «fichiers d'instance» (extension .xbrl) sous le dossier PublicDoc placé avec «glob». (L'explication du processus par décompression zip est omise)
Code1
xbrl_file_expressions = glob.glob('C:\\Users\\xxx\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\*.xbrl')
Result1
['C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E00112-000_2019-03-31_01_2019-06-27.xbrl', 'C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E01422-000_2019-03-31_01_2019-06-27.xbrl', 'C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E02770-000_2019-03-31_01_2019-06-21.xbrl', 'C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E04510-000_2019-03-31_01_2019-06-27.xbrl']
Le traitement en boucle est effectué à l'aide de xbrl_files
, et les données XBRL sont lues par le modelManager.load (xbrl_file) d'Arelle pour chaque fichier d'instance. En conséquence, vous pouvez obtenir l'objet model_xbrl d'Arelle qui contient les informations de données XBRL.
Code2
for index, xbrl_file in enumerate(xbrl_files):
ctrl = Cntlr.Cntlr()
model_manager= ModelManager.initialize(ctrl)
model_xbrl= modelManager.load(xbrl_file)
Result2
<arelle.ModelXbrl.Model_xbrl object at 0x0EF6F350>
Ensuite, le traitement en boucle est effectué à l'aide de model_xbrl.facts
, dans lequel tous les faits
(les données réelles telles que les valeurs numériques des éléments) contenues dans l'instance sont définis au format liste, et le nom d'élément de chaque fait
( fact. get concept.qname.localName
). Lorsque le nom de l'élément est le nom de l'élément à extraire cette fois, c'est un mécanisme pour acquérir la valeur numérique («fact.value») de l'élément. Lors du traitement de EDINETCODE, incorporer la logique permettant d'identifier le secteur d'activité de l'entreprise à partir de ʻEdinetcodeDlInfo.csv. En ce qui concerne le nombre d'employés, comme le même nom d'élément existe plusieurs fois, la période courante (
CurrentYearInstant) est spécifiée dans l'attribut de période appelé
context`.
Code3
for fact in model_xbrl.facts:
if fact.concept.qname.localName == 'EDINETCodeDEI':
edinet_code = fact.value
for code_name in edinet_info_list:
if code_name[0] == edinet_code:
industry_code = code_name[1]
break
elif fact.concept.qname.localName=='FilerNameInJapaneseDEI':
elif fact.concept.qname.localName=='AverageAnnualSalaryInformationAboutReportingCompanyInformationAboutEmployees':
elif fact.concept.qname.localName=='AverageLengthOfServiceYearsInformationAboutReportingCompanyInformationAboutEmployees':
elif fact.concept.qname.localName=='AverageLengthOfServiceMonthsInformationAboutReportingCompanyInformationAboutEmployees':
elif fact.concept.qname.localName=='AverageAgeYearsInformationAboutReportingCompanyInformationAboutEmployees':
elif fact.concept.qname.localName=='AverageAgeMonthsInformationAboutReportingCompanyInformationAboutEmployees':
elif fact.concept.qname.localName=='NumberOfEmployees':
if fact.contextID == 'CurrentYearInstant_NonConsolidatedMember':
Après cela, les informations de chaque élément acquis (ʻedinet_code,
filer_name_jp, ʻindustry_code
, salaire_info
, service_years
, ʻage_years,
number_of_employees) sont stockées dans
company_info_list. À l'heure actuelle, si les années moyennes de service (mois) (
service_months) et l'âge moyen (mois) (ʻage_months
) existent, nous avons incorporé un processus pour les convertir en années. Après cela, si vous stockez company_info_list
dans l'unité EDINETCODE (unité de fichier d'instance) dans ʻedinet_company_info_list`, une liste contenant les informations des employés de chaque entreprise sera complétée.
Code4
company_info_list.append(edinet_code)
company_info_list.append(filer_name_jp)
company_info_list.append(industry_code)
company_info_list.append(salary_info)
if len(service_months) != 0:
service_years_decimal= round(int(service_months)/12,1)
service_years = int(service_years) + service_years_decimal
service_years = str(service_years)
company_info_list.append(service_years)
if len(age_months) != 0:
age_years_decimal= round(int(age_months)/12,1)
age_years = int(age_years) + age_years_decimal
age_years = str(age_years)
company_info_list.append(age_years)
company_info_list.append(number_of_employees)
edinet_company_info_list.append(Company_info_list)
ʻEdinet_company_info_list` ressemble à ceci:
Result4
[['E00112', 'Totetsu Kogyo Co., Ltd.', 'Industrie de construction', '8547489', '13.8', '41.2', '1673'], ['E01422', 'Fuji Sash Co., Ltd.', 'Produits métalliques', '5527000', '20.7', '44.7', '850'], ['E02770', 'Siège social du groupe Misumi', 'Commerce de gros', '', '', '', '1293'], ['E04510', 'Power Development Co., Ltd.', 'Industrie de l'électricité et du gaz', '7980312', '19.6', '40.9', '2445']・ ・ ・]
Enfin, la ʻedinet_company_info_list` acquise est sortie au format CSV. Ceci termine l'extraction des éléments requis.
Code5
employee_frame = pd.DataFrame(edinet_company_info_list,
columns=['EDINETCODE', 'Nom de la compagnie', 'Industrie', 'Salaire annuel moyen (yen)', 'Années de service moyennes (années)', 'Âge moyen (années)', 'Nombre d'employés (personnes)'])
employee_frame.to_csv("C://Users//xxx//Desktop//xbrlReport//xbrl_qiita.csv", encoding='cp932')
En passant, lorsque vous exécutez le programme, le fichier CSV suivant sera généré à la fin. Il existe plusieurs types d'unités salariales annuelles moyennes (yens, 1 000 yens, etc.) selon la méthode de divulgation de l'entreprise. De plus, bien que nous ciblions les données à partir d'avril 2019, en raison de la fin de l'exercice de chaque entreprise, certaines n'ont pas encore été balisées et les données relatives aux salaires ne peuvent pas être obtenues.
# -*- coding: utf-8 -*-
from arelle import ModelManager
from arelle import Cntlr
import os
import zipfile
import glob
import pandas as pd
def make_edinet_info_list(edinetcodedlinfo_filepath):
edinet_info = pd.read_csv(edinetcodedlinfo_filepath, skiprows=1,
encoding='cp932')
edinet_info = edinet_info[["Code EDINET", "Industrie des soumissionnaires"]]
edinet_info_list = edinet_info.values.tolist()
return edinet_info_list
def unzip_file(zip_dir,xbrl_file_expressions):
zip_files = glob.glob(os.path.join(zip_dir, '*.zip'))
number_of_zip_lists = len(zip_files)
print("number_of_zip_lists:", number_of_zip_lists)
for index, zip_file in enumerate(zip_files):
print(zip_file, ":", index + 1, "/", number_of_zip_lists)
with zipfile.ZipFile(zip_file) as zip_f:
zip_f.extractall(zip_dir)
zip_f.close()
xbrl_files = glob.glob(xbrl_file_expressions)
return xbrl_files
def make_edinet_company_info_list(xbrl_files,edinet_info_list):
edinet_company_info_list = []
for index, xbrl_file in enumerate(xbrl_files):
edinet_code = "" # EDINETCODE
filer_name_jp = "" #Nom de la compagnie
industry_code = "" #Industrie
salary_info = "" #Salaire annuel moyen (yen)
service_years = "" #Années de service moyennes (années)
service_months = "" #Années de service moyennes (mois)
age_years = "" #Âge moyen (années)
age_months = "" #Âge moyen (mois)
number_of_employees = "" #Nombre d'employés (personnes)
company_info_list = [] #Information d'entreprise
ctrl = Cntlr.Cntlr()
model_manager = ModelManager.initialize(ctrl)
model_xbrl = model_manager.load(xbrl_file)
print(xbrl_file, ":", index + 1, "/", len(xbrl_files))
for fact in model_xbrl.facts:
if fact.concept.qname.localName == 'EDINETCodeDEI':
print("Code EDINET", fact.value)
edinet_code = fact.value
for code_name in edinet_info_list:
if code_name[0] == edinet_code:
print("Industrie",code_name[1])
industry_code = code_name[1]
break
elif fact.concept.qname.localName == 'FilerNameInJapaneseDEI':
print("Nom de la compagnie", fact.value)
filer_name_jp = fact.value
elif fact.concept.qname.localName == 'AverageAnnualSalaryInformationAboutReportingCompanyInformationAboutEmployees':
print("Salaire annuel moyen (yen)", fact.value)
salary_info = fact.value
elif fact.concept.qname.localName == 'AverageLengthOfServiceYearsInformationAboutReportingCompanyInformationAboutEmployees':
print("Années de service moyennes (années)", fact.value)
service_years = fact.value
elif fact.concept.qname.localName == 'AverageLengthOfServiceMonthsInformationAboutReportingCompanyInformationAboutEmployees':
print("Années de service moyennes (mois)", fact.value)
service_months = fact.value
elif fact.concept.qname.localName == 'AverageAgeYearsInformationAboutReportingCompanyInformationAboutEmployees':
print("Âge moyen (années)", fact.value)
age_years = fact.value
elif fact.concept.qname.localName == 'AverageAgeMonthsInformationAboutReportingCompanyInformationAboutEmployees':
print("Âge moyen (mois)", fact.value)
age_months = fact.value
elif fact.concept.qname.localName == 'NumberOfEmployees':
if fact.contextID == 'CurrentYearInstant_NonConsolidatedMember':
print("Nombre d'employés (personnes)", fact.value)
number_of_employees = fact.value
print("")
company_info_list.append(edinet_code)
company_info_list.append(filer_name_jp)
company_info_list.append(industry_code)
company_info_list.append(salary_info)
if len(service_months) != 0:
service_years_decimal = round(int(service_months) / 12, 1)
service_years = int(service_years) + service_years_decimal
service_years = str(service_years)
company_info_list.append(service_years)
if len(age_months) != 0:
age_years_decimal = round(int(age_months) / 12, 1)
age_years = int(age_years) + age_years_decimal
age_years = str(age_years)
company_info_list.append(age_years)
company_info_list.append(number_of_employees)
edinet_company_info_list.append(company_info_list)
return edinet_company_info_list
def write_csv_of_employee_info(edinet_company_info_list):
employee_frame = pd.DataFrame(edinet_company_info_list,
columns=['EDINETCODE', 'Nom de la compagnie', 'Industrie', 'Salaire annuel moyen (yen)', 'Années de service moyennes (années)', 'Âge moyen (années)', 'Nombre d'employés (personnes)'])
print(employee_frame)
employee_frame.to_csv("C://Users//xxx//Desktop//xbrlReport//xbrl_qiita.csv", encoding='cp932')
def main():
edinetcodedlinfo_filepath = 'C://Users//xxx//Desktop//xbrlReport//EdinetcodeDlInfo.csv'
edinet_info_list = make_edinet_info_list(edinetcodedlinfo_filepath)
zip_dir = 'C://Users//xxx//Desktop//xbrlReport//SR//'
xbrl_file_expressions = 'C://Users//xxx//Desktop//xbrlReport//SR//XBRL//PublicDoc//*.xbrl'
xbrl_files = unzip_file(zip_dir,xbrl_file_expressions)
edinet_company_info_list = make_edinet_company_info_list(xbrl_files,edinet_info_list)
print(edinet_company_info_list)
write_csv_of_employee_info(edinet_company_info_list)
print("extract finish")
if __name__ == "__main__":
main()
Le nom de l'élément défini dans XBRL
(ex.EDINETCodeDEI) a été décrit sans explication particulière, mais tous sont publiés sur le site EDINET. La dernière version en décembre 2019 est la liste des éléments de la taxonomie
et la liste des comptes de À propos de la publication de la taxonomie EDINET 2020. Vous pouvez vérifier à partir de . Les sujets extraits cette fois sont listés dans la liste des éléments de taxonomie (
1e_ElementList.xlsx`). Pour plus de détails, voir [Ordonnance n ° 3 du Cabinet Office sur les valeurs mobilières, rapport sur la divulgation des détails de l'entreprise, etc. (jpcrp030000-asr)] - [9] Feuille --212000b Statut de l'employé (jpcrp_212000-002_2019-11-01_pre.xml) ), Vérifiez s'il vous plaît. En utilisant ces listes, il est possible d'extraire divers sujets autres que les informations sur les employés. La taxonomie EDINET peut être mise à jour afin de répondre à la révision des lois et des normes comptables. Par conséquent, avant de traiter une instance, assurez-vous que la version de la taxonomie EDINET est correcte.
Pour toute demande concernant cet article, veuillez contacter l'adresse e-mail suivante. e-mail:[email protected] (Bien sûr, les commentaires sur qiita sont également les bienvenus)
Cette adresse e-mail sera le point de contact pour les demandes de renseignements sur le Comité de développement de XBRL Japan, qui rédige l'article sur qiita. Je vais. Par conséquent, nous ne pouvons pas répondre aux demandes générales sur l'organisation en fonction du contenu, mais n'hésitez pas à nous contacter pour toutes questions techniques, opinions, demandes, conseils, etc. concernant XBRL. Veuillez noter que la réponse peut prendre un certain temps car les membres du comité sont des bénévoles.
Recommended Posts