Python Seleniumによる無限スクロール 改良版

プログラミング

はじめに

スクレイピングする際に、ブラウザをスクロールしないとそもそもデータがHTML上に出てこない時(いわゆる無限スクロールが必要な時)はSeleniumが活躍する。

無限スクロールの方法は検索すればいくつかの方法が出てくるが、今回小さな工夫をいれることでパフォーマンスが向上したので残しておく。

よくある方法と問題点

よく見かける方法は、じわじわとページ最下部までスクロールして、スクロール操作をしても高さに変化がなくなった時に終了する方法だ。そしてページ読込にかかる時間を考慮して、所々で一定時間のスリープを入れている。

この方法だと数十回程度のスクロール量であれば上手くいったが、数百回以上のスクロールが必要になった時にはまだスクロール出来るのに勝手に止まることが頻発した。

具体的には https://www.quora.com/ における検索結果を一気に取得しようとした際、本来は数百スクロール出来るのに大体10-20スクロールで止まってしまっていた。

原因

スクロールの回数が多くなるに従って、ロードにかかる時間もじわじわと増えている様で、一定のスリープ時間内にロードが完了せずに、終了判定をくらっていた。

対策

スクロール操作の前後で高さが変わらなかった回数を記録し、その回数によって可変的にスリープ時間を調整するようにした。

結果

所々スタックしながらも、全部のデータを取得できた。

サンプルコード

# スタックした回数によってスリープ時間を調整
def flexible_sleep(stuck_count): 
    if stuck_count <=5:
        return 0.5
    else:
        return stuck_count/10

# Chromeドライバー設定
chrome_options = Options()
    # chrome_options.add_argument("--headless")
chrome_options.add_argument('--user-data-dir=/Users/kaitetsuro/Library/Application Support/Google/Chrome/Profile 3')
driver = webdriver.Chrome(
    chrome_options=chrome_options, executable_path="./chromedriver"
)
driver.set_window_size(1200,1000)
driver.get("https://www.quora.com/")
win_height = driver.execute_script("return window.innerHeight")
last_top = 1

# スタックした回数
stuck_count = 0

while True:
    last_height = driver.execute_script("return document.body.scrollHeight")
    top = last_top

    while top < last_height:
        top += int(win_height * 0.8)
        driver.execute_script("window.scrollTo(0, %d)" % top)
        time.sleep(flexible_sleep(stuck_count))

    time.sleep(flexible_sleep(stuck_count*2))
    new_last_height = driver.execute_script("return document.body.scrollHeight")

    if last_height == new_last_height:
        time.sleep(10)
        driver.execute_script("window.scrollTo(0, %d)" % top)
        time.sleep(10)
        stuck_count +=1
    
    print(stuck_count)

   # 50回スクックしたら諦める
    if stuck_count == 50:
        break
    
    last_top = last_height

コメント

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