はじめに
seleniumって書くのめんどくさいくないですか?
「入力やクリックみたいな簡単な操作でも要素取得->入力・クリックみたいに2手間かかる」
「サイトの表示速度に応じてtime.sleep()に入れるパラメータの値を調整する(表示されるまで待機するメソッドもあるが記述がめんどくさい)」
「ActionChainsは記述がめんどくさい」
などで自分は結構面倒に感じてしまいます
こういった面倒を改善したかったので、各操作を1つのメソッドで実行できるクラスを試しに作ってみました。
クラス
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
import time
class WaitDriver:
TIMEOUT = 20
SLEEP = 1
def __init__(self, driver):
if not isinstance(driver, webdriver.Chrome):
raise("Invalid driver type, expected for Chrome")
self.__driver = driver
def get(self, url):
self.__driver.get(url)
def quit(self):
self.__driver.quit()
def find(self, xpath, timeout=TIMEOUT):
wait = WebDriverWait(self.__driver, timeout)
element = wait.until(
expected_conditions.visibility_of_element_located(
(By.XPATH, xpath)
)
)
return element
def send_keys(self, xpath, text, timeout=TIMEOUT, sleep=SLEEP):
element = self.find(xpath, timeout)
time.sleep(sleep)
element.send_keys(text)
return element
def click(self, xpath, timeout=TIMEOUT, sleep=SLEEP):
wait = WebDriverWait(self.__driver, timeout)
element = wait.until(
expected_conditions.element_to_be_clickable(
(By.XPATH, xpath)
)
)
time.sleep(sleep)
element.click()
return element
def move_to_element(self, xpath, timeout=TIMEOUT, sleep=SLEEP):
element = self.find(xpath, timeout)
actions = ActionChains(self.__driver)
actions.move_to_element(element)
time.sleep(sleep)
actions.perform()
return element
def drug_and_drop(self, draggable_xpath, droppable_xpath, timeout=TIMEOUT, sleep=SLEEP):
source = self.find(draggable_xpath, timeout)
target = self.find(droppable_xpath, timeout)
actions = ActionChains(self.__driver)
actions.click_and_hold(source)
actions.move_to_element(target)
time.sleep(sleep)
actions.perform()
return source, target
使い方
windowsでのselenium環境構築方法はこちらを参考にしてください。
###1. インスタンス
from selenium import webdriver
import chromedriver-binary
from wait_driver import WaitDriver
driver = Webdriver.Chrome()
# 作ったやつをインスタンス化
wd = WaitDriver(driver)
###2. メソッド
# 指定のURLにアクセス
wd.get(url)
#(指定の要素が表示されるまで待機して)取得、要素返却
element = wd.find(xpath)
#(指定の要素がクリックできるまで待機して)クリック、要素返却
wd.click(xpath)
#(指定の要素が表示されるまで待機して)入力、要素返却
wd.send_keys(xpath, text)
#(画面外の指定した要素が表示されるまで待機して)スクロール、要素返却
element = wd.move_to_element(xpath)
#(指定したドラッグ要素とドロップ要素が表示されるまで待機して)ドラッグ&ドロップ、2つの要素返却
wd.drug_and_drop(druggable_xpath, droppable_xpath)
# Chromeを閉じる
wd.quit()
各メソッドにはtimeout
とsleep
の値を渡すこともできます。
timeout
は要素取得するまでに許容する時間です。時間内に要素が取得できなければタイムアウトになります。デフォルトは20秒。
sleep
は要素取得してから次のアクションを起こすまでの時間です。これを設定しないと操作が早すぎてクローリングしていることがばれる可能性があるので1ないしは2秒以上を推奨します。デフォルトは1秒。
また、デフォルトの値自体を変更したい場合はWaitDriverのクラス変数(以下部分)を直接いじります。
class WaitDriver:
TIMEOUT = 20
SLEEP = 1
....
まとめ
まだ十分には使ってないですが、ちょっと試した感じだとなかなかよさげなのでよかったら使ってみてください。まだメソッドが少ないですし、xpathでしか要素を取得できないのでそこは今後ブラッシュアップしていければと思います。