Youtube与selenium擦肩而过:没有得到所有评论

2024-09-28 01:33:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用selenium和python来获取youtube的评论。下面是一段代码,它只获取一个注释并抛出错误

driver = webdriver.Chrome()
url="https://www.youtube.com/watch?v=MNltVQqJhRE"
driver.get(url)

wait(driver, 5500)

driver.execute_script("window.scrollTo(0, document.body.scrollHeight + 500);")
driver.implicitly_wait(5000)

#content = driver.find_element_by_xpath('//*[@id="contents"]')
comm=driver.find_element_by_xpath('//div[@class="style-scope ytd-item-section-renderer"]')
comm1=comm.find_elements_by_xpath('//yt-formatted-string[@id="content-text"]')
#print(comm.text)
for i in range(50):
    print(comm1[i].text,end=' ')

这是我得到的输出。我怎样才能得到那个页面上的所有评论???有人能帮我吗。在

^{pr2}$

Tags: textidurlbyyoutubedriver评论element
1条回答
网友
1楼 · 发布于 2024-09-28 01:33:58

IndexError表示您试图访问不存在的列表中的位置。您在元素列表(comm1)上迭代了整整50次,但是列表中的元素少于50个,因此最终您将尝试访问一个不存在的索引。在

从表面上看,您可以通过将迭代改为循环使用列表中存在的元素来解决问题:

for element in comm1:
    print(element.text, end=‘ ‘)

但这会给你留下一个问题:为什么你的列表中的元素少于50个。你正在抓取的视频有超过90条评论。为什么你的单子上没有全部?在

如果您在浏览器中查看页面,您将看到使用infinite scroll技术逐步加载注释:当用户滚动到文档底部时,另一个注释“页面”被获取并呈现,从而增加了文档的长度。要加载更多注释,需要触发此行为。在

但根据评论的数量,一次获取可能不够。为了触发所有内容的获取和呈现,您需要:

  1. 尝试触发获取附加内容,然后
  2. 确定是否提取了附加内容,如果是
  3. 重复(因为可能会有更多的)。在

触发获取

我们已经知道,通过滚动到内容容器(带有id#contents的元素)的底部来获取附加内容,所以让我们这样做:

^{pr2}$

(注意:由于内容驻留在absolute位置的元素中,document.body.scrollHeight将始终是{},并且不会触发滚动。)

正在等待内容容器

但与任何浏览器自动化一样,我们也在与应用程序竞争:如果内容容器还没有呈现呢?我们的卷轴会失败。在

Selenium提供^{}帮助您等待应用程序处于特定状态。它还通过其^{}模块提供一组要等待的公共状态,例如元素的存在。我们可以使用这两种方法来等待内容容器出现:

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

TIMEOUT_IN_SECONDS = 10

wait = WebDriverWait(driver, TIMEOUT_IN_SECONDS)
wait.until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "#contents")))

确定是否提取了其他内容

在较高的级别上,我们可以确定是否通过以下方式获取了附加内容:

  1. 之前对内容进行计数我们触发提取
  2. 计算之后我们触发fetch,然后
  3. 比较两者。在

计算内容

在我们的容器中(使用id"#contents"),每个内容片段都有id#content。要计算内容,我们只需获取其中的每个元素并使用Python的内置len()

count = len(driver.find_elements_by_css_selector("#contents #content")

处理慢速渲染

但是,我们又在与应用程序竞争:如果获取或呈现附加内容的速度很慢,会发生什么情况?我们不会马上看到的。在

我们需要给web应用程序时间来完成它的工作。为此,我们可以将WebDriverWait()与自定义条件一起使用:

def get_count():
    return len(driver.find_elements_by_css_selector("#contents #content"))

count = get_count()
# ...
wait.until(
    lambda _: get_count() > count)

不处理其他内容

但是如果没有其他内容呢?我们等待计数增加将超时。在

只要我们的超时足够高以便有足够的时间让附加内容出现,我们可以假设没有其他内容并忽略超时:

try:
    wait.until(
        lambda _: get_count() > count)
except TimeoutException:
    # No additional content appeared. Abort our loop.
    break

把它们放在一起

from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

TIMEOUT_IN_SECONDS = 10

wait = WebDriverWait(driver, TIMEOUT_IN_SECONDS)

driver.get(URL)

wait.until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "#contents")))

def get_count():
    return len(driver.find_elements_by_css_selector("#contents #content"))

while True:
    count = get_count()
    driver.execute_script(
        "window.scrollTo(0, document.querySelector('#contents').scrollHeight);")
    try:
        wait.until(
            lambda _: get_count() > initial_count)
    except TimeoutException:
        # No additional content appeared. Abort our loop.
        break

elements = driver.find_elements_by_css_selector("#contents #content")

奖励:简化水豚py

使用capybara-py,这会变得简单一些:

import capybara
from capybara.dsl import page
from capybara.exceptions import ExpectationNotMet

@capybara.register_driver("selenium_chrome")
def init_selenium_chrome_driver(app):
    from capybara.selenium.driver import Driver
    return Driver(app, browser="chrome")

capybara.current_driver = "selenium_chrome"
capybara.default_max_wait_time = 10

page.visit(URL)

contents = page.find("#contents")

elements = []
while True:
    try:
        elements = contents.find_all("#content", minimum=len(elements) + 1)
    except ExpectationNotMet:
        # No additional content appeared. Abort our loop.
        break

    page.execute_script(
        "window.scrollTo(0, arguments[0].scrollHeight);", contents)

相关问题 更多 >

    热门问题