Python
 Computer >> コンピューター >  >> プログラミング >> Python

PythonのlxmlでWebスクレイピングを実装する方法|Yahoo Financeから株価データを抽出

Webスクレイピングは、データサイエンス愛好家だけでなく、Webサイトの仕組みを深く掘り下げたい学生や学習者にとっても非常に魅力的な技術です。Pythonには強力なスクレイピングライブラリが数多く用意されています。

  • Scrapy

  • Urllib

  • BeautifulSoup

  • Selenium

  • Requests

  • lxml

本記事では、その中でもlxmlライブラリを使ってWebページからデータを抽出する方法を解説します。lxmlはC言語製のXML解析ライブラリ「libxml2」をベースに構築されており、Beautiful Soupよりも高速に動作するのが大きな魅力です。一方で、特にWindows環境ではインストールにつまずくケースもあるため、導入手順から丁寧に見ていきましょう。

lxmlのインストールとインポート

lxmlはコマンドラインからpipで簡単にインストールできます。

pip install lxml

Anaconda環境をお使いの場合は、次のコマンドでもOKです。

conda install -c anaconda lxml

インストールが完了したら、HTMLを解析するためのhtmlモジュールをインポートします。

>>> from lxml import html

続いて、スクレイピング対象ページのソースコードを取得します。requestsライブラリまたはurllibを使ってHTMLをダウンロードし、その内容を含むlxmlのHTML要素オブジェクトを作成します。ここではrequestsを使用しましょう。まだインストールしていない場合は、ターミナルで次のコマンドを実行してください。

$ pipenv install requests

Yahoo Financeから株価データをスクレイピングしてみよう

今回は実践例として、Yahoo Financeから株式・銘柄データを抽出します。下の画像はYahoo Financeに表示されたマイクロソフト社(MSFT)のページです。

PythonのlxmlでWebスクレイピングを実装する方法|Yahoo Financeから株価データを抽出

このページ(https://finance.yahoo.com/quote/msft)から、画面に表示されている以下のような項目をすべて抽出していきます。

  • 前日終値(Previous Close)、始値(Open)、買値(Bid)、売値(Ask)

  • 当日レンジ、52週レンジ

  • 出来高(Volume)など

これを実現するPython + lxmlのコードがこちらです。

lxml_scrape3.py

from lxml import html
import requests
import json
import argparse
from collections import OrderedDict
from time import sleep

def parse(ticker):
    url = "https://finance.yahoo.com/quote/%s?p=%s" % (ticker, ticker)
    response = requests.get(url, verify=False)
    print("Parsing %s" % url)
    sleep(4)
    parser = html.fromstring(response.text)
    summary_table = parser.xpath('//div[contains(@data-test,"summary-table")]//tr')
    summary_data = OrderedDict()

    other_details_json_link = ("https://query2.finance.yahoo.com/v10/finance/"
                               "quoteSummary/{0}?formatted=true&lang=en-US"
                               "&region=US&modules=summaryProfile%2CfinancialData"
                               "%2CrecommendationTrend%2CupgradeDowngradeHistory"
                               "%2Cearnings%2CdefaultKeyStatistics%2CcalendarEvents"
                               "&corsDomain=finance.yahoo.com").format(ticker)
    summary_json_response = requests.get(other_details_json_link)
    try:
        json_loaded_summary = json.loads(summary_json_response.text)
        y_Target_Est = json_loaded_summary["quoteSummary"]["result"][0]["financialData"]["targetMeanPrice"]['raw']
        earnings_list = json_loaded_summary["quoteSummary"]["result"][0]["calendarEvents"]['earnings']
        eps = json_loaded_summary["quoteSummary"]["result"][0]["defaultKeyStatistics"]["trailingEps"]['raw']

        datelist = []
        for i in earnings_list['earningsDate']:
            datelist.append(i['fmt'])
        earnings_date = ' to '.join(datelist)

        for table_data in summary_table:
            raw_table_key = table_data.xpath('.//td[contains(@class,"C(black)")]//text()')
            raw_table_value = table_data.xpath('.//td[contains(@class,"Ta(end)")]//text()')
            table_key = ''.join(raw_table_key).strip()
            table_value = ''.join(raw_table_value).strip()
            summary_data.update({table_key: table_value})

        summary_data.update({'1y Target Est': y_Target_Est,
                             'EPS (TTM)': eps,
                             'Earnings Date': earnings_date,
                             'ticker': ticker,
                             'url': url})
        return summary_data
    except:
        print("Failed to parse json response")
        return {"error": "Failed to parse json response"}

if __name__ == "__main__":
    argparser = argparse.ArgumentParser()
    argparser.add_argument('ticker', help='')
    args = argparser.parse_args()
    ticker = args.ticker
    print("Fetching data for %s" % ticker)
    scraped_data = parse(ticker)
    print("Writing data to output file")
    with open('%s-summary.json' % ticker, 'w') as fp:
        json.dump(scraped_data, fp, indent=4)

このコードのポイントは、XPathを使ってHTML内のテーブル行(summary-table配下のtr要素)を特定し、キーと値をペアで抽出しているところです。さらにYahoo Financeが公開しているJSON APIにも同時にアクセスすることで、目標株価やEPS、決算発表日などの追加情報も取得しています。

スクリプトの実行方法

コードを保存したら、コマンドターミナルで以下のようにティッカーシンボルを引数に指定して実行します。

c:\Python\Python361>python lxml_scrape3.py MSFT

実行すると、カレントディレクトリに「銘柄名-summary.json」という形式のJSONファイルが自動的に作成されます。今回はMSFT(マイクロソフト)を指定しているので、「msft-summary.json」というファイルが生成されます。

以下は実際に出力されたJSONファイルの内容です。

PythonのlxmlでWebスクレイピングを実装する方法|Yahoo Financeから株価データを抽出

まとめ

このように、lxmlとrequestsを組み合わせることで、Yahoo Financeからマイクロソフトの株価に関するあらゆるデータを効率よく抽出し、JSONファイルとして保存できました。保存したデータはそのまま共有できるほか、時系列で蓄積すれば株価の推移分析などにも活用できます。

なお、WebサイトのHTML構造は予告なく変更されることがあります。XPathセレクタが機能しなくなった場合は、対象ページの最新のDOM構造を確認して修正してください。また、サンプルコード中のverify=FalseはSSL証明書の検証を無効化するオプションなので、本番環境では使用しないよう注意しましょう。

  1. PythonでのCX_Freezeの使い方:スクリプトを実行ファイル(EXE)に変換する方法

    はじめに 何か面白いものを作りたいという欲求は人間の本能であり、完成したものは誰かに共有したくなるものです。Pythonでもその願いを叶えられます。ただし、作成したPythonスクリプトをそのまま共有するには、相手のマシンにも同じバージョンのPythonと、プログラムで使用しているすべてのモジュールがインストールされている必要があります。 そこで役立つのがCX_Freezeです。このツールを使えば、Pythonがインストールされていない環境でも動作するスタンドアロンの実行ファイル(.exe)を作成できます。 CX_Freezeのインストール まず、コマンドプロンプトで以下のコマンドを実行し、c

  2. PythonでWebスクレイピング!主要ライブラリ6選の特徴と使い方を徹底解説

    Webスクレイピングとは コンピュータサイエンスにおけるWebスクレイピング(Web Scraping)とは、Webサイトからデータを抽出する技術のことです。この手法を活用することで、Web上に散在する非構造化データを、分析や加工がしやすい構造化データへと変換できます。 Python 3でよく使われる代表的なスクレイピングツールは以下の6つです。 Urllib(urllib.request) Requests BeautifulSoup Lxml Selenium MechanicalSoup 1. Urllib(urllib.request) UrllibはPythonに標準で組み込ま