Получение текстового значения тега HTML через Selenium Web Automation в Python?

Я делаю бота Reddit, который будет искать определенные атрибуты в комментариях, использовать селен для посещения информационного веб-сайта и использовать driver.find_element_by... для получения значения внутри этого тега, но он не работает.

Когда я использую driver.find_element_by_class_name(), это возвращаемые данные:

<selenium.webdriver.remote.webelement.WebElement (session="f454dcf92728b9db4de080a27a844bf7", element="514bd57d-99d7-4fce-a05d-3fa92f66ad49")>

когда я использую driver.find_elements_by_css_selector(".style-scope.ytd-video-renderer"), это возвращается:

[
  <selenium.webdriver.remote.webelement.WebElement (session="43cb953cde81df270260bf769fe081a2", element="6b4ee3e2-5e6b-48e2-8ec8-9083bf15baea")>, 
  <selenium.webdriver.remote.webelement.WebElement (session="43cb953cde81df270260bf769fe081a2", ...
]

когда я использую driver.find_elements_by_css_selector(".style-scope.ytd-video-renderer").

Предположим, что это то, что я пытаюсь найти (приведенный выше код вернул приведенные выше данные Selenium для этого тега):

<yt-formatted-string class="style-scope ytd-video-renderer" aria-label="Sword Art Online: Alicization Lycoris Opening Full『ReoNa - Scar/let』 by Melodic Star 2 months ago 4 minutes, 18 seconds 837,676 views">Sword Art Online: Alicization Lycoris Opening Full『ReoNa - Scar/let』</yt-formatted-string>

Что я хочу

Я хочу вернуть Sword Art Online: Alicization Lycoris Opening Full『ReoNa - Scar/let』.

Что я мог сделать?


person KazutoKiritoKirigaya    schedule 26.09.2020    source источник


Ответы (2)


Кажется, вы были достаточно близко. Когда вы используете driver.find_element_by_class_name(), первое соответствие WebElement возвращается. При печати того же вывода:

<selenium.webdriver.remote.webelement.WebElement (session="f454dcf92728b9db4de080a27a844bf7", element="514bd57d-99d7-4fce-a05d-3fa92f66ad49")>

который представляет сам WebElement, который, возможно, содержит нужный текст.

В аналогичных строках driver.find_elements_by_css_selector(".style-scope.ytd-video-renderer") возвращает список совпадающих WebElements, и при их печати выводится:

[
  <selenium.webdriver.remote.webelement.WebElement (session="43cb953cde81df270260bf769fe081a2", element="6b4ee3e2-5e6b-48e2-8ec8-9083bf15baea")>, 
  <selenium.webdriver.remote.webelement.WebElement (session="43cb953cde81df270260bf769fe081a2",
  ...
]

Решение

Чтобы извлечь текст Sword Art Online: Alicization Lycoris Opening Full『ReoNa - Scar/let』 из следующего HTML-кода:

<yt-formatted-string class="style-scope ytd-video-renderer" aria-label="Sword Art Online: Alicization Lycoris Opening Full『ReoNa - Scar/let』 by Melodic Star 2 months ago 4 minutes, 18 seconds 837,676 views">Sword Art Online: Alicization Lycoris Opening Full『ReoNa - Scar/let』</yt-formatted-string>

Вы можете использовать любую из следующих стратегий поиска:

  • Использование css_selector и get_attribute():

    print(driver.find_element_by_css_selector("yt-formatted-string.style-scope.ytd-video-renderer").get_attribute("innerHTML"))
    
  • Используя атрибут xpath и text:

    print(driver.find_element_by_xpath("//yt-formatted-string[@class='style-scope ytd-video-renderer']").text)
    

В идеале, чтобы напечатать текст 3862,76, вы должны вызвать WebDriverWait для visibility_of_element_located(), и вы можете использовать любой из следующих Стратегии поиска:

  • Использование CSS_SELECTOR и get_attribute():

    print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "yt-formatted-string.style-scope.ytd-video-renderer"))).get_attribute("innerHTML"))
    
  • Используя атрибут XPATH и text:

    print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//yt-formatted-string[@class='style-scope ytd-video-renderer']"))).text)
    
  • Примечание. Вы должны добавить следующие импорты:

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

Вы можете найти соответствующее обсуждение в Как получить текст WebElement с помощью Selenium - Python


Outro

Ссылка на полезную документацию:

person DebanjanB    schedule 26.09.2020
comment
Спасибо, просто хочу, чтобы вы остановились на этом немного подробнее - предположим, что у меня есть несколько <span class="tags"> Lorem Ipsum </>, и я использую driver.find_elements_by... вместо driver.find_element_by..., будет ли он возвращать текст в виде одной длинной строки или будет новая строка для каждого атрибута ( Я храню эти данные и заставляю их отвечать на комментарии Reddit через PRAW, поэтому, если я использую comment.reply("tags: {}".format(tags)), будут ли они просто объединять все теги в одну строку без пробелов или между каждым тегом будет стоять пробел? - person KazutoKiritoKirigaya; 26.09.2020
comment
@KazutoKiritoKirigaya driver.find_elements всегда будет возвращать список. Вы должны повторить список, чтобы извлечь текст. - person DebanjanB; 26.09.2020
comment
В том-то и дело, что driver.find_elements_by... не является итерируемым. - person KazutoKiritoKirigaya; 26.09.2020
comment
@KazutoKiritoKirigaya Верно, но мы также можем предложить вам оптимальное решение :) Не стесняйтесь задавать новый вопрос в соответствии с вашим новым требованием. Участники StackOverflow будут рады вам помочь. - person DebanjanB; 26.09.2020
comment
Нет ли очевидного альтернативного решения этой проблемы, чтобы я мог извлечь текст из driver.find_elements_by...? - person KazutoKiritoKirigaya; 26.09.2020
comment
@KazutoKiritoKirigaya Для этого тоже есть решения. Но поскольку контекст другой, я предлагаю вам поднять новый вопрос, чтобы этот вопрос и новый были полезны для будущих читателей. - person DebanjanB; 26.09.2020
comment
Готово, надеюсь, вы ответите там! Нашел ваш ответ на это весьма полезным. - person KazutoKiritoKirigaya; 26.09.2020

Используйте .text:

element = driver.find_element_by_xpath('//*[@id="container"]/h1/yt-formatted-string')
print(element.text)
person Stroe Andrei    schedule 26.09.2020