Youtube + Selenium ChromeDriver (Python) - 如何知道视频何时结束?

Youtube + Selenium ChromeDriver (Python) - How to know when a video ends?

[编辑:已解决,请参阅问题文本的中途]

关于理解其中播放视频的 Youtube 页面内容的快速问题:

总结

我使用 Selenium 在 Youtube 上播放视频,作为基于浏览器的 GUI 的一部分。

我需要知道视频何时播放完毕,以便 GUI 执行其他操作(例如将本地 HTML 馈送到浏览器)。

代码段和问题

import os, time
from selenium import webdriver

# [...]
chromedriver = 'path_to_chromedriver_binary'  # substitute as appropriate
driver = webdriver.Chrome(chromedriver)
youtube_link = 'https://www.youtube.com/watch?v=somevideo'
driver.get(youtube_link)

至此,我可以time.wait()视频的长度。

但是,我想知道我是否可以通过 Selenium 驱动程序查询 YouTube 页面并在 while 循环中计算剩余播放时间(我不熟悉如何从 youtube 页面提取此信息)

谢谢!

[用解决方案编辑]

硒溶液

感谢 Stanjer,感谢 this answer and this other answer,您可以通过此方法获得 movie_player 状态:

player_status = driver.execute_script("return document.getElementById('movie_player').getPlayerState()")

(别忘了在脚本开头加上"return")

Selenium 替代解决方案

不够优雅但值得指出: driver.text returns 表示此字符串格式 '1:00 / 2:00' 中的视频计时器的字符串。因此,您可以通过以下方式检查视频是否播放完毕:

video_is_playing = True
while video_is_playing:
    time.sleep(1)
    video_is_playing = not(driver.text[:4] == driver.text[-4:])

[编辑] 根据 Jose 的评论,此信息也可以通过以下方式访问:

driver.find_element_by_class_name("ytp-time-current").text

并发症和下一个问题

我需要以最大化格式打开视频,并自动播放。

这意味着我调用以下 url:

youtube.com/v/<video_code>?rel=0&autoplay=1

但是这个 returns 非常短 html 只包含一个嵌入代码,如这里的示例所示:

<HTML><HEAD></HEAD>
    <BODY leftMargin=0 scroll=no topMargin=0>
        <EMBED height="100%" 
        type=application/x-shockwave-flash 
        width="100%" 
        src=https://www.youtube.com/v/Fsc-oT9PsSQ?rel=0&amp;autoplay=1
        fullscreen="yes">
    </BODY>
</HTML> 

所以我这里没有 movie_player 元素。

方法 1 - 我可以从 application/x-shockwave-flash 中提取计时器吗?

方法 2 - 如果我在经典 Youtube 页面中启动 youtube 视频,我如何让 movie_player 最大化自己?

(注意:this answer and this answer 可能包含解决方法 2 的信息,post 如果我让它与 Selenium 一起工作,将会 post)

您可以在 youtube 视频页面的上下文中执行 javascript API:

youtubePlayer = document.getElementById("movie_player");
youtubePlayer.getPlayerState();

所以根据https://developers.google.com/youtube/js_api_reference?csw=1

state == 0 是视频结束时

您可以在循环中添加一个执行程序,每 N 秒检查一次状态。

您还可以使用 Youtube iFrame API 的 'onStateChange' 功能在状态发生变化时进行打印。

function onPlayerStateChange(event) {
      console.log(player.getPlayerState());     // 1 = Playing || 2 = Paused || 3 = <<- O ->> || 0 = Finished.
  }

您可以将视频的长度和当前播放时间作为文本获取,然后将它们转换为秒。另外,作为一个循环,您可以等到当前时间达到视频的长度。

length_str = driver.find_element_by_class_name("ytp-time-duration").text
current_time_str = driver.find_element_by_class_name("ytp-time-current").text

import re
length = re.findall(r'\d+', length_str) # convert ['2:24'] to ['2', '24']
current_time = re.findall(r'\d+', current_time_str)

length_sec = 60 * int(length[0]) + int(length[1])
current_time_sec = (60 * int(current_time[0]) + int(current_time[1]))
remaining_time = length_sec - current_time_sec
driver.find_element_by_class_name("ytp-time-current").text

它只在屏幕上显示时间和标题时有效。几秒钟后,标题消失,返回值为“”。

还有一个办法。只需添加等待 Replay 按钮:

video_ends = driver.find_element_by_css_selector(".ytp-chrome-controls button[title=Replay]")

在 Chrome 工作。