表示中のサイトの表やテキストを保存する 【Python & selenium】

Python

ネット上の任意のページを表示させたとき、そのページにある表やテキストを簡単に保存できるようにするスクリプトについてまとめ、公開しておきます。
よく使うサイトの URL を設定ファイルで指定しておくと、手動で好きなページに遷移して、表示させた表やテキストを簡単に保存できるようにしてみます。

以下の環境で動作確認をしています。
環境: Windows パソコン、Python 3 (selenium、Beautiful Soup の設定済み)

背景 任意のサイトの表を保存したい!

ウェブサイトを見ていると、表やテキストをかんたんなコマンドで保存したくなることがあります。
欲しい表は表示されているのだけれども、サイトにダウンロードボタンがない。指定した表をかんたんに保存したい、表がダウンロードできないならテキスト全文でもよいので保存したい、などといった場合です。

また、飲食店や株主優待のポイントサービスなどのサイトで、セキュリティの観点からパスワードの入力は手動で行いたいけれども、ログイン後に表示された表やテキストについて、かんたんに保存したくなることがあります。

そこで、よく使うサイトのトップ画面などの URL を保存しておくと、画面遷移や画面操作を手動で行っても、表示させた任意のデータを簡単に保存できるスクリプトを作成してみることにします。

たとえば、使っているポイントサービスが複数あったとき、各サイトのポイントの残高や期限をダウンロードしておくことが可能になります。
使っているポイントサービスが増えてくると、ポイントの残額や期限を確認してもすぐに忘れてしまいます。期限を確認するだけのために、何回もログインしていた、といった煩雑さを改善できるようになります。
具体的には、トリドールホールディングス(丸亀製麺)、コメダ珈琲などの株主優待のポイントサイトについて、手動でのログイン後、コマンドの実行により、ポイントの期限や履歴の表などをダウンロードできることを確認しています。
データのダウンロードさえできれば、Python のスクリプトなどを追加していくことで、各ポイントの期限や残高を一括管理していくことなどが可能になります。

設定手順

① 以下を参考に、ダウンロード用のフォルダ(”semi_auto_selenium1″)を作成してください。
例: c:\user\semi_auto_selenium1\
② ①のフォルダ内に “download1” という名前でフォルダを作ってください。データを保存するためのフォルダです。
例: c:\user\semi_auto_selenium1\download1\
③ ①のフォルダ内に “semi_auto_selenium1.py” という名前でテキストファイルを作り、下記のスクリプトを貼りつけて保存してください。
例: c:\user\semi_auto_selenium1\semi_auto_selenium1.py
つぎに、このスクリプトに記載した、path0 = “…” の部分を書き換えて、selenium から呼び出すブラウザ用のドライバのありかを設定してください。
ドライバの設定をしていない場合は、下記の関連リンク(「Webスクレイピングが動かなくなったとき 【Microsoft Edge & selenium】他)などを参照してください。
④ ①のフォルダ内に “url_list1.txt” という名前でテキストファイルを作り、下記のサンプルを貼りつけて保存してください。
例: c:\user\semi_auto_selenium1\url_list1.txt

使い方

⑤ コンソールを起動して ③ のスクリプトを実行してください。
例: python c:\user\semi_auto_selenium1\semi_auto_selenium1.py
⑥ コンソールに URL のリストが表示されます。コンソール上でアクセスする URL の番号を選択してください。
→ ブラウザが起動し、設定&選択したサイトが表示されます。
※ 表示されたサイトは、よく使うサイトを初期画面として設定できるようにしているだけです。うまく動いたら、必要により画面操作を行って、データをダウンロードしたいページに移ってみてください。

⑦ コンソール上で、”show_text” と入力してみてください。
ブラウザで表示中のページのテキストを取得し、コンソールに表示します。(サイトによってはエラーコードが出るようですが、無視してページの表示が完了した後に、入力してみてください。)
⑧ ⑦で表示した内容で保存したい場合は、”save_text” と入力してください。
②の “download1” フォルダ内にデータが保存されます。
⑨ また、コンソール上で “show_table_0” と入力してみてください。
表示中のページで、最初に見つかったテーブル(HTML で <table>タグ)の内容を表示します。テーブルがない場合は表示されません。
同様に、2番目、3番目、…のテーブルの内容を確認する場合は、 “show_table_1″、”show_table_2″、… などとしてください。
⑩ ⑨で確認したテーブルの内容を保存する場合は、 “save_table_0″、”save_table_1″、”save_table_2″、…などとしてください。
⑪ 必要により、任意の画面に移ってください。
任意のページ上で、⑦~⑩の操作を行うことで、データを保存できます。
⑫ プログラムを終了する場合は、”exit” と入力してください。ブラウザを閉じて、スクリプトを終了します。

うまく動いたら

・ うまく動いたら、設定ファイル url_list1.txt (④)を編集し、よく参照するサイトなどを追加してください。
url_list1.txt は、複数の URL を各行に登録するようになっています。各行は保存時のファイル名 + “, ” + URL の形式で記載してください。
また、保存時のファイル名に “yymmdd” という文字列を入れた場合は、その部分を実行時の年月日に変換して保存します。”yymm” という文字列を入れた場合は、年月に変換して保存します。
・ たとえば、ポイントサイトなどでよく参照するサイトがあれば、トップページの URL を記載しておくことで簡単にアクセスできるようになります。
・ トップページ等が表示されたら、ID やパスワードの入力は手動で行って、ログイン後に表示されるポイントの期限や使用履歴などをコマンド1つで保存できるようになります。
・ 表を保存する場合は、何番目の表か、保存時のファイル名に番号を追加するようにしています。必要により、スクリプトを修正してください。
・ 任意のサイトのテーブルやテキストをダウンロードすることが可能です。好きなようにカスタマイズしてアレンジしてみてください。

・ サイトへのアクセスは、各サイトの利用規約に従う必要があります。また、時間をあけてアクセスするなどサーバーへの負荷を配慮する必要があります。ご理解をいただきますようお願いします。

※ なお、url_list1.txt に記載したサンプルは、「yahoo ファイナンス」、「yahoo ニュース」、「IR BANK」、「セカイハブ」を参照させていただいております。サイトの表やテキストをダウンロードできる一例として挙げています。

スクリプトの説明

・ スクリプトを実行すると、設定ファイル url_list1.txt を読み込んで、コンソールに URL を表示します。
ユーザーが URL の番号を半角数字で入力すると、対応する URL と保存時のファイル名を取得し、ブラウザを起動して該当するサイトを表示します。
・ その後、ユーザーがコマンドを入力すると、コマンドに対応する処理を実行します。
・ 内容は、下記関連リンクの「サイトを巡回してファイルをダウンロードする」を応用したものとなっています。
・ スクリプトでは、selenium と Beautiful Soup を使用しています。ブラウザを起動するところ、終了するころで selenium を使っています。表示中の画面を取得するところで Beautiful Soup を使っています。
Beautiful Soup では、サイトのテキストや表(テーブル)を取得しています。
・ テーブルの取得では、ページの HTML から、<table> タグを取得して、その内容を Python のリスト(配列)の形式に変換し、さらにリストを平易なテキストに変換しています。
・ サイトによっては、見かけは表に見えるようにしてあるけれども、実際は <div> などのタグを使って表を作っていることがあります。
その場合は、<table> タグからはデータの取得ができません。テキスト全文をいったん保存して、データ解析のための Python スクリプトを別途追加するか、今回のスクリプトを修正するなど、データ取得後の処理を追加してみてください。

まとめ

HTML の表やテキストをダウンロードするスクリプトについてまとめました。

ポイントカードなどが複数あったとき、パスワードの入力は手動で行って、ログイン後に表示されたテーブルやテキストを保存することができます。
手動操作と自動操作が混在していても、プログラムを自由に作ることが可能です。

他にも、ウェブサイトのデータを扱うスクリプトなどについてまとめています。関心のある方は参照してみてください。

関連リンク
・ 一括でファイルを移動する 【Python】
・ 一括で日付つきファイル名に変換する 【Python】

・ ウェブ検索と結果の取得を自動化する【Python & selenium】
・ Webスクレイピング時のパッケージの使い分け 【requests vs. selenium】
・ Webスクレイピングが動かなくなったとき 【Microsoft Edge & selenium】
・ サイトを巡回してファイルをダウンロードする 【Python】

外部リンク
・ IR BANK 
・ セカイハブ
・ トリドールホールディングス ご優待カード

サンプルスクリプト

表示中のテーブルやテキストをダウンロードするスクリプト semi_auto_selenium1.py

※ 以下の path0 = “…” の部分でドライバを指定しています。
path0 の部分が、ブラウザ用のドライバのありかとなるようスクリプトを修正してください。selenium のインストール時に設定していると思います。


import os 
import re 
from datetime import datetime as dt1 
from selenium import webdriver
from bs4 import BeautifulSoup as bs1 

def read1( file1 ): 
    str1 = ""
    with open( file1, 'r', encoding='utf-8' ) as f1: 
        str1 = f1.read() 
    return str1 

def write1( file1, str1 ): 
    with open( file1, 'w', encoding='utf-8' ) as f1: 
        f1.write( str1 ) 
    return 0 

def get_a1( file1 ): 
    a1 = read1( file1 ).strip().replace("\n\n", "\n").split( "\n" ) 
    for i1 in range( len(a1) ): 
        a1[i1] = a1[i1].split( ", " ) 
    return a1 

def yymmdd1(): 
    now1 = dt1.now() 
    yy1 = now1.strftime("%y") 
    mm1 = now1.strftime("%m")
    dd1 = now1.strftime("%d")
    yymmdd2 = f"{yy1}{mm1}{dd1}"
    yymm2 = f"{yy1}{mm1}"
    return yymmdd2, yymm2 

def select_url1( a1 ): 
    yymmdd0, yymm0 = yymmdd1() 
    str1 = "" 
    n1 = 0 
    file1 = ""
    url1 = "" 
    for i1 in range( len(a1) ): 
        if len(a1[i1]) > 1: 
            str1 = str1 + str(i1) + " " + a1[i1][0] + " " + a1[i1][1] + "\n" 
        else: 
            break 
    print( str1 ) 
    n1 = input( "n1:" ) 
    if n1.isdigit(): 
        n1 = int(n1) 
        if n1 > len(a1)-1: 
            n1 = 0 
        file1 = a1[n1][0].strip().replace( "yymmdd", yymmdd0 ).replace( "yymm", yymm0 ) 
        url1 = a1[n1][1].strip() 
    return n1, file1, url1 

def get_tags1( html1, tag1 ): 
    tags1 = html1.find_all( tag1 ) 
    return tags1 

def get_tables1( html1 ): 
    a1 = get_tags1( html1, "table" ) 
    return a1 

def current_html1( driver1 ): 
    url1 = driver1.current_url 
    print( url1 ) 
    page_source1 = driver1.page_source 
    html1 = bs1( page_source1, 'html.parser' ) 
    return html1 

def table2list1( table1 ): 
    rows1 = table1.find_all('tr') 
    a1 = [] 
    for row1 in rows1: 
        cells1 = row1.find_all(['th', 'td']) 
        a2 = [cell1.get_text().strip() for cell1 in cells1] 
        if "".join(a2).strip() != "": 
            a1.append( a2 ) 
    return a1 

def join1(a1): 
    str1 = ""
    for i1 in range(len(a1)): 
        str1 = str1 + " ".join( a1[i1] ) + "\n" 
    return str1 

def get_table_str1( str1, html1 ) : 
    n1 = int( str1.split( "_" )[-1] ) 
    a1 = get_tables1( html1 ) 
    a2 = [] 
    if n1 < len(a1): 
        a2 = table2list1( a1[n1] ) 
    str2 = join1(a2) 
    return str2, n1 

def get_text1( html1 ): 
    str1 = html1.get_text()
    str1 = re.sub(r'\n+', "\n", str1 ) 
    str1 = re.sub(r' +', " ", str1 ) 
    return str1 

path0 = "C:/user/edgedriver_win64/edgedriver_win64/msedgedriver.exe" 

path1 = os.path.dirname(__file__) + "/" 

file1 = path1 + "url_list1.txt" 
a1 = get_a1( file1 ) 

n1, file2, url1 = select_url1( a1 ) 

print( str(n1) + " " + file2 + " " + url1 ) 

driver1 = webdriver.Edge( executable_path=path0 ) 
driver1.get( url1 ) 

for i1 in range(10): 
    print( file2 ) 

    input1 = input( "show_table_X, save_table_X, show_text, save_text, exit: " ) 
    if input1 == "exit": 
        break 
    elif input1.startswith( "show_table_" ): 
        html1 = current_html1( driver1 ) 
        str1, n2 = get_table_str1( input1, html1 ) 
        print( str1 ) 
    elif input1.startswith( "save_table_" ): 
        html1 = current_html1( driver1 ) 
        str1, n2 = get_table_str1( input1, html1 ) 
        file3 = path1 + "download1/" + file2  + "_" + str(n2) + ".txt" 
        write1( file3, str1 ) 
    elif input1 == "show_text": 
        html1 = current_html1( driver1 ) 
        str1 = get_text1( html1 ) 
        print( str1 ) 
    elif input1 == "save_text": 
        html1 = current_html1( driver1 ) 
        str1 = get_text1( html1 ) 
        file3 = path1 + "download1/" + file2 + ".txt" 
        write1( file3, str1 ) 

driver1.quit()






設定ファイル url_list1.txt

yahoo_finance_yymmdd,  https://finance.yahoo.co.jp/stocks/ranking/dividendYield?market=all
yahoo_news1_yymmdd,   https://news.yahoo.co.jp/topics/business
canon1_yymmdd,       https://irbank.net/E02274/results
GDP_ranking_2023,    https://sekai-hub.com/statistics/wb-real-gdp-ranking-2023

タイトルとURLをコピーしました