Как проверить кликабельность элемента?
Всем добрый день. Подскажите, как нажать на строку с помощью Selenium? Написал код, но выводит ошибку, что это место не кликабельно. Как кликнуть на последние 5 игр на этой странице?
https://www.flashscore.ru/match/MmfXOTNn/#h2h;home
Сам код:
import re
import time
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def wait_to_find_by(driver, wait, value=None, find="", by=By.ID, text=True):
"""Finds an element by By object and an expectation for
checking if the given text is present in the specified element.
If no match was found within the specified time, an Exception is raised.
inputs:
driver - instance of the selenium.webdriver.some_class.
wait - instance of the selenium.webdriver.support.ui.WebDriverWait.
value[None] - The By object of the element to be found.
find[""] - the text that must be present in the element.
by[By.ID] - selenium.webdriver.common.by.By object.
text[True] - if False, then returns the element itself, otherwise - element.text.
"""
try:
element = wait.until(
EC.text_to_be_present_in_element((by, value), find)
)
element = driver.find_element(by=by, value=value)
if text:
return element.text
return element
except TimeoutException:
driver.quit()
raise Exception(f"Element not found after {wait._timeout} sec of waiting")
except Exception as e:
driver.quit()
raise e
driver = webdriver.Chrome(executable_path="C:\\Users\\iljal\\PycharmProjects\\google_sheets\\chromedriver")
driver.get('https://www.flashscore.ru/match/MmfXOTNn/#h2h;home')
wait = WebDriverWait(driver, 10)
timee = wait_to_find_by(driver, wait, "utime", ".")
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')
game = driver.find_element_by_css_selector(".odd.highlight")
game.click()
Но выводит ошибку:
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
(Session info: chrome=83.0.4103.97)
Ответы (1 шт):
проблема была, в том, что на странице также много скрытых элементов и они идут раньше, чем видимые, поэтому нам нужна проверка на видимость:
element.is_displayed() - возвращает bool значение, скрыт ли element или нет
также вам надо искать не только odd, но и even, если посмотреть на структуру html, то будет видно, что не все игры захвачены с помощью только .odd.highlight, примерно половину будет упущена.
вот решение:
import time
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def wait_to_find_by(driver, wait, value=None, find="", by=By.ID, text=True):
"""Finds an element by By object and an expectation for
checking if the given text is present in the specified element.
If no match was found within the specified time, an Exception is raised.
inputs:
driver - instance of the selenium.webdriver.some_class.
wait - instance of the selenium.webdriver.support.ui.WebDriverWait.
value[None] - The By object of the element to be found.
find[""] - the text that must be present in the element.
by[By.ID] - selenium.webdriver.common.by.By object.
text[True] - if False, then returns the element itself, otherwise - element.text.
"""
try:
element = wait.until(
EC.text_to_be_present_in_element((by, value), find)
)
element = driver.find_element(by=by, value=value)
if text:
return element.text
return element
except TimeoutException:
driver.quit()
raise Exception(f"Element not found after {wait._timeout} sec of waiting")
except Exception as e:
driver.quit()
raise e
driver = webdriver.Chrome()
driver.get('https://www.flashscore.ru/match/MmfXOTNn/#h2h;home')
wait = WebDriverWait(driver, 10)
time = wait_to_find_by(driver, wait, "utime", ".")
soup = BeautifulSoup(driver.page_source, 'lxml')
game = driver.find_element_by_css_selector(".highlight")
if game.is_displayed():
game.click()
Поправка 1: здесь кликается на последние 5 видимых игр на странице:
import time
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def wait_to_find_by(driver, wait, value=None, find="", by=By.ID, text=True):
"""Finds an element by By object and an expectation for
checking if the given text is present in the specified element.
If no match was found within the specified time, an Exception is raised.
inputs:
driver - instance of the selenium.webdriver.some_class.
wait - instance of the selenium.webdriver.support.ui.WebDriverWait.
value[None] - The By object of the element to be found.
find[""] - the text that must be present in the element.
by[By.ID] - selenium.webdriver.common.by.By object.
text[True] - if False, then returns the element itself, otherwise - element.text.
"""
try:
element = wait.until(
EC.text_to_be_present_in_element((by, value), find)
)
element = driver.find_element(by=by, value=value)
if text:
return element.text
return element
except TimeoutException:
driver.quit()
raise Exception(f"Element not found after {wait._timeout} sec of waiting")
except Exception as e:
driver.quit()
raise e
driver = webdriver.Chrome()
driver.get('https://www.flashscore.ru/match/MmfXOTNn/#h2h;home')
wait = WebDriverWait(driver, 10)
time = wait_to_find_by(driver, wait, "utime", ".")
soup = BeautifulSoup(driver.page_source, 'lxml')
games = driver.find_elements_by_css_selector(".highlight")
displayed_games = []
for game in games:
if game.is_displayed():
displayed_games += [game]
for game in displayed_games[4:]:
game.click()
