20 Авг


2017

Selenium. Автоматизация работы в браузере.

Окей, что делать если api у сайта нет нооо ооооочень хочется? Тыц пыц, качаем селениум, веб драйвер для нужного браузера, устанавливаем модуль для питона который позволяет достаточно просто обращаться к элементам и вперед. На этом в принципе уже можно было закончить. 

Мысли вслух
Конечно основная задача selenium - автоматизация тестирования.., но у меня стояла задача именно автоматизировать часть рутины через веб браузер, также из минусов стоит отметить то, что нужно поднимать графическую среду если скрипт запущен на сервере (я использовал убунту 16.04), кроме того стотит отметить недолговечность работы, если api предоставляет хоть какую-то стабильность, то в моем случае изменение любого id влечет за собой крах системы

Ну и ближе к делу, на локальком компе визуальный дисплей можно не поднимать. (В принципе на сервере с использованием hantomJs тоже, правда в нем есть ряд недостатков, например костыльное скачивание файлов).

Качаем (либо устанавливаем apt install chromedriver) отсюда

При необходимости устанавливаем Xvfb (в случае если нет GUI)

sudo apt-get install xvfb
pip install pyvirtualdisplay

Далее весь код работы браузера будет оборачивать вокруг нашего виртуального дисплея:

display = Display(visible=0, size=(1024, 768))
display.start()
...
display.stop()

С подключением к браузеру все достаточно просто, однако перед этим можно получить настройки браузера, дабы изменить ряд параметров, лично мне нужно было изменить путь загружаемого файла, для этого получаем с вебдрайвера опции браузера, и добавляем в него нужные аргументы:

from selenium import webdriver
...
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option({
   'download.default_directory': path_to_download
})
chrome_options.add_argument('--no-sandbox')

После этого можно запустить наш веб драйвер с именнованным аргументом chrome_options= (а также в случае ручной загрузки вебдрайвера указать до него путь, либо прописать в PATH)

driver = webdriver.Chrome(path_to_driver, chrome_options=chrome_options)

Теперь можно получить нужную нам страницу.

driver.get('https://google.com')

Ну и конечно можно получить нужный элемент по id или классу

elem1 = driver.find_element_by_id('id_name')
elem2 = driver.find_element_by_class_name('class_name')

Тут из минусов стоит отметить что из-за ajax дом страницы может быть загружен раньше, поэтому нужно установить ожидания, можно установить топорный тайм слипы, но можно пойти куда более рациональным способом, задать ожидание конкретного элемента.

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

...

wait = WebDriverWait(driver, 10)

wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'class_name')))
wait.until(EC.element_to_be_clickable((By.ID,'id_name')))

Тут мы устанавливаем явное ожидание, драйвер просматривает дом каждый 500мс в течении 10 секунд. В случае невыполнения кода можно поймать exception. 

Ну и в конце не забываем закрыть браузер чтобы не отъедал кровно купленную память

driver.close()

На этом пока все, информация черпалась отсюда, а также частично со stackoverflow.

фичи
selenium
web