我正在尝试使用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=' ')
这是我得到的输出。如何获得该页面上的所有评论???任何人都可以帮助我。
Being a sucessful phyton freelancer really mean to me because if I able to make $2000 in month I can really help my family financial, improve my skill, and have a lot of time to refreshing. So thanks Qazi, you really help me :D
Traceback (most recent call last):
File "C:\Python36\programs\Web scrap\YT_Comm.py", line 19, in <module>
print(comm1[i].text,end=' ')
IndexError: list index out of range
答案 0 :(得分:5)
IndexError
表示您正在尝试访问列表中不存在的位置。您正在迭代元素列表(comm1
)50次,但列表中的元素少于50个,因此最终您尝试访问不存在的索引。
表面上,你可以通过改变你的迭代来解决你的问题,以完全循环列表中存在的元素 - 不多也不少:
for element in comm1:
print(element.text, end=‘ ‘)
但这会让你遇到为什么你的列表少于50个元素的问题。你正在搜索的视频有超过90条评论。为什么你的清单没有全部?
如果您查看浏览器中的页面,您会看到评论使用infinite scroll技术逐步加载:当用户滚动到文档底部时,另一个&#34 ;页面&#34;获取和呈现注释,增加文档的长度。要加载更多注释,您需要触发此行为。
但是根据评论的数量,一次提取可能还不够。为了触发所有内容的获取和呈现,您需要:
我们已经知道通过滚动到内容容器的底部(带有id
#contents
的元素)来获取其他内容,所以让我们这样做:
driver.execute_script(
"window.scrollTo(0, document.querySelector('#contents').scrollHeight);")
(注意:由于内容位于absolute
- 定位元素中,document.body.scrollHeight
将始终为0
,并且不会触发滚动。)
但与任何浏览器自动化一样,我们正在与应用程序竞争:如果内容容器尚未呈现,该怎么办?我们的卷轴会失败。
Selenium提供WebDriverWait()
来帮助您等待应用程序处于特定状态。它还通过其expected_conditions
模块提供一组等待的常见状态,例如元素的存在。我们可以使用这两个来等待内容容器出现:
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")))
在较高级别,我们可以通过以下方式确定是否提取了其他内容:
在我们的容器中(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")
使用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)