I am using a Selenium to code python script to search and play a YouTube video.
This is my code:
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Defining video name
video_name = "4k art"
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.maximize_window()
wait = WebDriverWait(driver, 3)
presence = EC.presence_of_element_located
visible = EC.visibility_of_element_located
# Navigate to url with video being appended to search_query
driver.get('https://www.youtube.com/results?search_query={}'.format(str(video_name)))
# play the video
wait.until(visible((By.ID, "video-title")))
driver.find_element(By.ID, "video-title").click()
# Wait for video to end
So, everything works fine, but I would like to know what is the best way to have the script wait until the video is finished before finishing? I saw different ways to do so using YouTube API or using Selenium with elements appearing. Is there a preferred way to do it?
You could look for the replay button and if it comes up exit the loop
wait=WebDriverWait(driver,10)
While True:
try:
wait.until(EC.element_to_be_clickable((By.XPATH,"//button[#aria-label='Replay']")))
break
except:
pass
Imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
It depends on what functionality you are testing.
In case you don't care about actual GUI presentation and just wish to get indication that the video is finished and you can do it with some API - do it with API. This is much more fast and stable approach.
In case you need to test the actual video finished on the GUI - you should wait for the appropriate web element with Selenium.
In this case you can use the solution given by Arundeep
Related
I made a Python program that opens my Youtube playlist using Selenium and I want to close that browser when all video is watched.
(I tried using time.sleep() but the problem is Youtube ads).
So, is there any way I can close my browser automatically when all video is watched?
When the video is finished //div[#class='ytp-autonav-endscreen-button-container'] element appears so you can wait until this element appearing and then close the driver.
You can also simply locate it by the class name 'ytp-autonav-endscreen-button-container' or other buttons / elements inside it.
So after staring the video use
WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.ID, 'ytp-autonav-endscreen-button-container')))
where delay is time that will be enough to the video to finish.
Lear more about webdriver explicit wait conditions here
Don't forget to add the essential imports
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
I suggest to make in in steps.
First step:
Wait for the last video in playlist:
By text:
last_video = driver.find_element_by_css_selector("#secondary .index-message.style-scope.ytd-playlist-panel-renderer:nth-child(1)").text == "10 /10"
Or by waiting for the last element in the playlist directly:
last_video = driver.find_element_by_css_selector("#secondary #items>.style-scope.ytd-playlist-panel-renderer:last-of-type").get_attribute("selected")
Second step:
After the first condition is true, wait for this video to finish, with this locator (Replay button)
video_ends = driver.find_element_by_css_selector(".ytp-chrome-controls button[title=Replay]")
For this you'll need to import:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
And use it like this:
wait = WebDriverWait(driver, timeout_in_seconds)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#secondary .index-message.style-scope.ytd-playlist-panel-renderer:nth-child(1)").text == "10 /10")))
Timeout will depend of the length of playlist.
It is not a quick task, nobody will agree to finish it for you here.
Python/coding newb, beware!
Im writing a script to download from youtube from " https://ytmp3.cc/en13/ ". I had written a click script using pyautogui but the problem being that the download button appears anywhere betweeen 1 and 15 seconds of entering the link. So i wanted to re-code it in a Selenium window to dynamically wait until the button is visible and then continue with the click script. I have tried about 15 ways but cant get it to work
library blah :
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
ways i tried to get it to work:
without waits, results in NosuchElement Exception
def check_exists():
try:
while True:
a=driver.find_element(By.LINK_TEXT, "Download")
a.click()
except NoSuchElementException:
time.sleep(10)
the syntax of this is most probably wrong
i tried a couple different variations of implicit and explicit waits but couldnt get it to work. Is there some javascript on the site linked above thats messing with my code?
in a separate .py, running
#driver.find_element(By.LINK_TEXT, "Download").click()
#either the line above or below works at finding the element, and clicking it
driver.find_element_by_link_text("Download").click()
I just need help getting the line above ^ into an explicit wait, but i dont have the language knowledge of how to do it yet. i would appreciate some help, thanks in advance!
You can use webdriver wait to wait until button is displayed. Tried the below code which works for me
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
video_path = "your_video_path"
waitTime=10
driver = webdriver.Chrome("./chromedriver.exe")
driver.get("https://ytmp3.cc/")
element = driver.find_element_by_id("input")
element.send_keys(video_path)
driver.find_element_by_id("submit").click()
try:
# wait 10 seconds before looking for element
element = WebDriverWait(driver, waitTime).until(
EC.presence_of_element_located((By.LINK_TEXT,"Download"))
)
driver.find_element_by_link_text("Download").click()
finally:
print(driver.title)
You can update your required wait time in waitTime variable in seconds so if the value is 10 selenium will wait and check for elements upto 10 seconds
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox(executable_path='/home/geckodriver')
driver.get('https://web.whatsapp.com/')
#function to check weather qr code is scanned or not
Hello, I am trying to write a function to "wait" until the user actually scans QR code, i.e return True if he is logged in and False if he is not. I checked how it's done in the network tab, basically it is a POST to WhatsApp then User is logged in.
if there is another way to do this, I am all ears.
Use WebDriverWait() with expected_conditions.invisibility_of_element_located():
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait(driver, 60).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'landing-window')))
I want to search and play a video using Selenium in Python.
Here is the code:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(www.youtube.com)
wait = WebDriverWait(driver, 3)
presence = EC.presence_of_element_located
visible = EC.visibility_of_element_located
# Search for the video.
time.sleep(1)
wait.until(visible((By.NAME, "search_query")))
driver.find_element_by_name("search_query").click()
driver.find_element_by_name("search_query").send_keys(video)
driver.find_element_by_id("search-icon-legacy").click()
# Play the video.
wait.until(visible((By.ID, "video-title")))
driver.find_element_by_id("video-title").click()
But the problem is, it plays the first video on the home page before it completes searching.
Can you guys suggest how to play the video?
You could bypass the need of starting off at the homepage completely by appending the desired search query to the search_query parameter :)
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.maximize_window()
wait = WebDriverWait(driver, 3)
presence = EC.presence_of_element_located
visible = EC.visibility_of_element_located
# Navigate to url with video being appended to search_query
driver.get('https://www.youtube.com/results?search_query={}'.format(str(video))
# play the video
wait.until(visible((By.ID, "video-title")))
driver.find_element_by_id("video-title").click()
Following is the code which im trying to run
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import os
import time
#Create a new firefox session
browser=webdriver.Firefox()
browser.maximize_window()
#navigate to app's homepage
browser.get('http://demo.magentocommerce.com/')
#get searchbox and clear and enter details.
browser.find_element_by_css_selector("a[href='/search']").click()
search=browser.find_element_by_class_name('search-input')
search.click()
time.sleep(5)
search.click()
search.send_keys('phones'+Keys.RETURN)
However, im unable to submit the phones using send_keys.
Am i going wrong somewhere?
Secondly is it possible to always use x-path to locate an element and not rely on id/class/css-selections etc ?
The input element you are interested in has the search_query class name. To make it work without using hardcoded time.sleep() delays, use an Explicit Wait and wait for the search input element to be visible before sending keys to it. Working code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Firefox()
browser.maximize_window()
wait = WebDriverWait(browser, 10)
browser.get('http://demo.magentocommerce.com/')
browser.find_element_by_css_selector("a[href='/search']").click()
search = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "search-query")))
search.send_keys("phones" + Keys.RETURN)