1

I have a page structure which contains a classname assigned to multiple divs. But there is one specific div that will contain a specific div.class inside it which happens dynamically.

<div class="ProductVariants__VariantCard-sc-1unev4j-3 bEuNss">
   <div class="ProductVariants__RadioButtonContainer-sc-1unev4j-4 jqJIBg">
     <div class="ProductVariants__RadioButtonOuter-sc-1unev4j-5 jcgpFW">
       <div class="ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM">
       </div>
     </div>
   </div>
   <div class="ProductVariants__VariantDetailsContainer-sc-1unev4j-7 fvkqJd">
     <p class="ProductVariants__VariantUnitText-sc-1unev4j-8 bZvIga">50 g</p>
     <div class="ProductVariants__PriceContainer-sc-1unev4j-9 jjiIua">
       ₹111 
       <span class="ProductVariants__MRPText-sc-1unev4j-10 jEinXG">
         ₹345
       </span>
     </div>
   </div>
</div>

If you see here this class ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM Line number 4 will be contained within one that specific class. Though there could be multiple of ProductVariants__VariantCard-sc-1unev4j-3 bEuNss.

How do I get the class ProductVariants__VariantCard-sc-1unev4j-3 bEuNss which contains ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM inside it.

This is what I have tried

driver.find_element(by=By.XPATH, value="//div[contains(@class,'ProductVariants__VariantCard-sc-1unev4j-3 bEuNss')]//div[contains(@class, 'ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM')]")

But this instead gives me the inner div and not the whole outer div

'<div class="ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM"></div>'
Himanshu Poddar
  • 7,112
  • 10
  • 47
  • 93
  • XPath from code sample doesn't match XPath from Exception. Update your question – JaSON Jul 05 '22 at 18:16
  • 1
    `fgFqYM` is nested at third level. So you can find this div and find parent that is three levels up. E.g. `driver.execute_script("return document.querySelector('.ProductVariants__RadioButtonInner-sc-1unev4j-6.fgFqYM').parentNode.parentNode.parentNode;")`. This would break if nesting order changes. – user47 Jul 05 '22 at 18:18
  • @Firelord isn't there a more selenium way, I don't want to execute any JS – Himanshu Poddar Jul 05 '22 at 18:21
  • @HimanshuPoddar I don't know xpath so I suggested alternative. Although, not a really good way to do this but I can pass the whole HTML body reference from selenium to Beautifulsoup and get parent or ascendants from there using Python. No JS would be needed. – user47 Jul 05 '22 at 18:22

2 Answers2

2

To identify the <div> with class="ProductVariants__VariantCard-sc-1unev4j-3 bEuNss with respect to the <div> with class="ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM you can use the following Locator Strategy:

driver.find_element(by=By.XPATH, value="//div[starts-with(@class, 'ProductVariants__RadioButtonInner')]//ancestor::div[starts-with(@class, 'ProductVariants__VariantCard')]")
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • `div_containing_radio = driver.find_element(by=By.XPATH, value="//div[contains(@class,'ProductVariants__VariantCard-sc-1unev4j-3 bEuNss') and .//div[contains(@class, 'ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM')]]")` if I use your code and now if I try to get class `ProductVariants__PriceContainer-sc-1unev4j-9 jjiIua` inside `div_containing_radio.find_element(by=By.CLASS_NAME, value="ProductVariants__PriceContainer-sc-1unev4j-9 jjiIua")` it gives error selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: – Himanshu Poddar Jul 05 '22 at 18:37
  • @HimanshuPoddar I haven't suggested `//div[contains(@class,'ProductVariants__VariantCard-sc-1unev4j-3 bEuNss') and .//div[contains(@class, 'ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM')]]` within my answer. – undetected Selenium Jul 05 '22 at 18:40
  • This is just a add on, do you want me to ask another question for it? – Himanshu Poddar Jul 05 '22 at 18:40
  • @HimanshuPoddar Ofcoarse the locators are supposed to be different. – undetected Selenium Jul 05 '22 at 18:41
  • `div_containing_radio.find_element(by=By.CSS_SELECTOR, value=".ProductVariants__PriceContainer-sc-1unev4j-9.jjiIua").text` this worked perfect – Himanshu Poddar Jul 05 '22 at 18:41
  • Can you help here please https://stackoverflow.com/questions/72874278/selenium-get-text-inside-an-element-but-not-inside-the-nested-tags-within-it – Himanshu Poddar Jul 05 '22 at 18:55
0

If you want to select ancestor node that contain specific descendant node try

driver.find_element(by=By.XPATH, value="//div[contains(@class,'ProductVariants__VariantCard-sc-1unev4j-3 bEuNss') and .//div[contains(@class, 'ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM')]]")
JaSON
  • 4,843
  • 2
  • 8
  • 15
  • `div_containing_radio = driver.find_element(by=By.XPATH, value="//div[contains(@class,'ProductVariants__VariantCard-sc-1unev4j-3 bEuNss') and .//div[contains(@class, 'ProductVariants__RadioButtonInner-sc-1unev4j-6 fgFqYM')]]") ` if I use your code and now if I try to get class `ProductVariants__PriceContainer-sc-1unev4j-9 jjiIua` inside `div_containing_radio.find_element(by=By.CLASS_NAME, value="ProductVariants__PriceContainer-sc-1unev4j-9 jjiIua")` it gives error `selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: ` – Himanshu Poddar Jul 05 '22 at 18:35
  • @HimanshuPoddar you cannot pass multiple class names to search by class. Try `(by=By.CLASS_NAME, value="ProductVariants__PriceContainer-sc-1unev4j-9")` or `(by=By.CSS_SELECTOR, value=".ProductVariants__PriceContainer-sc-1unev4j-9.jjiIua")` – JaSON Jul 05 '22 at 18:40