I'd like to get all child elements of some specific element with Selenium. Let's say I have the following HTML:
<html>
<table>
<tr>
<td>Test 1</td>
<td id="123">Test <b>2</b>
<span>span_text</span>
</td>
<td>Test 3</td>
</tr>
</table>
</html>
First, I'd like to find the second td element by its id and then I'd like to find all of its child elements (i.e. the b and span elements). Finding the second td element isn't hard:
from selenium import webdriver
from selenium.webdriver.common.by import By
page_source = """<table>
<tr>
<td>Test 1</td>
<td id="123">Test<b>2</b><span>span_text</span></td>
<td>Test 3</td>
</tr>
</table>
"""
driver = webdriver.Chrome()
driver.execute_script('document.documentElement.innerHTML=arguments[0]', f"<html>{page_source}</html>")
element = driver.find_element(By.ID, "123")
In order to find the child elements, I tried the td > *
CSS Selector:
for elements in element.find_elements(By.CSS_SELECTOR, f"td > *"):
print(element.tag_name)
However, this prints two td
tags instead of b
and span
. I also tried the . > *
CSS Selector instead, which seems to be invalid. How I can select all (direct) child elements of an WebElement in Selenium by CSS Selectors?
Note: I want to use the element.find_elements()
method, i.e. I want selenium to only search within the already found element.
CodePudding user response:
You were almost there. Your code is perfect. You just need to keep a track that within for
statement in each iteration the decendants are referred as elements
. So you have to invoke:
print(elements.tag_name) # instead of element, it should be elements
Here is the complete program:
page_source = """<table>
<tr>
<td>Test 1</td>
<td id="123">Test<b>2</b><span>span_text</span></td>
<td>Test 3</td>
</tr>
</table>
"""
driver = webdriver.Chrome(service=s, options=options)
driver.execute_script('document.documentElement.innerHTML=arguments[0]', f"<html>{page_source}</html>")
element = driver.find_element(By.ID, "123")
for elements in element.find_elements(By.CSS_SELECTOR, f"td > *"):
print(elements.tag_name)
Output:
b
span
CodePudding user response:
There's a bug in your code :)
for elements in element.find_elements(By.CSS_SELECTOR, f"td > *"):
print(element.tag_name)
^ elements
This should be elements.tag_name
(plural of element) to use the loop variable, elements
. Your variable on the previous line is element
so you were printing the TD from the previous line twice.
Having said that, you can do this in a single step and simplify your code and save a little time
for element in driver.find_elements(By.CSS_SELECTOR, "[id='123'] > *"):
print(element.tag_name)