[Python] Seleniumスクレイピングメモ

pythonでスクレイピングをしてみたのでメモ

スポンサーリンク

Seleniumとは

ブラウザの自動テストを行うためのものらしい、それを利用してプログラム(Python)からブラウザを操作して情報を取って来よう!というのがスクレイピングというらしい。

スポンサーリンク

なんでSeleniumでスクレイピング?

Seleniumを使うとjavascriptが実行されたあとのhtmlが取得できる。

また、プログラムからブラウザを操作できる。
・要素を指定してクリックしたり、キーを押したりできる。
・要素を指定してテキストを入力できる。

スポンサーリンク

Seleniumを使ってのスクレイピングのながれ

・目的のデータがあるページを開く
・がんばって目的のデータがある要素を取得する
・取得した要素から目的のデータを取得する

要素を取得する方法はいくつか用意されている。
・CSSセレクタで要素を指定
・XPathで要素を指定
…など

目的のデータに応じてこんな感じのことをする、
画像の場合は、imgタグのsrc属性から画像のurlを取得
取得したurlを使ってrequestsなどを使い画像をダウンロード

リンクの場合はaタグのhref属性からurlを取得
取得したurlを使いページ遷移したりする

属性を取得するには取得した要素のget_attributeメソッドを使う
テキストの場合はtextプロパティを使う
コードは下に記載

スポンサーリンク

環境整備

ブラウザのインストール

たぶんブラウザ(ChromeとかFirefoxとか)もインストールしないと動かない。

webdriverを入手

使いたいブラウザに合わせて「webdriver + chrome」、「webdriver + firefox」などで検索してドライバーを入手。

「chromedriver.exe」、「geckodriver.exe」などがドライバー本体
プログラム内でこのexeのパスを指定する

seleniumをpipする

pip install selenium
スポンサーリンク

起動

指定したURLのページを開く

firefoxで試した。chromeとかだとwebdriver.Chromeになる

from selenium import webdriver

url = '開きたいURL'
driverpath = 'webdriverのパス'
with webdriver.Firefox(executable_path=driverpath) as driver:
    driver.get(url)

withを使うと、withを抜けるとブラウザを閉じてくれる

ブラウザを非表示で実行する

Headlessモードというらしい。
optionを指定してwebdiverに渡す。

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

url = '開きたいURL'
driverpath = 'webdriverのパス'

op = Options()
op.set_headless()
with webdriver.Firefox(executable_path=driverpath, options=op) as driver:
    driver.get(url)
スポンサーリンク

要素の取得

見つかった最初の要素1つを返すメソッドと、見つかった要素すべてを返すメソッドがある。
find_element_xxxx が最初の一つで、
find_elements_xxxx が見つかったすべて(リストが返ってくる)

xxxxの部分は取得したい要素に合わせてid、tag名やclass名なんかで検索することができる。

find_element_by_class_name
find_element_by_css_selector
find_element_by_id

以下はcss_selectorを使用。

find_element系の戻り値のオブジェクトも同じメソッドを持っていて、見つかった要素の子要素のみを対象にまた検索するということができる。
戻り値はおそらくWebElementクラス

element1 = driver.find_element_by_css_selector('[id="aaaa"]')
element2 = element1.find_element_by_css_selector('div')

find_elementは指定した要素が見つからないとエラーになる。
回避したいときはfind_elementsを使ってWebElementのリストを受け取りその長さを判定したりする。

属性の取得

get_attributeメソッドを使う
引数に属性名を指定する

<div id=”yasnote” class=”c1″/>
からclassの値を取りたい場合、

# id=yasnoteの要素を検索
element1 = driver.find_element_by_css_selector('[id="yasnote"]')
# 要素からclassの値を取り出す
class_value = element1.get_attribute('class')
print(class_value)

テキストの取得

textプロパティを使う

<div id=”yasnote”>AAAAA</div>
からテキストの値を取りたい場合、

# id=yasnoteの要素を検索
element1 = driver.find_element_by_css_selector('[id="yasnote"]')
# テキストを取得、というか表示
print(element1.text)

非表示なテキストの取得

hiddenだったり、<title>タグなんかはtextプロパティを使うと空文字が取れてくる。
get_attribute(‘textContent’)を使うとテキストが取れる

element1 = driver.find_element_by_css_selector('[id="yasnote"]')
txt = element1.get_attribute("textContent")
print(txt)
スポンサーリンク

ブラウザの操作

以下を組み合わせるとユーザー名とかパスワードを入力してログインボタンをクリックなんてことができる。

クリック

選択した要素のclickメソッドを使う
<div id=”yasnote”/>を選択してクリックする場合、

element1 = driver.find_element_by_css_selector('[id="yasnote"]')
element1.click()

テキスト入力

選択した要素のsend_keysメソッドを使う
引数に入力したテキストを指定する

# 入力したい要素を取得
element1 = driver.find_element_by_css_selector('[id="yasnote"]')
# 入力
element1.send_keys('aaaabbcc')

キー入力

こちらも選択した要素のsend_keysメソッドを使う
引数にキーを指定する(Keys.XXX)

# Keysをインポート
from selenium.webdriver.common.keys import Keys
# キー入力したい要素を取得
element1 = driver.find_element_by_css_selector('[id="yasnote"]')
# キー入力(↑キー)
element1.send_keys(Keys.UP)

Enterキーとか、方向キーとかいろいろ入力できる
Keysの一覧は以下を参照した
https://www.seleniumqref.com/api/python/element_set/Python_special_send_keys.html

スポンサーリンク

javascriptの実行

開いているブラウザでjavascriptを実行できる
webdriverのexecute_scriptメソッドまたは、execute_async_scriptメソッドを使う
execute_async_scriptはjavascriptの中でリクエストを投げたり非同期処理を行う場合に使う

それぞれのメソッドの引数には、
第1引数にスクリプトを書いた文字列、
第2引数以降にスクリプトに渡す変数を指定する(可変長)

引数に指定した変数はargumentsという名前の配列でスクリプト内に渡される
スクリプト内の変数に代入したりして使う

execute_scriptメソッドの場合はスクリプト内でreturnで結果を返す

# 実行したいスクリプト
script = """
    var arg1 = arguments[0];
    var arg2 = arguments[1];
    return arg1 + 100;
"""
# 実行して結果を受け取る
ret = driver.execute_script(script, 10, 20)
# 結果を表示
print(ret)

execute_async_scriptメソッドの場合はスクリプト内でcallback(返したい値)で結果を返す
callback用のオブジェクトはargumentsの最後尾に入っている(4行目)

# 実行したいスクリプト
script = """
    var arg1 = arguments[0];
    var callback = arguments[arguments.length - 1];
    var xhr = new XMLHttpRequest();
    xhr.onload = function(){ callback(xhr.responseText) };
    xhr.open('GET', arg1);
    xhr.send();
"""
# 実行して結果を受け取る
ret = driver.execute_async_script(script, 'jsonが返ってくるurl')
# 結果を表示
print(ret)

コメント

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