alecxe alecxe - 4 years ago 249
Python Question

Getting current video tag URL with selenium

I'm trying to get the current html5 video tag URL using selenium (with python bindings):

from selenium import webdriver


driver = webdriver.Chrome()
driver.get('https://www.youtube.com/watch?v=9x6YclsLHN0')

video = driver.find_element_by_tag_name('video')
url = driver.execute_script("return arguments[0].currentSrc;", video)
print url

driver.quit()


The problem is that the
url
value is printed empty
. Why is that and how can I fix it?




I suspect that this is because the script is executed and the
currentSrc
value is returned before the video tag has been initialized. I've tried to add an Explicit Wait, but still got an empty string printed:

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

wait = WebDriverWait(driver, 5)
video = wait.until(EC.visibility_of_element_located((By.TAG_NAME, 'video')))


Which makes me feel I need to do it asynchronously. May be listening for the media events and wait for the
video
to start playing.

I'm also pretty sure
currentSrc
should work, because if I execute the code in the console and manually wait for a video to start - I see it printing the video
currentSrc
attribute value.




FYI, also tried with java bindings, same result, an empty string:

WebDriver driver = new ChromeDriver();
driver.get("https://www.youtube.com/watch?v=9x6YclsLHN0");

WebElement video = driver.findElement(By.tagName("video"));

JavascriptExecutor js = (JavascriptExecutor) driver;
String url = (String) js.executeScript("return arguments[0].currentSrc;", video);

System.out.println(url);

Answer Source

According to the W3 video tag specification:

The currentSrc DOM attribute is initially the empty string. Its value is changed by the resource selection algorithm.

Which explains the behavior described in the question. This also means that to get the currentSrc value reliably, we need to wait until the media resource has it defined.

Subscribing to the loadstart media event through execute_async_script() did the trick:

driver.set_script_timeout(10) 

url = driver.execute_async_script("""
    var video = arguments[0],
        callback = arguments[arguments.length - 1];

    video.addEventListener('loadstart', listener);

    function listener() {
        callback(video.currentSrc);
    };
""", video)
print(url)
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download