По этому URL: https://ec.europa.eu/economy_finance/recovery-and-resilience-scoreboard/milestones_and_targets.html?lang=en
Я хочу нажать на следующую кнопку:
а затем нажмите «Просмотреть таблицу данных», но я не могу найти соответствующий элемент. Код, который я использую, следующий:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('https://ec.europa.eu/economy_finance/recovery-and-resilience-scoreboard/milestones_and_targets.html?lang=en')
element = driver.find_element(By.XPATH, '//*[@id = "highcharts-ldz37cw-0"]/svg/g[7]/g')
element.click()
Ошибка, которую я получаю:
NoSuchElementException: невозможно найти элемент: //*[@id="highcharts-ldz37cw-0"]/svg/g[7]/g; Документацию по этой ошибке можно найти по адресу: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no- such-element-Exception
В чем может быть проблема?
Возможно, вам просто нужно немного подождать, чтобы элемент стал активным. Вы пробовали это?
Я получаю ошибку NoSuchElementException. Жду полной загрузки сайта. Проблема не в этом.
«Я жду полной загрузки веб-сайта» — как именно вы ждете? Здесь нет кода, который бы ждал. Вызов find_element()
происходит сразу после вызова driver.get()
, и между ними нет ничего, что могло бы ждать. Как код ждет?
Я запускаю код построчно.
Код Python всегда выполняется «построчно», поэтому я понятия не имею, что вы имеете в виду.
Я запускаю код в интерактивном режиме построчно.
Я подозреваю, что значение идентификатора highcharts-ldz37cw-0
не является постоянным — оно может меняться каждый раз при загрузке страницы. Я только что загрузил эту страницу, и значение идентификатора — highcharts-fy53m3a-0
.
Итак, вопрос в том, какой xpath подходит для этого элемента?
Не зная полной структуры страницы, я не могу ответить на этот вопрос. Обычный подход состоит в том, чтобы просмотреть исходный код страницы и найти некоторый элемент-предок, который однозначно идентифицируется (часто с использованием его атрибутов id
или class
), и построить относительный xpath, начиная с этого элемента, вплоть до желаемого целевого элемента.
И на самом деле это именно то, что вы сделали, за исключением того, что вы не знали, что значение id является переменным.
Вы можете найти его по имени класса. Кроме того, окно необходимо прокрутить до элемента:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Firefox()
element = driver.find_element(By.XPATH, '//*[@class = "highcharts-exporting-group"]')
ActionChains(driver).move_to_element(element).click().perform()
Обратите внимание, что идентификатор highcharts-ldz37cw-0
генерируется динамически, поэтому вам следует либо избегать его использования, либо найти обходной путь с помощью contains
или чего-то еще.
find_elements()
возвращает список, у которого явно нет метода .click()
. Вы имели в виду find_element()
вместо этого?
Хороший улов, спасибо. Конечно, find_element()
или find_elements()[0]
, я отредактировал ответ.
Хотя вы можете выбрать элемент, как вы упомянули, вы не можете щелкнуть его. Я получаю ElementNotInteractableException: элемент <g class = "highcharts-exporting-group"> не удалось прокрутить в поле зрения
@TheodosisSiomos, ты прав. Затем вам нужно прокрутить до элемента. Либо по driver.execute_script("window.scroll(0, 600)")
, либо по ActionChains
. Я обновил ответ, не могли бы вы проверить?
Что ж, теперь я получаю: MoveTargetOutOfBoundsException: цель перемещения (632, 783) выходит за пределы размеров области просмотра (1360, 643).
Я просмотрел код и нашел метод viewData()
, который вызывается при нажатии View data table
.
Мы можем напрямую вызвать его для первого графика, используя этот скрипт:
window.Highcharts.charts[0].viewData()
И сделать это в селене:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get('https://ec.europa.eu/economy_finance/recovery-and-resilience-scoreboard/milestones_and_targets.html?lang=en')
# wait until chart is loaded
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div#fulfillmentStatusBarChart > div[id^=highcharts]')))
# show data table for ALL charts
driver.execute_script('window.Highcharts.charts.forEach(ch => ch.viewData())')
# select the data table
table = driver.find_element(By.CSS_SELECTOR, 'table[id^=highcharts-data-table]') # div.highcharts-data-table
print(table.text)
Как вы узнали, что здесь задействован сценарий?
@TheodosisSiomos отладчик, код не запутан, поэтому его гораздо легче понять.
«невозможно найти соответствующий элемент» неоднозначно. Пожалуйста, обновите вопрос и добавьте полное сообщение об ошибке, чтобы нам не приходилось догадываться, что вы имеете в виду.