Téléchargez le rapport XBRL de titres, rapport trimestriel, rapport financier d'EDINET / TDNET avec Python

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

Convertir le lien en XBRL en DataFrame

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

Télécharger XBRL depuis DataFrame

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

Téléchargez le rapport XBRL de titres, rapport trimestriel, rapport financier d'EDINET / TDNET avec Python
Télécharger le fichier XBRL depuis EDINET (mémo personnel)
Télécharger en masse des images à partir d'une URL spécifique avec python
Télécharger en masse des images à partir d'une URL de site spécifique avec python
Apprenez Nim avec Python (dès le début de l'année).
Téléchargez facilement et partiellement mp4 avec python et youtube-dl!
[Bases de la science des données] Collecte de données depuis RSS avec python
Extraire le modèle du fichier EML enregistré depuis Thunderbird avec python3.7
Avec skype, notifiez avec skype de python!
Télécharger le fichier csv avec python
Essai de la reconnaissance vocale à l'aide d'Azure avec Python (entrée depuis le microphone)
Téléchargement par lots d'images à partir d'une URL spécifique avec la version modifiée de python
De l'introduction de JUMAN ++ à l'analyse morphologique du japonais avec Python