No desenvolvimento de testes com Selenium, frequentemente precisamos localizar elementos com base em suas relações no DOM, como nós filhos, pais ou irmãos. Quando um elemento não possui um seletor único, como um ID ou classe, podemos navegar pela árvore do documento. Este artigo explica técnicas para localizar elementos usando relações hierárquicas em Selenium com Python.
- Do Nó Pai para Nós Filhos
Localizar um nó a partir de seu nó pai é uma operação comum. Considere a seguinte estrutura HTML:
<html>
<body>
<div id="containerPai">
<div id="elementoAlvo">
<div>Conteúdo do nó filho</div>
</div>
</div>
</body>
</html>
Para localizar o nó filho sem ID a partir do elemento com ID "elementoAlvo", podemos usar diversos métodos:
# -*- coding: utf-8 -*-
from selenium import webdriver
navegador = webdriver.Chrome()
navegador.get('file:///caminho/para/arquivo.html')
# Método 1: Encadeamento de buscas
resultado1 = navegador.find_element('id', 'elementoAlvo').find_element('tag name', 'div').text
# Método 2: XPath com relação pai-filho
resultado2 = navegador.find_element('xpath', "//div[@id='elementoAlvo']/div").text
# Método 3: Seletor CSS com relação direta
resultado3 = navegador.find_element('css selector', 'div#elementoAlvo > div').text
# Método 4: Seletor CSS nth-child
resultado4 = navegador.find_element('css selector', 'div#elementoAlvo div:nth-child(1)').text
# Método 5: Seletor CSS nth-of-type
resultado5 = navegador.find_element('css selector', 'div#elementoAlvo div:nth-of-type(1)').text
# Método 6: Eixo XPath child (implícito)
resultado6 = navegador.find_element('xpath', "//div[@id='elementoAlvo']/child::div").text
navegador.quit()
Todos os métodos acima retornam o mesmo texto. O método 1 utiliza encadeamento, o 2 e 6 usam XPath, e os demais empregam seletroes CSS. Note que nth-child refere-se à posição entre todos os filhos, enquanto nth-of-type se aplica a filhos do mesmo tipo de elemento.
- Do Nó Filho para o Nó Pai
Localizar o nó pai a partir de um nó filho pode ser desafiador. Considere este HTML:
<html>
<body>
<div id="raiz">
<div>
<div>Nó neto com texto
<div>
<div id="netoAlvo"></div>
</div>
</div>
</div>
</div>
</body>
</html>
Para localizar o avô (dois níveis acima) do elemento com ID "netoAlvo", podemos usar XPath:
# -*- coding: utf-8 -*-
from selenium import webdriver
navegador = webdriver.Chrome()
navegador.get('file:///caminho/para/arquivo.html')
# Método 1: XPath com operador '..'
resultado1 = navegador.find_element('xpath', "//div[@id='netoAlvo']/../..").text
# Método 2: Eixo XPath parent
resultado2 = navegador.find_element('xpath', "//div[@id='netoAlvo']/parent::*/parent::div").text
navegador.quit()
O operador .. no XPath representa o nó pai. O eixo parent faz o mesmo. Observe que seletores CSS não oferecem uma maneira direta de localizar nós pais.
- Localizando Irmãos
Para localizar nós irmãos (anterior ou posterior), usamos técnicas específicas. Veja o HTML:
<html>
<body>
<div>
<div>Irmão anterior</div>
<div id="referencia"></div>
<div>Irmão posterior</div>
</div>
</body>
</html>
3.1. Do Nó para o Irmão Anterior
Para localizar o irmão anterior ao elemento com ID "referencia":
# -*- coding: utf-8 -*-
from selenium import webdriver
navegador = webdriver.Chrome()
navegador.get('file:///caminho/para/arquivo.html')
# Método 1: XPath via nó pai
resultado1 = navegador.find_element('xpath', "//div[@id='referencia']/../div[1]").text
# Método 2: Eixo XPath preceding-sibling
resultado2 = navegador.find_element('xpath', "//div[@id='referencia']/preceding-sibling::div[1]").text
navegador.quit()
O eixo preceding-sibling seleciona todos os irmãos enteriores, e o índice [1] pega o mais próximo.
3.2. Do Nó para o Irmão Posterior
Para localizar o irmão posterior ao mesmo elemento, há várias opções:
# -*- coding: utf-8 -*-
from selenium import webdriver
navegador = webdriver.Chrome()
navegador.get('file:///caminho/para/arquivo.html')
# Método 1: XPath via nó pai
resultado1 = navegador.find_element('xpath', "//div[@id='referencia']/../div[3]").text
# Método 2: Eixo XPath following-sibling
resultado2 = navegador.find_element('xpath', "//div[@id='referencia']/following-sibling::div[1]").text
# Método 3: Eixo XPath following (genérico)
resultado3 = navegador.find_element('xpath', "//div[@id='referencia']/following::*").text
# Método 4: Seletor CSS adjacente
resultado4 = navegador.find_element('css selector', 'div#referencia + div').text
# Método 5: Seletor CSS geral
resultado5 = navegador.find_element('css selector', 'div#referencia ~ div').text
navegador.quit()
O eixo following-sibling mira irmãos subsequentes. O seletor CSS + seleciona o elemento imediatamente seguinte, enquanto ~ seleciona todos os elementos seguintes. Para capturar múltiplos elementos, use find_elements.