问题
I am trying to click the Ask to join button in a google meet link(using my existing Google Chrome profile).This is the code:
options = webdriver.ChromeOptions()
options.add_argument(r"--user-data-dir=C:\\Users\\Pranil.DESKTOP-TLQKP4G.000\\AppData\\Local\\Google\\Chrome\\User Data")
browser = webdriver.Chrome(ChromeDriverManager().install(), options=options)
delay = 15
browser.get('https://meet.google.com/tws-kcie-aox')
ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
time.sleep(5)
join_butt = WebDriverWait(browser, delay ,ignored_exceptions=ignored_exceptions).until(EC.presence_of_element_located((By.XPATH, '//*[@id="yDmH0d"]/c-wiz/div/div/div[5]/div[3]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div')))
join_butt.click()
print(join_butt.text)#this prints Ask to join
But the join button is not getting clicked. The most weird part 'Ask to join' text on the button does get printed in the last line. This means that selenium has reached the correct button. But still why does it not click the button?
EDIT: According to an answer by @Alin Stelian I updated the code as follows:
browser.get('https://meet.google.com/hst-cfck-kee')
browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 'd')
join_butt = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.XPATH, "//span[contains(text(),'Ask to join')]")))
join_butt.click()
print(join_butt)
print(join_butt.text)
This does work as both the print statements work...But the button isn't getting clicked. What is going wrong over here?
回答1:
For further automating projects - avoid finding elements by id when the value is generated programmatically - it will not help you. Also, long xpaths is bad for your project performance.
The performance level of locators is -> ID, CSS, XPATH.
join_butt = WebDriverWait(browser, delay ,ignored_exceptions=ignored_exceptions).until(EC.presence_of_element_located((By.XPATH, '//span[contains(text(),'Ask to join')]')))
later edit next time don't ignore exceptions - it will help you to see your error syntax, I tested myself the below code.
join_butt = WebDriverWait(browser, delay).until(
EC.presence_of_element_located((By.XPATH, "//span[contains(text(),'Ask to join')]")))
driver.execute_script("arguments[0].click();", join_butt)
If the chrome browser doesn't allow you to log in - here is a trick
- Run your code
- In that browser go to StackOverflow
- Login w/ your account
- Quit the browser
- Run again your code - now you'll be logged in automatically in your google account.
回答2:
You can use the quickest path
//span[contains(text(),'Ask to join')]
or from your code correct xpath
//*[@id="yDmH0d"]/c-wiz/div/div/div[4]/div[3]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div/span/span
your xpath in the Code
//*[@id="yDmH0d"]/c-wiz/div/div/div[5]/div[3]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div
回答3:
When using Selenium for website that you don't own, NEVER rely on IDs or classes since they often change, especially for google's websites.
Best way to search for it is to find the element that presents the text that you know is wrote on the button (in this case Ask to join) and then get all the parents in a loop and check if some of them are buttons.
Like this:
WebElement buttonTextElement = browser.find_elements_by_xpath("//*[contains(text(), 'Ask to join')]")
then launch this javascript code in a cycle and stop it only if parent role attribute is equal to "button" or tag is "button"
WebElement parent = buttonTextElement;
WebElement parent = browser.execute_script("return arguments[0].parentNode;", parent)
Then click().
I've wrote for u a fully working code in Java. I've used chromedriver version 85.
I shouldn't paste a whole code, but i'll do it for u :)
I saw that "Next" Button is the first parent so you don't need to go recursive. PS: Since i visited the italian webpage, make sure that the strings "Next" and "Ask to Join" are right char for char. Change them if u need to.
import java.util.ArrayList;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String email = "Your Google Email";
String pass = "Your Google Password";
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
ChromeOptions options = new ChromeOptions();
// You need this to stop the page from askin u for mic
options.addArguments("--use-fake-ui-for-media-stream");
WebDriver driver = new ChromeDriver(options);
//Login to Google
driver.get("https://accounts.google.com/login");
ArrayList<WebElement> emailinput = new ArrayList<WebElement>();
ArrayList<WebElement> spans = new ArrayList<WebElement>();
emailinput = (ArrayList<WebElement>) driver.findElements(By.tagName("input"));
//Get all spans in page
spans = (ArrayList<WebElement>) driver.findElements(By.tagName("span"));
for(int i = 0; i < emailinput.size(); i++) {
if(emailinput.get(i).getAttribute("type").equals("email")) { emailinput.get(i).sendKeys(email); break; }
}
for(int i = 0; i < spans.size(); i++) {
if(spans.get(i).getText().equals("Next")) {
WebElement parent = (WebElement) ((JavascriptExecutor) driver).executeScript(
"return arguments[0].parentNode;", spans.get(i)); parent.click(); break; }
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ArrayList<WebElement> passinput = (ArrayList<WebElement>) driver.findElements(By.tagName("input"));
for(int i = 0; i < passinput.size(); i++) {
if(passinput.get(i).getAttribute("type").equals("password")) { passinput.get(i).sendKeys(pass); break; }
}
spans = (ArrayList<WebElement>) driver.findElements(By.tagName("span"));
for(int i = 0; i < spans.size(); i++) {
if(spans.get(i).getText().equals("Next")) {
WebElement parent = (WebElement) ((JavascriptExecutor) driver).executeScript(
"return arguments[0].parentNode;", spans.get(i)); parent.click(); break; }
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Create a Meet room and put here its URL
driver.navigate().to("https://meet.google.com/dxz-dbwt-tpj");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
spans = (ArrayList<WebElement>) driver.findElements(By.tagName("span"));
for(int i = 0; i < spans.size(); i++) {
if(spans.get(i).getText().equals("Ask to Join")) {
WebElement parent = (WebElement) ((JavascriptExecutor) driver).executeScript(
"return arguments[0].parentNode;", spans.get(i)); parent.click(); break; }
}
}
}
回答4:
To print the text Ask to join you need to induce WebDriverWait for the visibility_of_element_located()
and you can use the following Locator Strategy:
Using XPATH and
get_attribute()
:print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//span[text()='Ask to join']"))).get_attribute("innerHTML"))
Using XPATH and text attribute:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//span[text()='Ask to join']"))).text)
You can find a relevant discussion in How to retrieve the text of a WebElement using Selenium - Python
To click on the element with text Ask to join you need to induce WebDriverWait for the element_to_be_clickable()
and you can use the following Locator Strategy:
Using
XPATH
:WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "//span[text()='Ask to join']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC
Outro
Link to useful documentation:
- get_attribute() method
Gets the given attribute or property of the element.
- text attribute returns
The text of the element.
- Difference between text and innerHTML using Selenium
来源:https://stackoverflow.com/questions/63873200/how-to-click-on-the-ask-to-join-button-within-https-meet-google-com-using-sele