Python

【Python】seleniumでページをスクロールしてスクレイピングする

記事内に商品プロモーションを含む場合があります

こんにちは、hokkyokunです。

あるウェブサイトの情報を取得したくて、スクレイピングをしたのですが、スクロールしないと全体が見えない構成のページだったので、スクロールを自動化して処理しようと思います。

コード

一般的に使えるように関数化しています。

戻り値はhtml(文字列型)
引数はurlとページ読み込みの待ち時間です。デフォルト値として1秒としています。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

def get_full_page_source(url, scroll_pause_time=1):
    """
    指定されたURLのウェブページを開き、ページの最下部までスクロールして全てのHTMLソースを取得する。

    Args:
    url (str): スクレイピングするウェブページのURL。
    scroll_pause_time (int, optional): スクロール間の待機時間(秒)。デフォルトは1秒。

    Returns:
    str: ページの全HTMLソース。
    """
    # ChromeのWebDriverオブジェクトを作成
    driver = webdriver.Chrome()

    try:
        # スクレイピングするURLにアクセス
        driver.get(url)

        last_height = driver.execute_script("return document.body.scrollHeight")

        while True:
            # ページの最下部までスクロール
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            # ページがロードされるのを待つ
            time.sleep(scroll_pause_time)
            # 新しいページの高さを取得し、古いページの高さと比較
            new_height = driver.execute_script("return document.body.scrollHeight")
            if new_height == last_height:
                break
            last_height = new_height

        # HTMLを取得
        html_source = driver.page_source

        return html_source

    finally:
        # ブラウザを閉じる
        driver.close()


実際に使用

実際に使ってみます。

ウィブル証券という新興の証券会社の取り扱い銘柄数を調べたかったのですが、どこにも情報が載っていなかったので、

このページを最後までスクロールしてテーブルを全取得して数を数えてみようと思います。

上の画像は検索したいページのスクショをとったわけですが、「株式」もしくは「ETF」をクリックすると該当する銘柄でる仕組みになっています。

ETFだけ数を調べたかったので、スクロールを始める前にクリック操作をする必要があります。

つまり、

  1. セレニウムでページ読み込み
  2. 「ETF」ボタンをクリック
  3. 最後までスクロール
  4. 読み込んだhtmlからテーブルを取得

こんな感じの作業を行おうと思います。

ちょっと関数を変化させ、上記の処理をやっていきます。

<pre class="wp-block-syntaxhighlighter-code">def get_full_page_source(url, scroll_pause_time=1):
 
    # ChromeのWebDriverオブジェクトを作成
    driver = webdriver.Chrome()

    
    # スクレイピングするURLにアクセス
    driver.get(url)
    time.sleep(2)

    #クリック
    elements=driver.find_elements(By.CLASS_NAME,"wbapp50 ")
    elements<img class="ranking-number" src="https://www.hokkyokun.com/wp-content/themes/jin/img/rank01.png" />.click()
    time.sleep(2)

    last_height = driver.execute_script("return document.body.scrollHeight")

    while True:
        # ページの最下部までスクロール
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        # ページがロードされるのを待つ
        time.sleep(scroll_pause_time)
        # 新しいページの高さを取得し、古いページの高さと比較
        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:
            break
        last_height = new_height

    # テーブルの取得
    thead=driver.find_element(By.TAG_NAME,"thead")
    ths=thead.find_elements(By.TAG_NAME,"th")
    columns=[]
    for th in ths:
        columns.append(th.text)

    
    tbody=driver.find_element(By.TAG_NAME,"tbody")
    trs=tbody.find_elements(By.TAG_NAME,"tr")
    datas=[]
    for tr in trs:
        data=[]
        tds=tr.find_elements(By.TAG_NAME,"td")
        for td in tds:
            data.append(td.text)
        datas.append(data)
    
    df=pd.DataFrame(datas,columns=columns)

    driver.close()
    return df</pre>

実際に動かしてみます。

url = "https://www.webull.co.jp/search"
df = get_full_page_source(url,2)

こんな感じでテーブル取得できました

ウィブル証券で取り扱っているETFの数は224でした。
思ったより少なかったです。

SBI証券の方が多かったような。。