Python 株ランキングを例に、html解析によってデータを抽出してcsvへ保存する「BeautifulSoup」

 本記事では、html解析により、web上のデータを抜き出し、csvへ書き出す雛形コードを載せました。下図は、日経HPの株の売買ランキングを抽出した場合の例です。証券コードと銘柄名を抽出してcsvへ出力します。

f:id:HK29:20220226225713p:plain

ライブラリのインストールは次の通りです。

pip install beautifulsoup4

■日経HPの売買高ランキングのhtml解析の場合の例('22/02/26時点)

import requests
from bs4 import BeautifulSoup
import pandas as pd
import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d")

# 保存するファイル名
save_file_name = '売買高ランキング'

# URLをリストで指定
load_url_list = [
'https://www.nikkei.com/markets/ranking/page/?bd=vol&ba=11&Gcode=&excflag=1&hm=1', # 売買高ランキング 1位~50位
'https://www.nikkei.com/markets/ranking/page/?bd=vol&ba=11&Gcode=&excflag=1&hm=2', # 売買高ランキング 51位~100位
]

# html解析をして、証券コードと銘柄名をリストで取得する
ticker_symbol_list = []
stock_name_list = []
for load_url in load_url_list:
    print(load_url)
    html = requests.get(load_url)
    soup = BeautifulSoup(html.content, "html.parser")

    # htmlのclass属性のleftを指定して検索する。
    # この時、classはPythonの予約語と被るため、class_ とする
    for i, element in enumerate(soup.find_all(class_="left"), start=1):
        # 例えば、下記のようにclass="left"の行を抽出します
        # <td class="left"><a href="/nkd/company/?scode=8306&amp;ba=1" title="三菱UFJフィナンシャル・グループの株価情報">三菱UFJ</a></td>
        # さらに、ドット演算子によるタグの参照を利用して、下記のようにa href=を抽出します。
        # /nkd/company/?scode=8306&ba=1
        my_str = element.a.get('href')
        my_stock_name = element.text
        print(i, my_str, my_stock_name)
        
        # 証券コードを抽出
        my_left_index = my_str.find('=')
        my_right_index = my_str.rfind('&')
        my_ticker_symbol = my_str[my_left_index + 1: my_right_index]

        # 証券コードと銘柄名をそれぞれのリストへ格納
        ticker_symbol_list.append(my_ticker_symbol)
        stock_name_list.append(my_stock_name)

# 2つのリストから辞書を作成
stock_dict = dict(zip(ticker_symbol_list, stock_name_list))
print(stock_dict)

# pandasデータフレーム形式へ
df = pd.DataFrame(list(stock_dict.items()),
                  columns = ['証券コード', '銘柄名'],
                 ) 
print(df)

# csvへ保存
df.to_csv(now + '_' + save_file_name + '.csv',
          index = False,          
          encoding = 'utf_8_sig', # エクセルで文字化けしないcsvを出力)
         )
print('finished')

■日経HPの適時開示ランキングのhtml解析の場合の例('22/02/26時点)
 上記の売買高ランキングとはhtmlの記述が微妙に異なることがわかった。そのため、抽出の方法も異なる。ここでは、if文やtry文を使用している。もちろんこの雛形コードは一例であり、さらに可読性が良い、あるいは効率的な書き方はありえます。

import requests
from bs4 import BeautifulSoup
import pandas as pd
import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d")

# 保存するファイル名
save_file_name = '適時開示ランキング'

# URLをリストで指定
load_url_list = [
'https://www.nikkei.com/markets/ranking/page/?bd=disclose&hm=1', # 適時開示ランキング 1位~50位
'https://www.nikkei.com/markets/ranking/page/?bd=disclose&hm=2', # 適時開示ランキング 51位~100位
#'https://www.nikkei.com/markets/ranking/page/?bd=disclose_w&hm=1' # 適時開示(週間)ランキング 1位~50位
#'https://www.nikkei.com/markets/ranking/page/?bd=disclose_w&hm=2' # 適時開示(週間)ランキング 51位~100位
]

# html解析をして、証券コードと銘柄名をリストで取得する
ticker_symbol_list = []
stock_name_list = []
j = 0
for load_url in load_url_list:
    print(load_url)
    html = requests.get(load_url)
    soup = BeautifulSoup(html.content, "html.parser")

    for i, element in enumerate(soup.find_all('a'), start=1):
        my_str = element.get('href')
        my_stock_symbol_or_name = element.text
        if '/nkd/company/?scode=' in my_str:
            # 下記2つのいずれかの場合に処理する
            # <a href="/nkd/company/?scode=3772">3772</a></td>
            # <a href="/nkd/company/?scode=3772">ウェルス</a></td>
            
            # 数字(文字列)の場合、整数型へ変換する
            try:
                my_stock_symbol_or_name = int(my_stock_symbol_or_name)
            except:
                pass
            
            # 証券コードと銘柄名をそれぞれのリストへ格納
            if isinstance(my_stock_symbol_or_name, int):
                ticker_symbol_list.append(my_stock_symbol_or_name)
            else:
                stock_name_list.append(my_stock_symbol_or_name)
                j = j + 1
                print(j, my_str, my_stock_symbol_or_name)
                
# 2つのリストから辞書を作成
# 辞書型にすることで、重複を避けることができる
stock_dict = dict(zip(ticker_symbol_list, stock_name_list))
print(stock_dict)

# pandasデータフレーム形式へ
df = pd.DataFrame(list(stock_dict.items()),
                  columns = ['証券コード', '銘柄名'],
                 ) 
print(df)

# csvへ保存
df.to_csv(now + '_' + save_file_name + '.csv',
          index = False,          
          encoding = 'utf_8_sig', # エクセルで文字化けしないcsvを出力)
         )
print('finished')

以上

<広告>