1

I am using selenium + chrome web driver to load a dynamic page:

self.driver.get(url)
time.sleep(3)  # not sure if I need to add this wait, so the .js loads the page?

Once the page is loaded, I want to get a list of all cards available on the page and then iterate through each card and get its title:

cards = self.driver.find_elements_by_css_selector('div.my-card')
for card in cards:
    title = card.find_element_by_css_selector('h2.title::text').get() # <-- does not work
    desc = card.find_element_by_css_selector('div.desc::text').get() # <-- does not work
    # more fields that I need within this card

find_elements_by_css_selector seems to be a driver method... I am not sure how to apply these selector to card (the type card is WebElement).


Sample page:

<div class='my-card'>
    <h2 class='title'>title 1</h2>
    <div class='desc'>desc 1</div>
</div>
<div class='my-card'>
    <h2 class='title'>title 2</h2>
    <div class='desc'>desc 2</div>
</div>
<div class='my-card'>
    <h2 class='title'>title 3</h2>
    <div class='desc'>desc 3</div>
</div>
10
  • Can you provide the output of cards or the html of a card please. That would help. Commented Nov 18, 2020 at 6:14
  • 1
    You need a webdriver wait after driver.get to allow for page load. Commented Nov 18, 2020 at 6:26
  • @arundeepchohan: it's not just the title... there are multiple fields within the card that I need... that's why I am iterating the card... is there no way to use a css selector on the card element? Commented Nov 18, 2020 at 6:40
  • They are ways to go down a card element but we need the html element layout in order to do so. Commented Nov 18, 2020 at 6:41
  • 1
    I don't think the pseudo class selector ::text works here. Omit the ::text part of the selector to get the element. Then, you can use the .text attribute on the webelement object to retrieve the text. e.g. title = card.find_element_by_css_selector('h2.title").text Commented Nov 18, 2020 at 7:06

2 Answers 2

3

You can combine the two into one query (CSS) selector like so by using the combinator child or descendent selector.

If the h2 element is a child and a descendent of the card element:

self.driver.find_elements_by_css_selector('div.my-card > h2.title')

If the h2 element is only a descendent of the card element:

self.driver.find_elements_by_css_selector('div.my-card h2.title')

Find out more about CSS combinators here.

Sign up to request clarification or add additional context in comments.

3 Comments

This returns a list of webelements with a div class of my-card and a descendant of h2 class of title.
@HoomanBahreini perhaps something is missing from your example? The answer given here returns a list of all three h2 elements containing the title. Or is there something else missing from this answer?
@HoomanBahreini Yeah, it returns a list[WebElement], where each of the elements in the list is the title of a card.
1

What you have works as-is. Using your given example HTML:

In [19]: for card in cards:
    ...:     title_elem = card.find_element_by_css_selector('h2.title')
    ...:     print(title_elem.text)
    ...:
title 1
title 2
title 3

In [20]: card
Out[20]: <selenium.webdriver.remote.webelement.WebElement (session="534c4be3a233a0aa963f541550ac7861", element="b56dcaf3-9b38-4e4c-aae8-99005ac9840b")>

So. Your expectation of using nested selenium selectors is correct. Some other assumption must be throwing you off.

2 Comments

Thanks a lot... I updated the question.. I guess the problem was using the Scrapy syntax for getting the text inside h2 element... do you know how can I get the inner html of h2?
@HoomanBahreini in the example above you could do title_elem.get_attribute('innerHTML') -- see also

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.