-3

I'm coding in Python, working with Selenium.
I have to print that closed year between the span tag.

<div class="display_year">
  <span class="year">
   ::before
   "1989"
   ::after
  </span>
</div>

I have no experience with Selenium. I tried to write this:

year = driver.find_element_by_xpath("//span::after[@class='year']")
print(year.text)

But it doesn't work. I guess it's for that :: before ... :: after, because this code prints an empty string that's the contents of the span tag when it is :: before

Someone, please, can tell me how I have to write to print the contents of the year, in this case "1989"?

most important: In the example I showed, the code was span class = "year" . But in case the code is span class = "year something somethingelse" does it change something syntactically?

Deepak Rai
  • 2,163
  • 3
  • 21
  • 36
Zeta22
  • 1
  • 1
  • 1
    Have you tried something simple like a CSS selector, `div.display_year > span.year`? That should work no matter what... even if there are extra classes on the SPAN tag. If that doesn't work, my guess is that the page is processing in the background and that's why you are getting an empty string. You may need to add a wait until the text is not empty string. – JeffC Feb 02 '21 at 22:47
  • @jeff it won't print the pseudo element content it will print only the text – PDHide Feb 03 '21 at 00:16
  • @PDHide OP said all he wants is "1989", not the pseudo element content. – JeffC Feb 04 '21 at 02:25
  • 1
    @Zeta22 Can you provide a link to the page? I think this is probably a timing issue. – JeffC Feb 04 '21 at 02:28
  • Author already using text and he is getting the year author wants – PDHide Feb 04 '21 at 07:37
  • Updated answer with contains for last two sentence – PDHide Feb 04 '21 at 07:44

3 Answers3

0
value = driver.execute_script("return window.getComputedStyle(document.querySelector('span.year'),':after').content);")

if you want to print the beffore element use the above code as its a pseudo element

https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

If you just want the year then use

   driver.find_element_by_xpath("//span[contains (@class,'year')]").text

Contains a I'll check for class that contains year , so both year and year something

you can also use or opertor

   driver.find_element_by_xpath("//span[@class='year' or @class='year somethin' ]").text

this check for class with year or year soemthing as value

you can also use find by class name or css as space in class name indicates multiple classes.

driver.find_element_by_class_name("year")   # this won't check specific for span tag
driver.find_element_by_css_selector("span.year")
PDHide
  • 18,113
  • 2
  • 31
  • 46
  • Ok I understand. In the example I showed, the code was ``` span class = "year"``` . But in case the code is ``` span class = "year something somethingelse"``` does it change something syntactically? – Zeta22 Feb 02 '21 at 21:19
  • change the queryselector only span.yearsomething (if space is there change it with dot ) span.year.something – PDHide Feb 02 '21 at 21:22
  • So I have to write `value = driver.execute_script("return window.getComputedStyle(document.querySelector('span.yearsomethingsomethingelse'),':after').content);")`? – Zeta22 Feb 02 '21 at 21:29
  • yes you can use any valid css locator inside query selctor, you are just saying get ComputedStyle from :after pseudo element of element detected using span.class , so you can use any valid css iinside that like tag[class="soomthing else"] tag.class tag[attribute="value"] etc – PDHide Feb 02 '21 at 21:31
  • I understand and thanks, but I'm sorry to tell you that it doesn't work.. I gonna try again – Zeta22 Feb 02 '21 at 21:34
  • It will give only that before or after element , not the entire string , you have to get each one to verify it – PDHide Feb 02 '21 at 21:38
  • @PDHide It's best to have discussions about your answer under your answer. No, I did not downvote your answer but it could be improved quite a bit. When using XPath to match classes, you are doing an exact string match. So if you are looking for a SPAN that contains the class "year", you have to do a contains in this case because OP stated that the SPAN may contain other classes. The problem is that with XPath and exact string matching it makes it near impossible to match all the different possibilities. – JeffC Feb 04 '21 at 17:51
  • The better way to do this is to use a CSS selector. `span.year` will match any of the examples that OP posted, is much easier shorter and to read, is faster, and is much better supported than XPaths. You should use ID and then CSS selector and then only when it's required use XPaths. The only 2 cases where XPaths are required are when you are looking for an element based on contained text or you need to do some complicated DOM traversal. – JeffC Feb 04 '21 at 17:53
  • Having said all that, I don't think OP's problem has anything to do with locators. I think it's a timing issue because locators that should work are returning empty string. OP didn't say he wanted anything from the ::before or ::after sections. If you look in his question he clearly states, "Someone, please, can tell me how I have to write to print the contents of the year, in this case '1989'?". He wants just the year. – JeffC Feb 04 '21 at 17:55
  • @JeffC why can't you use find_ement_by_class_name() there will be difffere t solutinons – PDHide Feb 04 '21 at 17:56
  • You should worry less about who is downvoting your answers and wonder why they are downvoting. Downvotes, when used correctly, are an indicator that something is wrong. You should want to know what is wrong and correct it or at least know what someone else misunderstood so that you can make the answer clearer, etc. – JeffC Feb 04 '21 at 17:57
  • You could use `.find_element_by_class_name()` as well. I tend not to use methods for class name, name, etc. because I can do all of that with a simple CSS selector instead. That way in my projects I only use ID, CSS selector, and XPath (sparingly). Makes it easier to read and maintain. – JeffC Feb 04 '21 at 17:58
  • @JeffC i should be worried when i try to help someone and someone shows thier privillege without any helpful comments to improve question or answer. :) IT depends on why people are on a forum . SOme are there to show there skills some are there to help others – PDHide Feb 04 '21 at 17:59
  • @JeffC find by class name uses css under the hood – PDHide Feb 04 '21 at 18:00
  • @PDHide There is no requirement to add a comment. In fact, in many cases it causes more problems. I don't disagree with you but many, like DebanjanB, misuse their votes to revenge vote when people downvote their answer or make critical comments. Because of behavior like this, I and many others don't leave comments very often. – JeffC Feb 04 '21 at 18:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/228268/discussion-between-pdhide-and-jeffc). – PDHide Feb 04 '21 at 18:07
  • @PDHide Yes, but the point is readability, etc.. If I just use 3 different locators types, it's easier to read and maintain locators. If I use by class name and then need to add the element, I have to use a CSS selector and then I have to change the find_by. If the find_by is already css selector, I can just change the selector and I'm done. It's mostly a personal preference but I've been doing this for years and found this way is easiest. – JeffC Feb 04 '21 at 18:09
0

this should work driver.find_elements_by_xpath("//div[@class='display_year']/span[@class='year']")

-1

To print the text 1989 you can use either of the following Locator Strategies:

  • Using css_selector:

    print(driver.find_element(By.CSS_SELECTOR, "div.display_year > span.year.something.somethingelse").text)
    
  • Using xpath:

    print(driver.find_element(By.XPATH, "//div[@class='display_year']/span[@class='year something somethingelse']").text)
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 1
    Now that I've addressed your comments on the other question, your answer doesn't take the full question into account either. The OP stated, "But **in case** the code is span class = "year something somethingelse" does it change something syntactically?" Your answer only takes the second case into account but not the first. Hard coding XPaths like the SPAN class is going to be very brittle because it has to be an **exact** text match. The same class names in a different order or with an extra space between classes, etc. would all cause the XPath to fail. – JeffC Feb 03 '21 at 01:06