Как использовать EC.presence_of_element_located((By.ID, "myDynamicElement")), кроме как указать класс, а не идентификатор

Я пытаюсь использовать Python для веб-очистки веб-сайта, который динамически загружает его HTML, используя встроенные файлы javascript, которые отображают данные как ответ в HTML. Поэтому, если я использую только BeautifulSoup, я не смогу получить эти данные, которые мне нужны, поскольку моя программа очистит их до того, как Javascript загрузит данные. Из-за этого я интегрирую библиотеку селена в свой код, чтобы моя программа ждала, пока не будет найден определенный элемент, прежде чем он очистит веб-сайт.

Изначально я сделал это:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.ID, "tabla_evolucion")))

Но вместо этого я хочу указать класс, сделав что-то вроде:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.class, "ng-binding ng-scope")))  

Вот остальная часть моего кода:

driver_path = 'C:/webDrivers/chromedriver.exe'
driver = webdriver.Chrome(executable_path=driver_path)
driver.header_overrides = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'}
url = "myurlthatIamscraping.com" 
response = driver.get(url)
html = driver.page_source
characters = len(html)
element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.class, "ng-binding ng-scope")))

print(html)
print(characters)
time.sleep(10)
driver.quit()

У меня это не работает, и я нигде не могу найти правильный синтаксис.

4 ответа

Решение

Соответствующий HTML помог бы нам составить более канонический ответ. Однако, чтобы начать с вашей первой строки кода:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.ID, "tabla_evolucion")))

в значительной степени законно, если вторая строка кода:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.class, "ng-binding ng-scope")))

Вызовет ошибку как:

Сообщение: недопустимый селектор: имена составных классов не разрешены

поскольку вы не можете пройти несколько классов через By.class.

Вы можете найти подробное обсуждение в Invalid selector: составные имена классов не разрешены с использованием find_element_by_class_name с Webdriver и Python


Решение

Вам нужно позаботиться о нескольких вещах, а именно:

  • Без какой-либо видимости вашего варианта использования, функционально вызывая WebDriverWait в сочетании с EC какpresence_of_element_located()просто подтверждает присутствие элемента в дереве DOM. Предположительно, продвигаясь вперед, вам нужно получить атрибуты, напримерvalue, innerTextи т. д., иначе вы могли бы взаимодействовать с элементом. Так что вместоpresence_of_element_located() вам нужно использовать либо visibility_of_element_located() или element_to_be_clickable()

Вы можете найти подробное обсуждение в WebDriverWait, который не работает должным образом

  • Для оптимального результата вы можете объединить ID а также CLASS атрибуты, и вы можете использовать любую из следующих стратегий локатора:

    • С помощью CSS_SELECTOR:

      element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".ng-binding.ng-scope#tabla_evolucion")))
      
    • С помощью XPATH:

      element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//*[@class='ng-binding ng-scope' and @id='tabla_evolucion']")))
      

Это в документации.

Набор поддерживаемых стратегий локатора.
CLASS_NAME = 'имя класса'
CSS_SELECTOR = 'css selector'
ID = 'id'
LINK_TEXT = 'текст ссылки'
NAME = 'name'
PARTIAL_LINK_TEXT = 'частичный текст ссылки'
TAG_NAME = 'имя тега'
XPATH = 'xpath'

Примечание. В вашем коде есть не класс, а два класса. Это не сработает, если вы используетеBy.CLASS_NAME()потому что он ожидает только одного класса. Вместо этого вам нужен селектор CSS.

EC.presence_of_element_located((By.CSS_SELECTOR, ".ng-binding.ng-scope")))

В синтаксисе селектора CSS .указывает класс. См. Документацию W3C для получения дополнительной информации о синтаксисе селектора CSS.

У меня есть решение, попробуйте это - измените свой класс class к CLASS_NAME

      element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.CLASS_NAME , "ng-binding ng-scope")))

попробуйте следующее:

      element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.CLASS_NAME, "ng-binding")))

или же

      element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.CLASS_NAME, "ng-scope")))

Следует упомянуть, что вы пытаетесь передать два имени класса, т.е. ng-binding - это один класс, а ng-scope - другой.

Другие вопросы по тегам