Second element on selenium chromedriver - python

When trying to automate our application, there are two div with same parameters.
I'm not able to find a way to recognize these. Please let me know what could be the other ways to identify these elements in selenium chromedriver in python.
I tried it, no it's doesn't work for me.
driver.find_element_by_xpath("(//div[#class='c3'])[2]/p").send_keys('text')
This is my html code
<div class="c3">
<p> test1 </p>
</div>
<div class="c3">
<p> test2 </p>
</div>
<div class="c3">
<p> test3 </p>
</div>
I want add my text after test2

Problem is the extra parentheses() / parentheses at wrong place in your xpath.
Correct xpath would be:
driver.find_element_by_xpath("//div[#class='c3'][2]/p").send_keys('text')
OR
driver.find_element_by_xpath("(//div[#class='c3']/p)[2]").send_keys('text')

Related

How to distinguish 2 button base on their parent/ancestor element in Selenium (PYTHON)?

<a href="/google.com">
<div> ABC </div>
<span>
<button class="btn"> Show more </button>
<span/>
</a>
<div>
<div>ABC</div>
<span>
<button class="btn"> Show more </button>
<span/>
</div>
As you guys see here, we have 2 BUTTONS and I need to click to BUTTON whose ancestor is not <a/> tag, because if I click to button whose ancestor is tag, it will redirect me to other pages. So I don't want this behaviour.
The obvious solution is I can use absolute Xpath for this, but it's not a good way because HTML DOM or css structure could be changed so it'
s not stable.
So how can I distinguish 2 button, using ancestor or something related? I mean other better ways.
Thank you guys for helping me so much!
To select a button that has no a tag ancestor can be done with the following XPath:
//button[not(ancestor::a) and(contains(.,'Show more'))]

Python Selenium Webdriver - Grab div after specified one

I am trying to use Python Selenium Firefox Webdriver to grab the h2 content 'My Data Title' from this HTML
<div class="box">
<ul class="navigation">
<li class="live">
<span>
Section Details
</span>
</li>
</ul>
</div>
<div class="box">
<h2>
My Data Title
</h2>
</div>
<div class="box">
<ul class="navigation">
<li class="live">
<span>
Another Section
</span>
</li>
</ul>
</div>
<div class="box">
<h2>
Another Title
</h2>
</div>
Each div has a class of box so I can't easily identify the one I want. Is there a way to tell Selenium to grab the h2 in the box class that comes after the one that has the span called 'Section Details'?
If you want grab the h2 in the box class that comes after the one that has the span with text Section Details try below xpath using preceding :-
(//h2[preceding::span[normalize-space(text()) = 'Section Details']])[1]
or using following :
(//span[normalize-space(text()) = 'Section Details']/following::h2)[1]
and for Another Section just change the span text in xpath as:-
(//h2[preceding::span[normalize-space(text()) = 'Another Section']])[1]
or
(//span[normalize-space(text()) = 'Another Section']/following::h2)[1]
Here is an XPath to select the title following the text "Section Details":
//div[#class='box'][normalize-space(.)='Section Details']/following::h2
yeah, you need to do some complicated xpath searching:
referenceElementList = driver.find_elements_by_xpath("//span")
for eachElement in referenceElementList:
if eachElement.get_attribute("innerHTML") == 'Section Details':
elementYouWant = eachElement.find_element_by_xpath("../../../following-sibling::div/h2")
elementYouWant.get_attribute("innerHTML") should give you "My Data Title"
My code reads:
find all span elements regardless of where they are in HTML and store them in a list called referenceElementList;
iterate all span elements in referenceElementList one by one, looking for a span whose innerHTML attribute is 'Section Details'.
if there is a match, we have found the span, and we navigate backwards three levels to locate the enclosing div[#class='box'], and find this div element next sibling, which is the second div element,
Lastly, we locate the h2 element from its parent.
Can you please tell me if my code works? I might have gone wrong somewhere navigating backwards.
There is potential difficulty you may encounter, the innerHTML attribute may contain tab, new line and space characters, in that case, you need regex to do some filtering first.

Selenium - driver.find_element_by_css_selector can't find the element (python)

I got a problem to use "find_element_by_css_selector" to get the element "Select" (a href).
I tried the methods below but all of them didn't work:
driver.find_element_by_css_selector("div.plan.right > a.select.").click()
driver.find_element_by_xpath("//div[#class='plan right']/div[2]/a/select").click()
Could anyone kindly give me some suggestions? Thanks!!
<div class="choose_plan">
<h1>Sign up now for <strong>UNLIMITED</strong> access <br/>to all </h1>
<div class="plans">
<div class="plan left">
<div class="head">
<p>MONTHLY</p>
</div>
<div class="body">
<p>annually</p>
</div>
<hr />
SELECT
</div>
<div class="plan right">
<img alt="Popular-right" class="popular" src="/assetse8.png" />
<div class="head">
<p>14</p>
</div>
<div class="body">
<p>Unlimited</p>
</div>
<hr />
SELECT
</div>
</div>
</div>
I know you already have an answer but there's a simple alternative that may be helpful in the future. From the HTML you provided, it looks like the data-planId attribute is unique for each A tag. You can take advantage of that using the code below.
driver.find_element_by_css_selector("a[data-planId='31']")
See this CSS Selector reference for more info.
It would help to have well formed HTML, as line 15 (<div class="choose_plan">) appears to be unclosed. This solution below was done with this line removed, but the rest of the HTML as shown. You can test online XPath here.
driver.find_element_by_xpath("//div[#class='plan right']/a").click()
yields the following:
Element='SELECT'
I would try to make it simple:
driver.find_element_by_css_selector("div.right a.select")
Or:
driver.find_elements_by_link_text("SELECT")[-1]
Here we are basically getting the last a element having SELECT text.

handling deeply nested tags in xpath

Please help me!
I don't know how to select deeply nested tag to select the text
inside of it.
If someone would please help me by saying, how to do it in a single line with
xpath query and please give me an explanation regarding the answer.
Below I have given a html code will anybody explain how to display the Hello world or whatever may be in that tags.
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<div class="deep">
<span>
<strong class="select">Hello world!</strong>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I assume since you asked for the text property the node you'd like to match is the strong tag (the only one with content).
If you are guaranteed only one <strong> tag from the document root and the level of nesting is irrelevant, the simplest xpath would be:
//strong/text()
To match via class specifically as well:
//strong[#class="select"]/text()
// will start from the document root, and # is an attribute match clause.
http://www.b624.net/modelare-software-uml-si-xml/laboratoare-an-3-is/xpath-cheat-sheet

Scrapy, python, Xpath how to match respective items in html

I am new to Xpath, trying to scrapy website with below format:
<div class="top">
<a> tittle_name </a>
<div class="middle"> listed_date </div>
<div class="middle"> listed_value </div>
</div>
<div class="top">
<a> tittle_name </a>
<div class="middle"> listed_date </div>
</div>
<div class="top">
<a> tittle_name </a>
<div class="middle"> listed_value </div>
</div>
The presences of listed_value & listed_date are optional.
I need to group each tittle_name with respective listed_date, listed_value (if available) then insert reach record to MySQL.
I am using scrapy shell which gives some basic examples like
listings = hxs.select('//div[#class=\'top\']')
for listing in listings:
tittle_name = listing.select('/a//text()').extract()
date_values = listing.select('//div[#class=\'middle\']')
Above code give me list of tittle_name and list of available listed_date, listed_value, but how to match them? (we cannot go by index because the format is not symmetric).
Thanks.
Do note that those XPath expressions are absolute:
/a//text()
//div[#class=\'middle\']
You would need relative XPath expression like these:
a
div[#class=\'middle\']
Second. It's not a good idea to select text nodes in a mixed content model like (X)HTML. You should extract the string value with the proper DOM method or with string() function. (In the last case, you would need to eval the expression for each node because the implicit node set casting into singleton node set)
Well, since the website doesn't specify whether something in a div[#class='middle'] is a date or a value, you'll have to code your own way of deciding this.
I guess the dates have some specific format that you could match with some analysis, maybe using a regular expression.
Can you maybe be more specific on what are possible values for listed_date and listed_value?

Categories