Le titre est long. .. 9uant effectue des analyses quantitatives et de la science des données dans le domaine financier. Nous faisons aussi twitter, donc si vous êtes intéressé, suivez-nous!
Comme le titre l'indique, nous partagerons le code pour télécharger rapidement le XBRL des états financiers. Je voudrais écrire un commentaire un par un. Suivez les deux étapes suivantes.
--DataFrame le lien vers XBRL --Téléchargez le fichier zip XBRL à partir de DataFrame
import os
import glob
import shutil
import re
import time
from datetime import date, timedelta, datetime
from dateutil.relativedelta import relativedelta
import requests
from bs4 import BeautifulSoup
import urllib3
from urllib3.exceptions import InsecureRequestWarning
urllib3.disable_warnings(InsecureRequestWarning)
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
import zipfile
import numpy as np
import pandas as pd
import json
EDINET Facile car EDINET dispose d'une API.
def edinet_xbrl_link(annual=True, quarter=True, codes=None, year=0,month=0,day=0):
'''
Créer un DataFrame pour les liens XBRL pour des sociétés spécifiques ou pour tous les titres et rapports trimestriels
Parameters:
annual: bool, default True
Obtenez un rapport sur les titres si True
quarter: bool, default Ture
Obtenez un rapport trimestriel si True
codes: None, int, float, str, or list (codes[code]=int, float,or str), default None
Obtenez des données pour toutes les entreprises si aucune
Si vous spécifiez un code boursier, seules les données de ces sociétés seront acquises.:point_up_tone4:
year, month, day: int, default 0
Spécifiez combien de jours il y a les données seront récupérées(Jusqu'à 5 ans)
Returns:
database: pandas.DataFrame
database['code']: str
Code de titres à 5 chiffres
database['type']: str
'annual' or 'quarter'
database['date']: datetime.date
date de sortie
database['title']: str
Titre
database['URL']: str
URL pour télécharger le fichier zip XBRL
'''
edinet_url = "https://disclosure.edinet-fsa.go.jp/api/v1/documents.json"
#Unifiez les codes dans un tableau de types de caractères.
if codes != None:
if type(codes) in (str, int, float):
codes = [int(codes)]
for code in codes:
#Convertir le code de titres à 4 chiffres en 5 chiffres
if len(str(int(code)))==4:
code = str(int(code))+'0'
#Tourner l'instruction for avec le type datetime
def date_range(start, stop, step = timedelta(1)):
current = start
while current < stop:
yield current
current += step
#Préparer un DataFrame pour stocker le résultat
database = pd.DataFrame(index=[], columns=['code','type','date','title','URL'])
for d in date_range(date.today()-relativedelta(years=year, months=month, days=day)+relativedelta(days=1), date.today()+relativedelta(days=1)):
#Accéder à l'API EDINET
d_str = d.strftime('%Y-%m-%d')
params = {'date' : d_str, 'type' : 2}
res = requests.get(edinet_url, params=params, verify=False)
json_res = json.loads(res.text)
time.sleep(5)
#Si vous ne pouvez pas accéder normalement
if json_res['metadata']['status']!='200':
print(d_str, 'not accessible')
continue
print(d_str, json_res['metadata']['resultset']['count'])#Afficher la date et le numéro
#En cas de 0
if len(json_res['results'])==0:
continue
df = pd.DataFrame(json_res['results'])[['docID', 'secCode', 'ordinanceCode', 'formCode','docDescription']]
df.dropna(subset=['docID'], inplace=True)
df.dropna(subset=['secCode'], inplace=True)
df.rename(columns={'secCode': 'code', 'docDescription': 'title'}, inplace=True)
df['date'] = d
df['URL'] = df['docID']
df['URL'] = "https://disclosure.edinet-fsa.go.jp/api/v1/documents/" + df['URL']
#Extraire uniquement le code de valeurs spécifié
if codes != None:
df = df[df['code'] in codes]
if annual == True:
df1 = df[(df['ordinanceCode']=='010') & (df['formCode']=='030000')]
df1['type'] = 'annual'
database = pd.concat([database, df1[['code', 'type', 'date','title', 'URL']]], axis=0, join='outer').reset_index(drop=True)
if quarter == True:
df2 = df[(df['ordinanceCode']=='010') & (df['formCode']=='043000')]
df2['type'] = 'quarter'
database = pd.concat([database, df2[['code', 'type', 'date','title', 'URL']]], axis=0, join='outer').reset_index(drop=True)
return database
TDNET Utilisez «sélénium» pour collecter les données de TDNET. Étant donné que seuls 200 résultats de recherche de mots gratuits sont affichés, nous avons créé une fonction de recherche par code de valeur et une fonction de recherche par date séparément.
def tdnet_xbrl_link_by_code(codes):
'''
Créez un DataFrame qui lie les états financiers de la société spécifiée à XBRL
Parameters:
codes: None, int, float, str, or list (codes[code]=int, float,or str), default None
Obtenez des données pour toutes les entreprises si aucune
Returns:
database: pandas.DataFrame
database['code']: str
Code de titres à 5 chiffres
database['type']: str
'annual' or 'quarter'
database['date']: datetime.date
date de sortie
database['title']: str
Titre
database['URL']: str
URL pour télécharger le fichier zip XBRL
'''
#Unifiez les codes dans un tableau de types de caractères.
if type(codes) in (str, int, float):
codes = [int(codes)]
for i, code in enumerate(codes):
#Convertir le code de titres à 4 chiffres en 5 chiffres
if len(str(int(code)))==4:
codes[i] = str(int(code))+'0'
database = pd.DataFrame(index=[], columns=['code','type','date','title','URL'])
for code in codes:
#Lancez le navigateur
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('--headless') #Masquer le navigateur
driver = webdriver.Chrome(options=chromeOptions)
driver.get("https://www.release.tdnet.info/onsf/TDJFSearch/I_head")
#Envoyer le mot de recherche
duration = driver.find_element_by_name('t0')
select = Select(duration)
select.options[-1].click()
inputElement = driver.find_element_by_id("freewordtxt")
inputElement.send_keys(code)
inputElement.send_keys(Keys.RETURN)
time.sleep(5)
#Déplacer vers le cadre où les résultats de la recherche sont affichés
iframe = driver.find_element_by_name("mainlist")
driver.switch_to.frame(iframe)
#Termine le traitement lorsqu'il n'y a aucun résultat de recherche
if driver.find_element_by_id("contentwrapper").text == 'Les informations pertinentes de divulgation en temps opportun n'ont pas été trouvées.':
return database
#Lire les données de chaque ligne dans le tableau des résultats de recherche
table = driver.find_element_by_id("maintable")
trs = table.find_elements(By.TAG_NAME, "tr")
for i in range(len(trs)):
title = trs[i].find_elements(By.TAG_NAME, "td")[3].text
#Sélectionnez les états financiers de la société spécifiée où XBRL existe, pas les documents de correction
if ('États financiers' in title) and ('correction' not in title) and (len(trs[i].find_elements(By.TAG_NAME, "td")[4].text)!=0) and (code==trs[i].find_elements(By.TAG_NAME, "td")[1].text):
date = trs[i].find_elements(By.TAG_NAME, "td")[0].text[:10]
date = datetime.strptime(date, '%Y/%m/%d').date()
url = trs[i].find_elements(By.TAG_NAME, "td")[4].find_element_by_tag_name("a").get_attribute("href")
database = database.append(pd.Series([code,'brief',date,title,url], index=database.columns), ignore_index=True)
driver.quit()
return database
def tdnet_xbrl_link_by_date(date=None):
'''
Créer un DataFrame liant la date spécifiée ou tous les états financiers à XBRL
Parameters:
date: None or str ('yyyy/mm/dd'), default None
Obtenir des données pour toutes les dates si aucune
Returns:
database: pandas.DataFrame
database['code']: str
Code de titres à 5 chiffres
database['type']: str
'annual' or 'quarter'
database['date']: datetime.date
date de sortie
database['title']: str
Titre
database['URL']: str
URL pour télécharger le fichier zip XBRL
'''
database = pd.DataFrame(index=[], columns=['code','type','date','title','URL'])
#Lancez le navigateur
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('--headless') #Masquer le navigateur
driver = webdriver.Chrome(options=chromeOptions)
driver.get("https://www.release.tdnet.info/inbs/I_main_00.html")
duration = driver.find_element_by_name('daylist')
select = Select(duration)
for i in range(1, len(select.options)):
driver.get("https://www.release.tdnet.info/inbs/I_main_00.html")
duration = driver.find_element_by_name('daylist')
select = Select(duration)
d = datetime.strptime(select.options[i].text[:10], '%Y/%m/%d').date()
print(select.options[i].text)
if (date == None) or (date == select.options[i].text[:10]):
select.options[i].click()
time.sleep(5)
#Déplacer vers le cadre où les résultats de la recherche sont affichés
iframe = driver.find_element_by_id("main_list")
driver.switch_to.frame(iframe)
#Termine le traitement lorsqu'il n'y a aucun résultat de recherche
if driver.find_element_by_id("kaiji-text-1").text!='Informations divulguées dans':
continue
#Continuer le traitement jusqu'à la dernière page
while True:
#Lire les données de chaque ligne dans le tableau des résultats de recherche
table = driver.find_element_by_id("main-list-table")
trs = table.find_elements(By.TAG_NAME, "tr")
for i in range(len(trs)):
title = trs[i].find_elements(By.TAG_NAME, "td")[3].text
#Sélectionnez les états financiers de la société spécifiée où XBRL existe, pas les documents de correction
if ('États financiers' in title) and ('correction' not in title) and (len(trs[i].find_elements(By.TAG_NAME, "td")[4].text)!=0):
code = trs[i].find_elements(By.TAG_NAME, "td")[1].text
url = trs[i].find_elements(By.TAG_NAME, "td")[4].find_element_by_tag_name("a").get_attribute("href")
database = database.append(pd.Series([code, 'brief', d, title,url], index=database.columns), ignore_index=True)
if len(driver.find_element_by_class_name("pager-R").text)!=0:
driver.find_element_by_class_name("pager-R").click()
time.sleep(5)
else:
#Termine le traitement si le mot "Suivant" n'existe pas
break
driver.quit()
return database
def dl_xbrl_zip(codes=None, database):
'''
Téléchargez le fichier zip XBRL en vous référant au DataFrame qui répertorie les liens vers le XBRL.
Parameters:
codes: None, int, float, str, or list (codes[code]=int, float,or str), default None
Obtenez XBRL pour toutes les entreprises si aucune
database: pandas.DataFrame
database['code']: str
Code de titres à 5 chiffres
database['type']: str
'annual' or 'quarter'
database['date']: datetime.date
date de sortie
database['title']: str
Titre
database['URL']: str
URL pour télécharger le fichier zip XBRL
Returns:
None
'''
database.dropna(subset=['code'], inplace=True)
database = database.reset_index(drop=True)
#Unifier les codes dans un tableau de caractères
if codes == None:
codes = [None]
else:
if type(codes) in (str, int, float):
codes = [int(codes)]
for i, code in enumerate(codes):
#Convertir le code de titres à 4 chiffres en 5 chiffres
if len(str(int(code)))==4:
codes[i] = str(int(code))+'0'
for code in codes:
if code == None:
df_company = database
else:
df_company = database[database['code']==code]
df_company = df_company.reset_index(drop=True)
#Utilisez le code de sécurité comme nom de répertoire
dir_path = database.loc[i,'code']
if os.path.exists(dir_path)==False:
os.mkdir(dir_path)
#Téléchargez le fichier zip de chaque ligne de la liste extraite du lien vers XBRL
for i in range(df_company.shape[0]):
#Lors de l'accès à EDINET
if (df_company.loc[i,'type'] == 'annual') or (df_company.loc[i,'type'] == 'quarter'):
params = {"type": 1}
res = requests.get(df_company.loc[i,'URL'], params=params, stream=True)
if df_company.loc[i,'type'] == 'annual':
#Le nom de fichier du rapport titres est"yyyy_0.zip"
filename = dir_path + r'/' + df_company.loc[i,'date'][:4] + r"_0.zip"
elif df_company.loc[i,'type'] == 'quarter':
if re.search('Période', df_company.loc[i,'title']) == None:
#Le nom de fichier du rapport trimestriel de période inconnue est"yyyy_unknown_docID.zip"
filename = dir_path + r'/' + df_company.loc[i,'date'][:4] + r'_unknown_' + df_company.loc[i,'URL'][-8:] + r'.zip'
else:
#Le nom de fichier du rapport trimestriel est"yyyy_quarter.zip"
filename = dir_path + r'/' + df_company.loc[i,'date'][:4] + r'_' + df_company.loc[i,'title'][re.search('Période', df_company.loc[i,'title']).end()] + r'.zip'
#Lors de l'accès à TDNET
elif df_company.loc[i,'type'] == 'brief':
res = requests.get(df_company.loc[i,'URL'], stream=True)
#Remplissez les caractères vides
s_list = df_company.loc[i,'title'].split()
s = ''
for i in s_list:
s += i
filename = df_company.loc[i,'date'][:4] + r'_' + s[re.search('Période', s).end()] + r'_brief.zip'
#Si un fichier zip du même nom existe, il ne sera pas écrasé.
if os.path.exists(filename):
print(df_company.loc[i,'code'],df_company.loc[i,'date'],'already exists')
continue
#Téléchargez le fichier zip uniquement si vous pouvez y accéder normalement
if res.status_code == 200:
with open(filename, 'wb') as file:
for chunk in res.iter_content(chunk_size=1024):
file.write(chunk)
print(df_company.loc[i,'code'],df_company.loc[i,'date'],'saved')
print('done!')
return None
Recommended Posts