ネットワーク製造業-企業別データ検索(Yahoo Financial scraping)

11742 ワード

前回のリリースでは70000以上のCompany Ticker Symbolを見つけましたが、各Company Tickerにエンタープライズ詳細ページが表示されるようにデータを収集します.
最初はsec open apiを導入しようと思っていましたが、欲しいデータが見つからず、少し迷いました.yahoo financeはすでに多くのデータが私の欲しい形で表示されていました.SEC filing URLもjsonデータの形で提供され、難易度が下がりましたか?西ヤフー金融を放棄することにした.
これはyahoo financeのAAPLメイン画面です.

この画面で、「ページソースの表示」を右クリックすると、大量のブラブラが書いたものが表示されます.(抜粋部の例)

ここに書いてあるように,このページを含む複数のJavaScript関数から動的にデータがロードされる.
データ内はjavascript関数にあるため、以下の順序で行います.
  • scriptのtagを確認します.
  • script内のコンテンツを抽出します.
  • contentsをjson形式の文字列に変更し、Python dictionaryに変換します.
  • 1.で説明したようにscriptのtagをインポートする必要がありますが、tagには特別な点はありませんので、正規表現を使用します.
    次に、正規表現に一致するテキストが存在するscript要素を検索します.
    このスクリプトは私たちが望むデータの周りにあるので、欲しいデータだけを取得するためにcontextの始まりから、2番目の文字から終わりまで、12番目の文字から始まります.
    (実は私は今自分が何を説明しているのか分かりません.
    全く理解していない状態で、次のYouTubeを参考にして、必要な方は行ってみてください.https://www.youtube.com/watch?v=fw4gK-leExw )
    これにより、次のコードが作成されます.
    import re
    import json
    from bs4 import BeautifulSoup
    import requests
    
    response = requests.get(url_financials.format(stock, stock))
    
    soup = BeautifulSoup(response.text, 'html.parser')
    
    pattern = re.compile(r'\s--\sData\s--\s')
    script_data = soup.find('script', text=pattern).contents[0]
            
    script_data[:500]
    
    script_data[-500:]
    
    start = script_data.find("context") - 2
    json_data = json.loads(script_data[start:-12])
    上の基本コードから、おなじみのJSON形式のデータが出てきますが、ここから、勝手にデータをインポートできます.
    インポートするデータは6つに分かれています.
  • financials
  • profile
  • holders
  • SEC filings
  • price summary
  • ESG
  • 1. financials
    当該企業の2020、2019、2018、2017年の損益計算書、財務状態計算書、キャッシュフロー計算書のデータを取得する.
    json内の0番目のcontentsは2020年で、1、2、3の順で年が逆行します.
    annual_is = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['incomeStatementHistory'][
                'incomeStatementHistory']
    total_revenue_0 = annual_is[0]['totalRevenue']['raw']
    cost_revenue_0 = annual_is[0]['costOfRevenue']['raw']
    gross_profit_0 = annual_is[0]['grossProfit']['raw']
    operating_expense_0 = annual_is[0]['totalOperatingExpenses']['raw']
    operating_income_0 = annual_is[0]['operatingIncome']['raw']
    pretax_income_0 = annual_is[0]['incomeBeforeTax']['raw']
    net_income_0 = annual_is[0]['netIncome']['raw']  
    
    annual_bs = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['balanceSheetHistory'][
                'balanceSheetStatements']
    total_asset_0 = annual_bs[0]['totalAssets']['raw']
    current_asset_0 = annual_bs[0]['totalCurrentAssets']['raw']
    noncurrent_asset_0 = int(annual_bs[0]['totalAssets']['raw']) - int(
    annual_bs[0]['totalCurrentAssets']['raw'])
    total_liab_0 = annual_bs[0]['totalLiab']['raw']
    current_liab_0 = annual_bs[0]['totalCurrentLiabilities']['raw']
    noncurrent_liab_0 = int(annual_bs[0]['totalLiab']['raw']) - int(annual_bs[0]['totalCurrentLiabilities']['raw'])
    total_equity_0 = annual_bs[0]['totalStockholderEquity']['raw']
    
    annual_cf = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['cashflowStatementHistory'][
                'cashflowStatements']
    operating_cashflow_0 = annual_cf[0]['totalCashFromOperatingActivities']['raw']
    investing_cashflow_0 = annual_cf[0]['totalCashflowsFromInvestingActivities']['raw']
    financing_cashflow_0 = annual_cf[0]['totalCashFromFinancingActivities']['raw']
    changes_cash_0 = int(operating_cashflow_0) + int(investing_cashflow_0) + int(financing_cashflow_0)
    capital_expenditure_0 = annual_cf[0]['capitalExpenditures']['raw']
    issuance_stock_0 = annual_cf[0]['issuanceOfStock']['raw']
    2. profile
    これにより、企業名、住所、産業、取締役、ウェブサイトなどの基本情報と多くのリスク指標がもたらされます.
    引っ越しは一番大切な二人ぐらいしか持ってこない.
    # 1. Company Information
    profile = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['assetProfile']
    
    summary = profile['longBusinessSummary']
    sector = profile['sector']
    industry = profile['industry']
    employees = profile['fullTimeEmployees']
    address = profile['address1']
    city = profile['city']
    state = profile['state']
    country = profile['country']
    phone = profile['phone']
    website = profile['website']
    
    # 2. Officers
    
    officer1_name = profile[0]['name']
    officer1_title = profile[0]['title']
    officer1_yearborn = profile[0]['yearBorn']
    officer1_pay = profile[0]['totalPay']
    
    officer2_name = profile[1]['name']
    officer2_title = profile[1]['title']
    officer2_yearborn = profile[1]['yearBorn']
    officer2_pay = profile[1]['totalPay']
    
    # 2. Risk
    
    overall_risk = profile['overallRisk']
    audit_risk = profile['auditRisk']
    compensation_risk = profile['compensationRisk']
    shareholder_risk = profile['shareHolderRightsRisk']
    board_risk = profile['boardRisk']
    3. holders
    企業の株主の現状をもたらす.企業の内部株主、外部機関株主の割合と外部機関株主の数から、主要機関投資家は3位、主要ファンド投資家は3位が誰ですか.
    # 1. Major Holders
    holders = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['majorHoldersBreakdown']
    
    insider_holders = holders['insidersPercentHeld']['fmt']
    institutional_holders = holders['institutionsPercentHeld']['fmt']
    institutional_float = holders['institutionsFloatPercentHeld']['fmt']
    institutional_count = holders['institutionsCount']['raw']
    
    # 2. institutionOwnership
    ownerlist = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['institutionOwnership']['ownershipList']
    ownerlist_organ_0 = ownerlist[0]['organization']
    ownerlist_pctheld_0 = ownerlist[0]['pctHeld']['fmt']
    ownerlist_position_0 = ownerlist[0]['position']['fmt']
    ownerlist_value_0 = ownerlist[0]['value']['fmt']
    
    # 3. fundownership
    fundlist = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['fundOwnership']['ownershipList']
    fundlist_organ_0 = fundlist[0]['organization']
    fundlist_pctheld_0 = fundlist[0]['pctHeld']['fmt']
    fundlist_position_0 = fundlist[0]['position']['fmt']
    fundlist_value_0 = fundlist[0]['value']['fmt']
    4. SEC filings
    最近のEDGARの主なSEGファイルは5つのtitle,data,urlがあります.
    for i in range(5):
    date = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['secFilings']['filings'][i]['date']
    title = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['secFilings']['filings'][i]['title']
    edgarurl = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['secFilings']['filings'][i]['edgarUrl']
    filings = date, title, edgarurl
    5. price summary
    株価情報:最近の取引終値、200営業日平均、営業日最高、営業日最低価格、それに関連する配当率、beta、PE比率、時価総額、取引量を取得します.
    summary = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['summaryDetail']
    price_previouseclose = summary['previousClose']['raw']
    price_200dayaverage = summary['twoHundredDayAverage']['raw']
    price_marketdaylow = summary['regularMarketDayLow']['raw']
    price_marketdayhigh = summary['regularMarketDayHigh']['raw']
    summary_divdend = summary['dividendRate']['raw']
    summary_beta = summary['beta']['raw']
    summary_pe = summary['trailingPE']['fmt']
    summary_marketcap = summary['marketCap']['fmt']
    summary_volume = summary['averageVolume']['fmt']
    6.ESG
    企業をもたらすTotal ESG Scoreと部門(環境、社会、ガバナンス構造)Score.
    esg = json_data['context']['dispatcher']['stores']['QuoteSummaryStore']['esgScores']
    esg_total = esg['totalEsg']['fmt']
    esg_environment = esg['environmentScore']['fmt']
    esg_social = esg['socialScore']['fmt']
    esg_governance = esg['governanceScore']['fmt']
    そこで,データを抽出できる基本コードについて理解した.
    コードを見ればわかりますが、構造はかなり簡単で重複しています.
    多くのデータドメインが生成される可能性があります.
    company ticker星のプロパティデータを抽出する方法が見つかりました.前回のレッスンで持ってきたcompany tickerデータをクリップします.
    私のデータベースの会社手形に関する情報を取得するために、for文を書いてdbに会社手形を読み込ませました.
    from pymongo import MongoClient
    
    client = MongoClient('localhost', 27017)
    db = client.company
    companies = list(db.company.find({}, {'_id': False}))
    
    for company in companies:
        stock = company['company_ticker']
        url_profile = 'https://finance.yahoo.com/quote/{}/profile?p={}'
        url_financials = 'https://finance.yahoo.com/quote/{}/financials?p={}'
        url_holder = 'https://finance.yahoo.com/quote/{}/holders?p={}'
        url_summary = 'https://finance.yahoo.com/quote/{}?p={}'
        url_esg = 'https://finance.yahoo.com/quote/{}/sustainability?p={}'
        
    company tickerを読み込んでデータを出力します.
    出力されたデータは、再一致した会社手形レコード行にフィールドを生成することによってデータを追加します.
    このため、update文を使用してデータを追加します.(次の例ではpricesummaryプロパティのデータを表示します)
    db.company.update_one({'company_ticker': stock}, {'$set': {
            'price_previouseclose': price_previouseclose,
            'price_200dayaverage': price_200dayaverage,
            'price_marketdaylow': price_marketdaylow,
            'price_marketdayhigh': price_marketdayhigh,
            'summary_divdend': summary_divdend,
            'summary_beta': summary_beta,
            'summary_pe': summary_pe,
            'summary_marketcap': summary_marketcap,
            'summary_volume': summary_volume
        }})
    このように振り返ってみると、企業によってはKeyError、TypeError、IndexError、Attribute Errorが発生する可能性があります.しかし、なぜこれが起こったのかを知る前に、受信できるデータを全部受け取ったほうがいいと思います.try/除外/継続文が使用されています.そのため、データベースを表示すると、真ん中に空のデータが表示されます.
        try:
           
        except TypeError:
            continue
        except KeyError:
            continue
        except IndexError:
            continue
        except AttributeError:
            continue
    
        db.company.update_one({'company_ticker': stock}, {'$set': {
        }})
    
    現在、すべての財務データを受け取ったデータベースは次のとおりです.
    见ると空く行が多い.ううう
    空いている歩行者企業を検索してみると、金融系企業は1年か1年しかないのですが、特定の口座データがない場合は部分的に受け取れば良いのですが、いっそ全部空いてしまうのはもったいないです.

    holdingsは次のように格納されます.
    保有量も金融類とは思えませんが、空いているところもあります.
    △しかし、現在2000件ほどのデータを受け取っています.ほとんどの企業の第一機関投資家はBlackrockではなく、Vanguardグループで、不思議に思っています.