From this page: https://www.realestate.com.kh/buy/, which looks like this in the inspector:
I'm trying to extract all elements of class css-1uuzwjq eq4or9x0 into a list in order to click on the elements and further explore.
I have this code, in which I try to get the elements by their Xpath:
ads = browser.find_elements_by_class_name('css-1uuzwjq eq4or9x0')
for ad in ads:
ad.click()
However, the list always ends up empty. What am I doing wrong?
class attribute holds multiple classes , each class is separated by space. In your case, 'css-1uuzwjq eq4or9x0' are two classes not one
you can find it as :#
xpath
in xpath it validates the class attribute value is exactly the same
//*[#class="css-1uuzwjq eq4or9x0"]
CSS
in css it checks for element that contains both the mentioned class, each class should be mentionedwith a dot
.css-1uuzwjq.eq4or9x0
if you want exact match , use the below locator as it checks the class attribute value to be exact
[class="css-1uuzwjq eq4or9x0"]
using class locator
browser.find_elements_by_class_name('css-1uuzwjq.eq4or9x0')
calss locator uses css locator under the hood , so when you pass a class name, it just adds 'dot' in front of it . so to make it a valid locator pass all classes by replacing space with dot
//div[#class='list']/div[./header[contains(#class,'featured')]]
I would use this xpath to obtain all the divs needed to search.
use /div/header/a if you want the a tag to click.
So it would be
driver.get('https://www.realestate.com.kh/buy/')
hrefs=[x.get_attribute('href') for x in driver.find_elements(By.XPATH,"//div[#class='list']/div/header/a")]
print(hrefs)
for href in hrefs:
driver.get(href)
Would retrieve all the hrefs to loop and will prevent using driver.back() and all the stale elements you will get.
I would not recommend getting by class name because they seem dynamic also those are multiple class names which are grabbed by a css selector.
css-1uuzwjq eq4or9x0 -> .css-1uuzwjq.eq4or9x0
Related
I'm trying to learn more about how Selenium works with VBA and I'm trying to do somethings about the trendings behaviors of ecommerce nowadays.
In this case, I don't know how works the FindelementByclass when it has special characters like _ or - inside, because it always gives me empty result and I need to identify it because I want to go through every class called as it.
<span class="minificha__sku ng-binding">Cód TG: AS0-322</span>
space in class means it has two classes,
class="minificha__sku ng-binding"
means it has "minificha__sku" and "ng-binding" , so use xpath or css instead of byclass or use either of the two class not two
css:
span[class="minificha__sku ng-binding"]
xpath
//span[#class="minificha__sku ng-binding"]
To identify the element you can use either of the following Locator Strategies:
Using FindElementByClassName I:
bot.FindElementByClassName("minificha__sku")
Using FindElementByClassName II:
bot.FindElementByClassName("ng-binding")
Using FindElementByCss:
bot.FindElementByCss("span.minificha__sku.ng-binding")
Using FindElementByXPath:
bot.FindElementByXPath("//span[#class='minificha__sku ng-binding']")
I need to write the location of an element in page which has just the tag name and only 1 attribute - class and the class value has number characters which is dynamic so I have to use contains to specify the element.
Could not traverse from parent node as it is a list with similar parent name.
Any Suggestions please??
You can use the Selector.withAttribute method.
For example, the following code finds an input with an attribute, which name ends with 'testId' and clicks on it.
await t.click(Selector('input').withAttribute(/.*testid/);
I am using Selenium WebDriver and I have number of items on a page and each item on page is a separate form type.
I have saved all of these form elements in a list and I am iterating over every item in an attempt to get the name of the element by using the "alt" attribute.
However when I try to get the "name" attribute from the input element it is always returning the first input tag found on that page, not the name attribute of the element I have currently selected.
The syntax I am using is:
((Webdriver imgtags.get(i)).findelement(By.xpath("//input[#name='qty']")).sendKeys ("100");
I have also tried to get the id from the tag by using:
((Webdriver imgtags.get(i)).getAttribute("id");
It's returning a blank value, but it should return the value of the id attribute in that input tag.
I also tried to get the id by using .bytagname but as id is an attribute it is not accessible
Try:
(driver) findElement(By.xpath("//*[contains(local-name(), 'input') and contains(#name, 'qty')]")).sendKeys("100");
To answer the comment by #rrd: to be honest, I have no idea why OP uses ((Webdriver imgtags.get(i)). I don't know what that is. Normally, I just use driver.findElement[...]
Hoping that he knows what works in his framework :D
Selenium Xpath handling is not fully compliant and it does not always treat // as a synonym of descendant-or-self.
Instead try tweaking your code to use the following Xpath:
((Webdriver imgtags.get(i)).findElement(By.xpath("./descendant-or-self::input[#name='qty']")).sendKeys("100");
This will base your search off the currently selected WebElement and then look for any descendants that have a name attribute with a value of "qty".
I would also suggest storing your imgtags array as an array of WebElement e.g.
List<WebElement> imgtags = new ArrayList<>();
This is a much better idea than casting to WebDriver to be able to use .findElement(). This will cause you problems at some point in the future.
If a class name changes all the time, but a column is always there.
how to navigate RFW to 2nd row and 6 column?
(instead of class name)
https://www.investing.com/equities/pre-market
In ROBOT Framework, you can access the element by several ways. See http://robotframework.org/Selenium2Library/Selenium2Library.html . See section 'Locating elements".
The most common way is by id, name, class, xpath and css_selectors. So, let's assume that it is not possible to get locator by id, name & class due its dynamically changes during page load. So, we will use absolute xpath expressioin for this solution.
In xpath, you can access the node either by i) relative xpath or ii) absolute xpath.
If the class or id are dynamic and keep changing, then just use it's absolute xpath.
Before that, it is highly recommended if you install an add-on in your web browser for checking/inspecting the xpath element/expression. For firefox, just install 'ChroPath' extension.
The absolute xpath expression below will return a single matching node for ROW=2, COLUMN=6..
/html[1]/body[1]/div[5]/section[1]/div[6]/table[1]/tbody[1]/tr[2]/td[6]
The absolute xpath expression below will return all matching nodes for all rows, COLUMN=6..
/html[1]/body[1]/div[5]/section[1]/div[6]/table[1]/tbody[1]/tr/td[6]
Then, in ROBOT Framework, you can access this element like below..
${xpath}= Set Variable /html[1]/body[1]/div[5]/section[1]/div[6]/table[1]/tbody[1]/tr[2]/td[6]
Wait until Page Contains Element xpath=${xpath}
${output} = Get Text xpath=${xpath} #if you want the text of this column.
Click Element xpath=${xpath} #This will simply click the element
I am not able to find the element using "id" in selenium as the id is randomly changing in every session of execution so the same id i am not getting in next execution.
As there is no other unique property is there to identify the element.
code sample
You didn't specify a language so I'm going to give you Java. You can do this by using the CSS class or probably a better choice (because of likely uniqueness) is data-lynx-name.
By CSS class
driver.findElement(By.cssSelector("div.http-lynx-json-org-text-input"));
By attribute
driver.findElement(By.cssSelector("div[data-lynx-name='username']"));
You really should read the question that I duped this one to:
Find element by attribute
Also read more about CSS selectors,
http://www.w3.org/TR/selectors/#selectors
You can use XPath.
String xpath = //div[#data-lynx-name='usernameLabel'][text='User ID']/following-sibling::div[1]
The above XPath will will find the div tag containing text 'User ID' and finds the next div which is is the required textbox.
It seems that you can even use the attribute 'data-lynx-name' attribute of the textbox div tag directly.
String xpath = //div[#data-lynx-name='username']
Selenium
driver.findElement(By.xpath(xpath));