Find xpath or something similar (=identifier) on web page - python

I am trying to click on a place on a video. I tried it with xpath already, but without success.
For example on this tiktok video: https://www.tiktok.com/#willsmith/video/7125844820328926510?is_from_webapp=v1&item_id=7125844820328926510&web_id=7139992072584676869
I'm trying to click on the heart with selenium (python).
That's my code:
if driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[2]/div[1]/div[3]/div[1]/div[1]/div[3]/button[1]/span/div/svg/g/path") :
driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[2]/div[1]/div[3]/div[1]/div[1]/div[3]/button[1]/span/div/svg/g/path").click()
It says that it's "Unable to locate element". I don't know why. I even added some sleep to the code because I thought that the website didn't load up fully or even tried with a different xpath.
I also tried to do it with the ID of the "heart-location" but the ID is very hard to understand if I inspect element.
Could someone please help me out? Thanks in advance!

You need to use the correct locator
And to wait for the element to be clickable.
For the former WebDriverWait Expected Conditions explicit wait should be used.
The below code works:
(In case you are already logged in)
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
options = Options()
options.add_argument("start-maximized")
webdriver_service = Service('C:\webdrivers\chromedriver.exe')
driver = webdriver.Chrome(service=webdriver_service, options=options)
url = "https://www.tiktok.com/#willsmith/video/7125844820328926510?is_from_webapp=v1&item_id=7125844820328926510&web_id=7139992072584676869"
driver.get(url)
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span[data-e2e='like-icon']"))).click()
In case you want to use XPath instead of CSS Selector just change the line above with
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[#data-e2e='like-icon']"))).click()

Related

Possible security feature that disables automation?

I am making a Python script with the Selenium Chrome Webdriver to automate this website: https://nordicwellness.se/logga-in/?redirecturl=/mina-sidor/ (it's a Swedish website).
I am trying to automate the login process but I keep getting errors such as:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
and
Keyboard not reachable
I am using the following code to locate the email input field and password input field:
emailInp = driver.find_element(By.XPATH, '//*[#id="UserName"]').send_keys('test')
passwordInp = driver.find_element(By.XPATH, '//*[#id="Password"]').send_keys('123')
I've tried passing multiple options and even used the WebDriverWait function, even tried Firefox and Safari, but nothing seems to work.
Is it possible that the website has some kind of security feature that doesn't allow automated scripts? If so, is there a way to bypass it?
You are using not unique locators. There are 3 elements matching //*[#id="UserName"] and //*[#id="Password"] locators.
Locators should be always unique. In this case you need to take in account the unique parent element to make locators unique.
The following code works:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
options = Options()
options.add_argument("start-maximized")
webdriver_service = Service('C:\webdrivers\chromedriver.exe')
driver = webdriver.Chrome(options=options, service=webdriver_service)
wait = WebDriverWait(driver, 10)
url = "https://nordicwellness.se/logga-in/?redirecturl=/mina-sidor/"
driver.get(url)
wait.until(EC.element_to_be_clickable((By.XPATH, "//main//input[#id='UserName']"))).send_keys('test')
wait.until(EC.element_to_be_clickable((By.XPATH, "//main//input[#id='Password']"))).send_keys('123')
The result screenshot is:
I believe it is due to your XPath. If you inspect the web elements in the page itself, there are actually 3 elements matched the XPath you entered //*[#id="UserName"]. Without specifying, Selenium will always match the first return element. Which is hidden in the top menu. This is why you get the error of element not interactable.
A quick solution is to use the direct full XPath as per below :
emailInp = driver.find_element(By.XPATH, '/html/body/div[1]/main/div/div/div/form/input[1]').send_keys('test')
passwordInp = driver.find_element(By.XPATH, '/html/body/div[1]/main/div/div/div/form/input[2]').send_keys('123')
Or you need to specifically filter out which //*[#id="UserName"] you trying to access, for an example :
emailInp = driver.find_element(By.XPATH, '//main//*[#id="UserName"]').send_keys('test')
passwordInp = driver.find_element(By.XPATH, '//main//*[#id="Password"]').send_keys('123')

How to click login button?

I can't get the code to click the "Login to Facebook" button, I tried without success:
Link
wait.until(EC.element_to_be_clickable((By.XPATH, "/html[1]/body[1]/div[1]/div[1]/div[2]/div[1]/div[2]/ div[1]/div[1]/div[1]/div[2]/div[1]/div[1]/span[1]/div[1]/div[1]/div[1]" ))).click()
Try to use relative XPATH instead of Full XPATH, It will be more accurate.
Or if possible try to share screenshot of element you are trying to access.
I found This XPATH. Hopefully it will work.
driver.find_element(By.XPATH,"//form[#class='_9vtf']/div[2]/button").click()
You should never use long absolute XPaths or CSS Selectors. Locators should be short and unique.
The following code works:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
options = Options()
options.add_argument("start-maximized")
webdriver_service = Service('C:\webdrivers\chromedriver.exe')
driver = webdriver.Chrome(service=webdriver_service, options=options)
url = 'https://business.facebook.com/creatorstudio/home'
driver.get(url)
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.XPATH, "//div[contains(text(),'Facebook login')]"))).click()
wait.until(EC.element_to_be_clickable((By.ID, "email"))).send_keys("my#email.com")
wait.until(EC.element_to_be_clickable((By.ID, "pass"))).send_keys("my_psw")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[name='login']"))).click()
UPD
Instead of "//div[contains(text(),'Entrar no Facebook')]" try "//font[contains(text(),'entrar no Facebook')]" - the first word not capitalized and font tag instead of div. This is what I see when I translate it to Portugues

selenium find_element_by_css_selector for the long class name

I have tried multiple times with other instruction codes with space from the tutorial which worked fine. However, when I just changed the URL and the following class, it would give the error saying
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified
(Session info: chrome=100.0.4896.88)
Everything worked when I used the tutorial code.
Here is my code (I have solved a few chrome driver problems from the internet)
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-logging"])
driver = webdriver.Chrome(options=options)
driver.get("https://raritysniper.com/nft-drops-calendar")
time.sleep(1)
link = driver.find_element_by_css_selector(".w-full.h-full.align-middle.object-cover.dark:brightness-80.dark:contrast-103.svelte-f3nlpp").get_attribute("alt")
print(link)
I am trying to get attributes of each projects and make them into csv.
(Please refer to the screenshot)
Screen shot of HTML that I am trying to extract
it would be wonderful if anyone could depict the problem I got with the code.
Thank you!
The CSS_SELECTOR that you are using
.w-full.h-full.align-middle.object-cover.dark:brightness-80.dark:contrast-103.svelte-f3nlpp
does not really match any element in the HTML.
Instead, you should use this CSS_SELECTOR:
div.w-full.h-full.align-middle img:not(.placeholder)
In code:
driver.maximize_window()
wait = WebDriverWait(driver, 30)
driver.get("https://raritysniper.com/nft-drops-calendar")
#time.sleep(1)
first_element = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.w-full.h-full.align-middle img:not(.placeholder)")))
print(first_element.get_attribute('alt'))
print(first_element.get_attribute('src'))
Import:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Output:
NEON PLEXUS
https://media.raritysniper.com/featured/neon-plexus_1648840196045_3.webp
Process finished with exit code 0

Python 2.7 Selenium No Such Element on Website

I'm trying to do some webscraping from a betting website:
As part of the process, I have to click on the different buttons under the "Favourites" section on the left side to select different competitions.
Let's take the ENG Premier League button as example. I identified the button as:
(source: 666kb.com)
The XPath is: //*[#id="SportMenuF"]/div[3] and the ID is 91.
My code for clicking on the button is as follows:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
chrome_path = "C:\Python27\Scripts\chromedriver_win32\chromedriver.exe"
driver = webdriver.Chrome(chrome_path)
driver.get("URL Removed")
content = driver.find_element_by_xpath('//*[#id="SportMenuF"]/div[3]')
content.click()
Unfortunately, I always get this error message when I run the script:
"no such element: Unable to locate element:
{"method":"xpath","selector":"//*[#id="SportMenuF"]/div[3]"}"
I have tried different identifiers such as CCS Selector, ID and, as shown in the example above, the Xpath. I tried using waits and explicit conditions, too. None of this has worked.
I also attempted scraping some values from the website without any success:
from selenium import webdriver
from selenium.webdriver.common.by import By
chrome_path = "C:\Python27\Scripts\chromedriver_win32\chromedriver.exe"
driver = webdriver.Chrome(chrome_path)
driver.get("URL removed")
content = driver.find_elements_by_class_name('price-val')
for entry in content:
print entry.text
Same problem, nothing shows up.
The website embeddes an iframe from a different website. Could this be the cause of my problems? I tried scraping directly from the iframe URL, too, which didn't work, either.
I would appreciate any suggestions.
Sometimes elements are either hiding behind an iframe, or they haven't loaded yet
For the iframe check, try:
driver.switch_to.frame(0)
For the wait check, try:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, '-put the x-path here-')))

Selenium in Python expected conditions works with Firefox but not Chrome

I log into a private site and then wait for a link text to appear and then open the link with browser.get(). The code below throws a timeout exception almost every time while waiting for the link text "OTD" to appear. It is strange that it works once out of many tries. Even stranger is that if I use a sleep timer instead of the wait for expected condition, it works, but that is not what I want to use.
Here is the html:
<a target="_blank" href="/privateurl">OTD</a>
And here is the code that uses chromedriver:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import webbrowser
chrome_options = webdriver.ChromeOptions()
prefs = {'download.default_directory' : 'E:\\folder'}
chrome_options.add_experimental_option('prefs', prefs)
browser = webdriver.Chrome(chrome_options=chrome_options)
#browser.get('private url login page')
#enter login information and submit
wait = WebDriverWait(browser, 10)
wait.until(
EC.presence_of_element_located((By.LINK_TEXT, "OTD"))
)
browser.get('private url')
I have the same code, but for the Firefox driver and it works perfectly every time. I just need to use Chrome browser instead.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import webbrowser
profile = webdriver.FirefoxProfile()
profile.set_preference("browser.download.folderList", 2)
profile.set_preference("browser.download.dir", 'E:\\folder')
profile.set_preference("browser.download.useDownloadDir", True)
browser=webdriver.Firefox(profile)
#browser.get('private url login page')
#enter login information and submit
wait = WebDriverWait(browser, 10)
wait.until(
EC.presence_of_element_located((By.LINK_TEXT, "OTD"))
)
browser.get('private url')
What am I doing wrong in the code using the chromedriver that is making it throw a timeout exception?
There are a couple of things to address :
Finally as you are invoking click() on the WebElement so instead of the expected_conditions clause as presence_of_element_located() you should use the clause element_to_be_clickable(locator).
When you use expected_conditions clause as element_to_be_clickable(locator) the WebElement is returned back and you can directly invoke click() method on it.
Your optimized line of code will be :
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "OTD"))).click()
Update A
As per your comment update you are seeing the error :
'element_to_be_clickable' object has no attribute 'click'
An alternative would be to extract the href attribute and invoke get() as follows :
element = WebDriverWait(browser, 10).until(EC.visibility_of_element_located((By.LINK_TEXT, "OTD")))
attr_href = element.get_attribute("href")
driver.get(attr_href)
Update B
As per your comment update the idea of Selenium does interact with the element ... even though it is unable to attain visibility_of_element is not a full proof solution as :
The expected_conditions clause presence_of_element_located(locator) mentions :
class selenium.webdriver.support.expected_conditions.presence_of_element_located(locator)
An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
locator - used to find the element returns the WebElement once it is located.
Where as the expected_conditions clause visibility_of_element_located(locator) mentions :
class selenium.webdriver.support.expected_conditions.visibility_of_element_located(locator)
An expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0.
locator - used to find the element returns the WebElement once it is located and visible.
From Selenium perspective if an element is not displayed Selenium won't be interact with the element e.g. invoking click()

Categories