MENU

Pythonでのスクレイピングを始める際に知っておくべきこと【Selenium,BeautifSoup】

以下の方向けの記事になります
  • Pythonでのスクレイピングの勉強を始めたばかりの方
  • スクレイピングのコードを書き始めたばかりの方

スクレイピングのコードを初めて書いた際に、つまったり、調べたことをまとめました。

目次

プログラム設計関連

そもそもSelenium、BeautifulSoupって何?

Seleniumはブラウザの制御、BeautifulSoupはHTMLコードからデータ抽出を行うモジュール。

上記二つを組み合わせ、以下の様な流れでスクレイピングを行います。

  1. Seleniumでブラウザを操作し、スクレイピングしたい情報のある画面にする。
  2. HTMLコードをBeautifulSoupに渡す。
  3. BeautifulSoupを用いて必要な情報を抽出する。
  4. 抽出データの不要箇所の除去、文字コードの変換等、データのクレンジングを行う。
  5. 抽出データをcsv等の形式で出力したり、抽出したURLより画像データを保存したりとデータ収集を行う。

ChromeにてCSS Selectorの取得、及び確認する方法

Chromeの開発者ツールを用いることで、CSS Selectorの取得、及び確認が容易に行えます。

Googleのトップページにある、「Gmail」の要素を指すCSS Selectorを探す例は以下の通りです。

取得手順

STEP
Googleのトップページを開きます
STEP
Google ChromeにてF12キーを押す
開発者ツールが立ち上がります
STEP
カーソルマークのボタンをクリックし、「Gmail」にカーソルを移動
STEP
「Gmail」をクリックするとHTMLコードが表示されます
STEP
右クリックからCopy→CSS Selectorを選択

コピー出来たものが選択された要素を指定するCSS Selectorとなります。

確認手順

STEP
開発者ツールからConsoleを選択し、$$(“CSS Selector”)を入力する

CSS Selectorに適合する要素がリスト形式で取得される。

STEP
Enterで確定し、展開して要素リストを確認する

開発者ツールからのコピペでは悠長なCSS Selectorではあるが、問題なく指定出来ている。

次の操作を行うタイミング

ブラウザの操作ではリンクやボタンを押してウェブサイトの読み込みやJavascriptを動作させます。

従って、クリックするべきリンクやボタンの読み込みを終えたタイミングで処理を行う必要があります。

どのタイミングで次の処理に進むかは、大きく分け次の2つの選択肢があります。

特定要素が読み込まれたタイミング
一定時間が経過したタイミング
  • 確実に挙動を制御できるため、
    何処でエラーが生じたか把握が容易
  • 無駄な待ち時間が生じないため、
    実行時間が短縮される
  • 読み込み状況がどうなろうと、時間経過後次に進む。
  • 無駄な待ち時間が生じる。
  • エラーの原因となる可能性が高いため、「最終手段」として用いる。

基本的には「特定要素が読み込まれたタイミング」で次に進むことを推奨します。

コードは下の「WebDriverWait()」の箇所がそれにあたります。

読み込み失敗等、エラー時の処理の実装

ウェブサイトの構造が変わったり、読み込みが遅いと想定通りの挙動を取らなくなります。

そのため、失敗する可能性がある処理は「リトライ処理→失敗時に原因解明のための出力」を実装する事を推奨します。

具体的には以下のコードを参考下さい。

import sys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


def exist_check_CCS_Selector(css_selector, wait_second, retries_count, driver):
    """CSS Selectorが存在するか確認する

    Args:
        css_selector ([string]): 検索する CSS Selector
        wait_second ([integer]): 待機時間
        retries_count ([integer]): リトライ回数
        driver : webdriver.Chrome()
    """
    for _ in range(retries_count):
        try:
            # リトライさせる処理
            WebDriverWait(driver, wait_second).until(EC.visibility_of_element_located((By.CSS_SELECTOR, css_selector)))
        except TimeoutException as e:
            print(e)
        else:
            # 成功時forを抜ける
            break
    else:
        # リトライしても成功しなかった場合の処理
        # スクショやSelector、URL等を出力すると原因解明が容易となる

        # 見つからなかったSelectorを出力し、終了
        sys.exit('Cant find CSS Selector {}'.format(css_selector))
    return 

Chrome Driver設定

Chrome Driverって何?

昨今のウェブサイトはJavascript等でページ内容が変化するものが大半です。

従って、ウェブサイトから単純にHTMLコードを入手するだけでは目的の情報を収集出来ません。

そこでGoogle Chromeでウェブサイトを開くためのChrome Driverを用います。

Chrome DriverのVersion選択

現在使用しているGoogle Chromeと同じVersionを選択しましょう。

Chrome Driverの設置場所

PythonもしくはAnacondaのインストール時に設定した、環境変数のPathが通っている場所に置きましょう。

Proxy(shadowsocks等)を使用したい

Chrome Driverのoptionにて「add_argument(“–proxy-server=’direct://'”)」を使用しないでください。

具体的には下のコードを参考にして下さい。

ヘッドレスモードで動かない場合のUserAgent偽装方法

ウェブサイトによっては、スクレイピング対策を行っておりブラウザ情報を確認しているようです。

ブラウザを起動させる場合は動くけど、ヘッドレスモードでは動かない場合はUserAgentを偽装して下さい。

具体的には以下のコードを参考にして下さい。

def conect_without_blowser(URL, weiting_CSS_selector, use_proxy):
    # ChoromeDriver
    op = Options()
    # ヘッドレスモード設定
    op.add_argument("--headless")
    op.add_argument("--disable-gpu")
    op.add_argument("--disable-extensions")
    op.add_argument("--start-maximized")

    # Proxyの使用分岐
    if not use_proxy:
        print("proxy not use Mode")
        op.add_argument("--proxy-server='direct://'")
        op.add_argument("--proxy-bypass-list=*")
    #UserAgentの偽装
    op.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36')  # 追加

    driver = webdriver.Chrome(chrome_options=op)

    # Seleniumでサイトアクセス
    driver.get(URL)
    WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, weiting_CSS_selector)))

    return driver

その他

Windows使用時の文字エンコーディング問題 (UTF-8→cp932変換処理)

Windowsにてcsvファイル等を出力する際、cp932に存在しない文字列が存在するとエラーとなる。

従って、cp932に存在しない文字列を除去する必要あり。

具体的には以下のコードを参考にして下さい。(無駄なスペース等の除去も併せて行っています)

def formatting_str_list(info_list):
    """文字列リストのクレンジング処理

    Args:
        info_list (list): 元の情報リスト

    Returns:
        [list]: 書式を整えた情報リスト
    """
    retrun_list = []
    for string in info_list:
        # utf8特殊文字除去
        format_str = string.encode('cp932', "ignore")
        format_str = format_str.decode('cp932')
        # 2つ以上のスペース(半角、全角)を半角スペース1つに置換
        format_str = re.sub('[  ]{2,}', ' ', format_str)
        # 改行を削除
        format_str = format_str.replace('\n', '')
        retrun_list.append(format_str)

    return retrun_list
Let's share this post!

コメントする

To comment

目次
閉じる