Обрабатываем нажатие кнопки в Selenium
В материале «Парсим данные, используя Buetiful Soup и Selenium» мы уже рассмотрели, как быть, когда данные на странице динамически подгружаются при скролле страницы. Но бывают ситуации, когда новые данные можно получить, только нажав на кнопку «Показать ещё» — сегодня узнаем, как через Selenium сымитировать нажатие кнопки для полного открытия страницы, соберём идентификаторы пива, оценки к каждому продукту и отправим данные в Clickhouse
Структура страницы
Возьмём случайную пивоварню — у неё 105 чекинов, то есть, отзывов. Страница с чекинами пивоварни показывает не более 25 чекинов и выглядит так:

Если попробуем промотать в самый низ, столкнёмся с той самой кнопкой, мешающей нам взять все 105 за раз:

Мы поступим так: выясним, к какому классу относится элемент кнопки и будем на неё нажимать, пока это возможно. Так как Selenium запускает браузер, следующая кнопка «Показать ещё» может не успеть прогрузиться, поэтому между нажатиями поставим интервал в пару секунд. Как только страница раскроется полностью — мы возьмём её содержимое и распарсим нужные данные из чекинов. Зайдём в код страницы и найдём кнопку — она относится к классу more_checkins .

У кнопки есть свойства стиля, а именно — display . В случае, если кнопка должна отображаться, display принимает значение block . Но когда промотаем страницу до самого конца, кнопку не нужно будет показывать, ведь открывать больше нечего — поэтому display кнопки примет значение none . В случае, если мы запросим у кнопки display и вернётся none будем знать, что открывать больше нечего и можно перестать жать на кнопку.

Пишем код
Начнём с импорта библиотек:
import time from selenium import webdriver from bs4 import BeautifulSoup as bs import re from datetime import datetime from clickhouse_driver import Client
Chromedriver, необходимый для запуска браузера через Selenium, можно установить с официальной страницы
Подключимся к базе данных, зададим cookies:
client = Client(host='ec1-23-456-789-10.us-east-2.compute.amazonaws.com', user='', password='', port='9000', database='') count = 0 cookies = < 'domain':'untappd.com', 'expiry':1594072726, 'httpOnly':True, 'name':'untappd_user_v3_e', 'path':'/', 'secure':False, 'value':'your_value' >
О том, как запускать Selenium с cookies можно прочитать в материале «Парсим данные каталога сайта, используя Beautiful Soup и Selenium». Нам нужен параметр untappd_user_v3_e.
Так как мы планируем работать с пивоварнями, у которых более сотни тысяч чекинов, может оказаться так, что страница будет чересчур тяжёлой, и нагрузка на машину будет огромна. Чтобы этого избежать, отключим всё лишнее, а затем подключим cookie для авторизации:
options = webdriver.ChromeOptions() prefs = > options.add_experimental_option('prefs', prefs) options.add_argument("start-maximized") options.add_argument("disable-infobars") options.add_argument("--disable-extensions") driver = webdriver.Chrome(options=options) driver.get('https://untappd.com/TooSunnyBrewery') driver.add_cookie(cookies)
Напишем функцию, которая принимает ссылку, переходит по ней, полностью раскрывает страницу и возвращает нам soup, который можно будет распарсить. Получим display кнопки и запишем в переменную more_checkins : пока он не равен none будем нажимать на кнопку и снова получать её display . Сделаем интервал в две секунды между нажатиями, чтобы подождать прогрузку страницы. Как только будет получена вся страница, переведём её в soup библиотекой bs4 .
def get_html_page(url): driver.get(url) driver.maximize_window() more_checkins = driver.execute_script("var more_checkins=document.getElementsByClassName('more_checkins_logged')[0].style.display;return more_checkins;") print(more_checkins) while more_checkins != "none": driver.execute_script("document.getElementsByClassName('more_checkins_logged')[0].click()") time.sleep(2) more_checkins = driver.execute_script("var more_checkins=document.getElementsByClassName('more_checkins_logged')[0].style.display;return more_checkins;") print(more_checkins) source_data = driver.page_source soup = bs(source_data, 'lxml') return soup
Напишем следующую функцию: она тоже будет принимать url страницы, передавать его в get_html_page , получать soup и парсить его. Функция вернёт запакованные списки с идентификатором пива и оценкой к нему.
О том, как парсить элементы страницы мы уже говорили в материале «Парсим данные каталога сайта, используя Beautiful Soup».
def parse_html_page(url): soup = get_html_page(url) brewery_id = soup.find_all('a', )[0]['href'][28:] items = soup.find_all('div', ) checkin_rating_list = [] beer_id_list = [] count = 0 print('Заполняю списки') for checkin in items: print(count, '/', len(items)) try: checkin_rating_list.append(float(checkin.find('div', )['data-rating'])) except Exception: checkin_rating_list.append('cast(Null as Nullable(Float32))') try: beer_id_list.append(int(checkin.find('a', )['href'][-7:])) except Exception: beer_id_list.append('cast(Null as Nullable(UInt64))') count += 1 return zip(checkin_rating_list, beer_id_list)
Наконец, напишем вызов функций по пивоварням. В материале «Использование словарей в Clickhouse на примере данных Untappd» мы уже рассмотрели, как получить список идентификаторов российских пивоварен — обратимся к нему через таблицу в Clickhouse
brewery_list = client.execute('SELECT brewery_id FROM brewery_info')
Если посмотрим на brewery_list , то узнаем, что данные вернулись в неудобном формате: это список кортежей.

Небольшое лямбда-выражение позволит его «выпрямить»:
flatten = lambda lst: [item for sublist in lst for item in sublist] brewery_list = flatten(brewery_list)
Работать с таким списком значительно комфортнее:

Для каждой пивоварни в списке сформируем url — он состоит из стандартной ссылки и идентификатора пивоварни в конце. Отправим url в функцию parse_html_page , которая сама вызовет get_html_page и вернёт списки с beer_id и rating_score . Так как два списка вернутся упакованными можем пройти по ним итератором, сформировав кортеж и отправив его в Clickhouse.
for brewery_id in brewery_list: print('Беру пивоварню с id', brewery_id, count, '/', len(brewery_list)) url = 'https://untappd.com/brewery/' + str(brewery_id) returned_checkins = parse_html_page(url) for rating, beer_id in returned_checkins: tuple_to_insert = (rating, beer_id) try: client.execute(f'INSERT INTO beer_reviews VALUES ') except errors.ServerException as E: print(E) count += 1
С кнопками на этом всё. Постепенно мы формируем отличный датасет для последующего анализа, который рассмотрим в следующем цикле статей, как только завершим сбор данных — возможно, через месяц.
Python-сообщество
![]()
- Начало
- » Python для новичков
- » Как «нажать кнопку»?
#1 Ноя. 19, 2017 14:58:57
DenAon От: Ярославль Зарегистрирован: 2017-11-17 Сообщения: 5 Репутация: 0 Профиль Отправить e-mail
Как «нажать кнопку»?
Изучаю Python 3 и Selenium Webdriver.
Есть страница с Яндека, картинки https://yandex.ru/images/
Нужно нажать кнопку для перехода на картинку предыдущего дня
try:
elem2 = driver.find_element_by_class_name("b-501px-slider__arrow b-501px-slider__arrow_dir_prev")
except NoSuchElementException:
qwe = input("Не нашлось кнопки Назад. Нажмите Enter для выхода")
else:
print("Переход по кнопке Назад")
Происходит исключение.
Как я понимаю проблемы могут быть следующие:
1. кнопка не видимая, нужно навести на нее мышку и нажать.
2. здесь срабатывает не нарисованная кнопка, а другой элемент, которому и надо передавать событие нажатия.
Прошу задать ускорение в нужную сторону.
Многознание уму не научает.
#2 Ноя. 20, 2017 19:38:19
hvppydvddy Зарегистрирован: 2015-05-26 Сообщения: 36 Репутация: 0 Профиль Отправить e-mail
Как «нажать кнопку»?
DenAon
elem2 = driver.find_element_by_xpath("/html/body/div[6]/div[1]/div/div[1]/div[3]/div[4]/div[1]/div") driver.execute_script("$(arguments[0]).click();", elem2) print("Переход по кнопке Назад")

Отредактировано hvppydvddy (Ноя. 20, 2017 19:46:30)
#3 Ноя. 20, 2017 19:57:42
DenAon От: Ярославль Зарегистрирован: 2017-11-17 Сообщения: 5 Репутация: 0 Профиль Отправить e-mail
Как «нажать кнопку»?
hvppydvddy
DenAon
Благодарю за ответ. Я уже успел кой чего приколхозить, основная проблема была в том что я смотрел функцию хрома “посмотреть код”. Он показывал вот такой код
Но когда подсвечивается элемент при выделении кода, на экране он уже обозван как
div.b-501px-slider__arrow.b-501px-slider__arrow_dir_prev
Вместо пробела точка.
второй прикл, что эта кнопка при первой загрузке подсвечена и имеет вот такой код
Он отличается от того что я искал и нажимал.
В итоге пришлось сделать задержку и после нее искать элемент и нажимать.
time.sleep(1)
try:
elem2 = driver.find_element_by_class_name("b-501px-slider__arrow.b-501px-slider__arrow_dir_prev")
except NoSuchElementException:
qwe = input("Не нашлось кнопки Назад. Нажмите Enter для выхода")
else:
print("Переход по кнопке Назад")
Click = ActionChains(self.driver).click(elem2)
Click.perform()
Еще подскажите каким инструментом можно найти правильный XPATH для элемента. А то из просмотра кода что то он совсем не видится. Или я не там смотрю.
Многознание уму не научает.
#4 Ноя. 20, 2017 20:02:58
hvppydvddy Зарегистрирован: 2015-05-26 Сообщения: 36 Репутация: 0 Профиль Отправить e-mail
Как «нажать кнопку»?
DenAon
ще подскажите каким инструментом можно найти правильный XPATH для элемента
Фаерфокс с этим справляется на ура) в старых версиях (если не ошибаюсь ниже 50) это аддон Fire Bug + FirePath. А на последней версии вообще сказка без всяких аддонов, ПКМ по элементу -> Исследовать элемент, снизу на выделенной строчке жмем ПКМ -> копировать -> Xpath
Отредактировано hvppydvddy (Ноя. 20, 2017 20:03:37)
#5 Ноя. 20, 2017 20:14:09
DenAon От: Ярославль Зарегистрирован: 2017-11-17 Сообщения: 5 Репутация: 0 Профиль Отправить e-mail
Как «нажать кнопку»?
hvppydvddy
Круто, буду знать! Полезный совет.
Многознание уму не научает.
![]()
- Начало
- » Python для новичков
- » Как «нажать кнопку»?
Python Selenium Иммитировать нажатие на кнопку «я не робот» recaptcha v2
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нем неправильно.
Необходимо обновить браузер или попробовать использовать другой.
themixa
Новичок
Пользователь
Май 13, 2020 14 0 1
Windows 10 , Python 3.9.5 , Хочу иммитировать нажатие на копку «я не робот» recaptcha v2. Но выдает ошибку : selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified ; «объект не допустим или закрыт» подскажите как обойти recaptcha v2 и нажать «я не робот» . Спасибо
import webbrowser,time,os,pyautogui
import selenium.common.exceptions
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import random
import os
from selenium.webdriver.chrome.options import Options
Как нажать на кнопку Selenium?

Здраствуйте, имеется такая кнопка: Я хочу на нее сделать клик, вот код —
chrome.find_element_by_xpath('//input[@value="Выберите файл. "]').click()
В итоге имею такую ошибку:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
Как это сделать? Кнопка кликабельна мышью
Отслеживать
задан 7 сен 2021 в 0:41
Vladimir Maksymchuk Vladimir Maksymchuk
57 2 2 серебряных знака 12 12 бронзовых знаков
Выведите на печать весь этот элемент прямо из кода. Сравните с тем, что видите в инспекторе. Терзают смутные сомнения, что вы слишком быстро добираетесь до кнопки и в момент обращения к ней она отключена. Возможно, в классах элемента установлен какой-то класс для отключения кнопки в этот момент или имеется соответствующий аргумент тега.