I am trying to click on a specific element that dynamically changes locations and therefore it changes xpaths and css selectors as well.
Tried xpath.
//*[#id="hld"]/div/div[X]/div[1]/h2/select
Note: The X will range from 2 to 10 depending on various factors.
There are no class names or IDs to use either. All I have to work with are the tag names.
My current code is as follows.
h2 = driver.find_element_by_tag_name("h2")
select = h2.find_element_by_tag_name("select")
select.click()
Unfortunately the select tag will load some time after the h2 tag, and I am trying to do a webdriverwait to wait until the element is clickable/visible before running the above code.
Sadly the proper syntax to single out the select element isn't clear to me. Below is the code to find the h2 tag, but I am trying to expand it out to focus in on the select tag.
WebDriverWait(driver, 30).until(
EC.visibility_of_element_located((By.TAG_NAME, "h2")))
Any help is greatly appreciated.
Try removing the dynamic div locator - the driver will iterate through the elements on the page and only click on it if it exists.
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.ui import WebDriverWait
xpath = ".//[#id="hld"]/div/div/div/h2/select"
timeout = 30
WebDrierWait(driver, timeout).until(ec.presence_of_element_located(By.XPATH))
driver.find_element_by_xpath(xpath).click()
Otherwise, if the driver is finding multiple xpaths that match your xpath, you could try something like:
elements = driver.find_elements_by_xpath(xpath)
for element in elements:
try:
element.click()
except ElementNotVisibleException:
pass
Related
I have this page and I want to click on the a element that sends an email(the one that is highlighted in the screenshot below
and I have tried to find this element using By.XPATH
email = driver.find_element(By.XPATH, "//a[contains(#class, 'email-old-32')]").click()
and By.CLASS_NAME
email = driver.find_element(By.CLASS_NAME, 'email-old-32').click()
and in both situations i'm getting an error no such element, does anyone know what am I doing wrong?
There are several possible thing that may cause this:
You need to wait for element to be loaded and to become clickable. WebDriverWait expected_conditions can be used for that.
If this is your case instead of email = driver.find_element(By.XPATH, "//a[contains(#class, 'email-old-32')]").click() try this:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.XPATH, "//a[contains(#class, 'email-old-32')]"))).click()
The element class attribute value can be dynamic. Make sure it is not changing. In case it does - you need to find another, stable locator for that element.
The element can be inside iframe. In this case you will need to switch into the iframe.
Possibly you opened a new tab where the goal element is presented but forget to switch to a new tab.
I'm trying to scrape a list from a website. There are two different lists, and one will load only after the first option is chosen. Issue is, I'm unable to select the first option. I scraped the list of all available options. But after writing it, I have to select it from the given option, and I'm unable to do so.
I've tried using browser.find_element_by_css_selector(....).click(), but it's showing the elementnotfound exception even after putting the proper wait condition. I think that's because it's unable to find that element.
browser.find_element_by_css_selector("#Brand_name").send_keys(company[i])
element= browser.find_element_by_css_selector("#Brand_name_selectWrap")
browser.implicitly_wait(5) # seconds
browser.find_element_by_css_selector("""#Brand_name_selectWrap > ul > li.selected""").click()
PS: Following is the link which I'm trying to scrape. I need all the mobiles listed company wide.
https://bangalore.quikr.com/Escrow/post-classifieds-ads/?postadcategoryid=227
Can someone kindly suggest some better way?
You can gather all options and their rel attributes into a dictionary and then loop that with appropriate wait conditions for the sublist to appear:
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
d = webdriver.Chrome()
d.get('https://bangalore.quikr.com/Escrow/post-classifieds-ads/?postadcategoryid=227')
options = {i.get_attribute('textContent'):i.get_attribute('rel') for i in d.find_elements_by_css_selector('#Brand_name_selectWrap .optionLists li:not(.optionHeading) a')}
input_element = d.find_element_by_id('Brand_name')
for k,v in options.items():
input_element.click()
input_element.send_keys(k)
selector = '[rel="' + v + '"]'
WebDriverWait(d, 3).until(EC.element_to_be_clickable((By.CSS_SELECTOR, selector))).click()
WebDriverWait(d, 2).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#Model_selectWrap.showCustomSelect")))
I created a dictionary that had all the options for mobiles in it. The keys were the actual text that would go in the input box and the values are the rel attribute values for those elements. Each option has a rel attribute. It means that I can input the phone name via the key so as to generate the dropdowns to select your mobile from possible values, then use the rel attribute in a css attribute = value selector to ensure I click on the right one
The rel attribute inside anchor tags (<a>) describes the relation to the document where the link points to.
The selector variable just hold the current css attribute = value selector for getting an mobile drop down option by its rel attribute value.
The element is covered by an other element so you'll need to use ActionChains to preform the click.
You'll needto import it:
from selenium.webdriver.common.action_chains import ActionChains
Then to click on the input only after that send_keys:
input_el = browser.find_element_by_css_selector('#Brand_name')
ActionChains(browser).move_to_element(input_el).click().perform()
It's a good practice to use WebDriverWait to validate your conditions:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
wait = WebDriverWait(browser, 15)
input_el = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#Brand_name")))
ActionChains(browser).move_to_element(input_el).click().perform()
I'm trying to gather price information for each product variation from this web page: https://www.safetysign.com/products/7337/ez-pipe-marker
I'm using Selenium and FireFox with Python 3 and Windows 10.
Here is my current code:
driver = webdriver.Firefox()
driver.get('https://www.safetysign.com/products/7337/ez-pipe-marker')
#frame = driver.find_element_by_class_name('product-dual-holder')
# driver.switch_to.frame('skuer5c866ddb91611')
# driver.implicitly_wait(5)
driver.find_element_by_id('skuer5c866ddb91611-size-label-324').click()
price = driver.find_element_by_class_name("product-pricingnodecontent product-price-content").text.replace('$', '')
products.at[counter, 'safetysign.com Price'] = price
print(price)
print(products['safetysign.com URL'].count()-counter)
So, I'm trying to start by just selecting the first product variation by id (I've also tried class name). But, I get an Unable to locate element error. As suggested in numerous SO posts, I tried to change frames (even though I can't find a frame tag in the html that contains this element). I tried switching to different frames using index, class name, and id of different div elements that I thought might be a frame, but none of this worked. I also tried using waits, but that return the same error.
Any idea what I am missing or doing wrong?
To locate the elements you have to induce WebDriverWait for the visibility_of_all_elements_located() and you can create a List and iterate over it to click() each item and you can use the following solution:
Code Block:
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
driver=webdriver.Firefox(executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
driver.get("https://www.safetysign.com/products/7337/ez-pipe-marker")
for product in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//form[#class='product-page-form']//div[#class='sku-contents']//following::ul[1]/li//label[starts-with(#for, 'skuer') and contains(., 'Pipe')]"))):
WebDriverWait(driver, 20).until(EC.visibility_of(product)).click()
driver.quit()
They may well be dynamic. Select by label type selector instead and index to click on required item e.g. 0 for the item you mention (first in the list). Also, add a wait condition for labels to be present.
If you want to limit to just those 5 size choices then use the following css selector instead of label :
.sku-contents ul:nth-child(3) label
i.e.
sizes = WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".sku-contents ul:nth-child(3) label")))
sizes[0].click()
After selecting size you can grab the price from the price node depending on whether you want the price for a given sample size e.g. 0-99.
To get final price use:
.product-under-sku-total-label
Code:
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
url = 'https://www.safetysign.com/products/7337/ez-pipe-marker'
driver = webdriver.Chrome()
driver.get(url)
labels = WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "label")))
labels[0].click()
price0to99 = driver.find_element_by_css_selector('.product-pricingnodecontent').text
priceTotal = driver.find_element_by_css_selector('.product-under-sku-total-label').text
print(priceTotal, price0To99)
# driver.quit()
Tried something like this in python unable I want to click on cross using Selenium.
driver.find_element_by_xpath("//span[contains(#onclick, 'parent.$WZRK_WR.closeIframe('60005','intentPreview');')]").click()
As per the HTML you have shared to click on the element depicted as X, first you need to induce WebDriverWait while switching to the <iframe> and again induce WebDriverWait for the desired element to be clickable and you can use the following solution:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#id='wiz-iframe-intent']")))
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='CT_Interstitial']//span[#class='CT_InterstitialClose']"))).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
Open below URL and Click on Add to Chrome button.
Xpath Helper- https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl?hl=en
Once plugin added to Chrome. Open your application/webpage and press SHIFT+CTRL+X. Black window will appear on top then you can play with xpath.
If xpath is invalid- then you will get xpath error and if no matches found then it will display NULL.
Note- To check element attribute still you can use F12 that is nothing but default inspect element for all browser then check attribute and create your own xpath and try.
Xpath Syntax
// tagname[#attribute-name=’value1′] and if you are not sure about tag name then no worry you can try with * also
//*[#attribute-name='value1']
You are dealing with an iframe. Follow below steps :
You'll need to switch control to iframe.
Then perform your action (in this case 'Click close').
Switch the control back to default frame.
You can try with this css_selector :
div.CT_InterstitialContents+span.CT_InterstitialClose[onclick]
Xpath would be :
//div[#class='CT_InterstitialContents']/following-sibling::span[#class='CT_InterstitialClose' and onclick]
Try to use this xPath:
//div[#id = 'contentDiv']/div/div/span[#class = 'CT_InterstitialClose']
Code:
close_btn = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//div[#id = 'contentDiv']/div/div/span[#class = 'CT_InterstitialClose']")))
close_btn.click()
Imports:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
Explanation:
WebDriverWait is used to wait until element will be clickable, and only then clicks on it. In this example WebDriverWait will wait at least 10 seconds until element will be clickable.
PS: as I see in the screenshot your element is probably in iframe. That means you have to switch to this iframe first, to be able to interact with the elements in it. The code sample for it would be like this:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, "XPATH_TO_FRAME")))
# do stuff
close_btn = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//div[#id = 'contentDiv']/div/div/span[#class = 'CT_InterstitialClose']")))
close_btn.click()
# switch back to default content
driver.switch_to.default_content()
You can write xpath using class name of span. Please refer an example below.
//span[#class='amountCharged']
the link is "https://www.psacard.com/smrpriceguide/baseball-card-values/1909-11-t206-white-border/1055/".
My question is: How I will get the index of the particular record of which Description contains "Carolina". Also how can I click the hyperlink(Shop) against that row. Please provide solution with python and selenium only.
With selenium, I usually use xpath searches. I suggest googling xpath, but here's a quick example for your case:
Find a div element who's text is exactly Carolina Brights:
//div[text()="Carolina Brights"]
in selenium:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
browser = webdriver.PhantomJS()
browser.implicitly_wait(10)
my_xpath = '//div[text()="Carolina Brights"]]'
my_div = WebDriverWait(browser, 10).until(
EC.visibility_of_element_located((By.XPATH, my_xpath))
)
my_div.click()
Obviously that particular div has no onClick so no point clicking it, but you get the idea ...