Unable to select html element by class name in python selenium

1k views Asked by At

I am trying to select I NEED THIS TEXT from the last line of the following html code and did not yet have success so far:

        <div class="warn">
<div class="row container pv2">
    <div class="col xs12">
        <div class="display-table-cell b-text_copy-4 pr1">
            <i class="msg-icon b-icon b-icon-warn"></i>
        </div>
        <div class="display-table-cell b-text_copy-2 b-text_weight-bold">
                    <div> I NEED THIS TEXT <a href=https://somelink/contact.html target=_blank>contact us</a>.</div>

INPUT I failed with the following approaches:

# all lines also tested without .text suffix
    text1 = driver.find_element_by_class_name("display-table-cell.b-text_copy-2.
                                              b-text_weight-bold").text
    text2 = driver.find_element_by_class_name("warn").text 
    text3 = driver.find_element_by_class_name("col.xs12").text
    text4 = driver.find_element_by_class_name("display-table-cell").text
    text5 = driver.find_element_by_xpath("//*[contains(@text='I NEED THIS TEXT')]")

OUTPUT:

text1: Message: Unable to locate element: .display-table-cell.b-text_copy-2.b-text_weight-bold
text2: Message: Unable to locate element: .warn
text3: Message: Unable to locate element: .col.xs12
text4: Message: Unable to locate element: .display-table-cell
text5: Message: Given xpath expression "//*[contains(@text='I NEED THIS TEXT')]" is invalid: [Exception... "<no message>"  nsresult: "0x8060000d (<unknown>)"  location: "JS frame :: chrome://marionette/content/element.js :: element.findByXPath :: line 355"  data: no]

Am I doing something fundamentally wrong? How to select I NEED THIS TEXT and print it to console?

2

There are 2 answers

5
undetected Selenium On

Our main aim was to extract the text I NEED THIS TEXT from the following node :

<div> I NEED THIS TEXT <a href=https://somelink/contact.html target=_blank>contact us</a>.</div>

Now as per your code trials you have tried to use the class_name display-table-cell.b-text_copy-2.b-text_weight-bold, warn, col.xs12, display-table-cell and xpath as //*[contains(@text='I NEED THIS TEXT')]. Through those class_name you haven't reached to the exact Node which contains the intended text. Hence we have to construct either an xpath or a cssSelector to mock the DOM and reach till the intended <div> tag where the text is located.

So, to print I NEED THIS TEXT to console from the last line of the given html you can use the following code block :

my_string = driver.find_element_by_xpath("//div[ancestor::div[contains(@class, 'display-table-cell b-text_copy-2 b-text_weight-bold')]]").get_attribute("innerHTML")                    
my_text = my_string.split("contact")
print(my_text[0])

Console Output :

I NEED THIS TEXT 
5
JeffC On

The main problem is that you are using mostly CSS selectors instead of class names. .find_element_by_class_name() is specifically for a single class name. If you want to use a CSS selector you need to use .find_element_by_css_selector(). Most of the CSS selectors you were using weren't actually for the DIV that you want either. It's hard to tell without a link to the page or more HTML but try these.

CSS Selector

div.display-table-cell.b-text_copy-2.b-text_weight-bold > div

XPath

//div[contains(.,'I NEED THIS TEXT')]
//a[.='contact us']/..

One issue you are going to run into is that the DIV that immediately contains the text you want also contains " contact us." so you will need to strip that out if you don't want it as part of the final string.