Geonode logo
Geonode Team

Geonode Team

Atualizado: 7 de outubro de 2026

Publicado: 2 de setembro de 2026

Ficha de referência do XPath: Guia com exemplos

O XPath é uma linguagem de consulta para navegar em documentos XML e HTML. Tem um núcleo reduzido e um grande número de formas de ser mal utilizado. Esta é uma referência organizada da forma como realmente precisas: primeiro a sintaxe, depois as funções que vale a pena conhecer, seguidas dos padrões que surgem repetidamente e, por fim, as armadilhas. Tudo aqui diz respeito ao XPath 1.0, que é o que os navegadores, o Selenium e a maioria das bibliotecas de análise implementam.

Uma breve nota sobre quem escreveu isto. Somos a Geonode e vendemos proxies a pessoas que extraem dados; por isso, o XPath está relacionado com a nossa atividade, mas não faz parte dela. É importante referir que um problema de seletor e um problema de proxy não se parecem em nada, e confundi-los faz perder horas — um pedido bloqueado devolve uma página de desafio ou um estado de erro, enquanto uma expressão incorreta devolve uma página perfeitamente válida e um resultado vazio. Se o HTML estiver presente e o seu XPath não encontrar nada, a rede está a funcionar bem e esta página é o local certo.

A sintaxe básica

ExpressãoSeleciona
/html/body/divCaminho absoluto a partir da raiz
//divQualquer elemento div em qualquer parte do documento
//div/pElementos p que sejam filhos diretos de um div
//div//pElementos p em qualquer profundidade dentro de um div
.O nó de contexto atual
..O pai do nó de contexto
*Qualquer elemento
@hrefO atributo «href»
//@hrefTodos os atributos «href» no documento
text()Nós de texto filhos do nó de contexto
node()Qualquer nó, incluindo texto e comentários
//a | //linkUnião — tudo o que for correspondido por qualquer uma das expressões

A distinção entre / e // é aquela que deve ser interiorizada. Uma barra simples significa «filho direto»; duas barras significam «descendente em qualquer profundidade». //div/p não encontra um parágrafo envolvido por um section; //div//p encontra-o.

Os caminhos absolutos — /html/body/div[2]/div[1]/span — são o que a opção «copiar XPath» do navegador produz e o que deixa de funcionar na próxima reformulação. É preferível começar por algo identificável e navegar de forma relativa.

Predicados

Os parênteses retos filtram um conjunto de nós. É aqui que se realiza a maior parte do trabalho útil.

ExpressãoSeleciona
//div[1]O primeiro div entre os seus irmãos, por pai
(//div)[1]O primeiro div em todo o documento
//div[last()]O último div entre os seus irmãos
//div[position() < 4]Os três primeiros
//a[@href]Links que possuem um atributo «href»
//a[@href='/about']Links com exatamente esse «href»
//div[@class and @id]Elementos com ambos os atributos
//p[text()]Parágrafos com pelo menos um elemento filho do tipo «text-node»
//div[p]Divs que contêm pelo menos um elemento filho do tipo «p»
//div[not(@hidden)]Divs sem um atributo «hidden»
//td[.='42'][@class='qty']Dois predicados, aplicados em sequência

//div[1] versus (//div)[1] é a confusão mais comum no XPath. O primeiro é um predicado aplicado por pai, pelo que seleciona o primeiro div sob cada pai que tenha um — potencialmente muitos nós. O segundo reúne todos os divs num conjunto de nós pela ordem do documento e seleciona o primeiro, o que corresponde exatamente a um nó. Ambos são úteis; não são intercambiáveis.

Os predicados encadeiam-se, e cada um aplica-se ao resultado do anterior. //td[@class='price'][1] significa «o primeiro entre as células com a classe price», lendo-se da esquerda para a direita.

Eixos

Os eixos orientam-se em relação ao nó de contexto. A maioria das pessoas utiliza três e, ocasionalmente, necessita dos restantes.

EixoSeleciona
child::Filhos diretos — o valor predefinido, normalmente omitido
descendant::Todos os descendentes em qualquer profundidade
parent::O pai
ancestor::Todos os antepassados até à raiz
ancestor-or-self::Antepassados mais o próprio nó
following-sibling::Irmãos posteriores
preceding-sibling::Irmãos anteriores
following::Tudo o que vem a seguir na ordem do documento, excluindo descendentes
preceding::Tudo o que vem antes, excluindo antepassados
attribute::Atributos — abreviados como @
self::O próprio nó

Quatro são eixos inversos — ancestor, ancestor-or-self, preceding e preceding-sibling — e, nesses, a numeração das posições decorre de trás para a frente. preceding-sibling::p[1] é o parágrafo mais próximo que precede, não o primeiro no documento. Utilize parênteses para obter a ordem do documento. Abordámos este tema em pormenor em XPath preceding-sibling.

following e preceding são muito mais abrangentes e muito mais lentos do que as suas contrapartes «sibling», e excluem, respetivamente, antepassados e descendentes. Recorra a elas apenas quando a relação for genuinamente vaga.

Funções de cadeias de caracteres

As funções mais utilizadas.

FunçãoO que faz
contains(a, b)Retorna «True» se a contiver b como subcadeia
starts-with(a, b)Retorna «True» se a começar por b
normalize-space(s)Remove e comprime os espaços em branco internos
string-length(s)Conta o número de caracteres
substring(s, start, len)Subcadeia, indexada a partir de 1
substring-before(a, b)Tudo o que vem antes da primeira ocorrência de b
substring-after(a, b)Tudo o que vem depois da primeira ocorrência de b
translate(s, from, to)Substituição caractere a caractere
concat(a, b, ...)Une cadeias de caracteres
string(node-set)Apenas o valor da cadeia do primeiro nó

Três notas que evitam erros reais.

substring() é indexado a partir de 1. substring('hello', 1, 3) devolve hel. Todos cometem este erro pelo menos uma vez.

normalize-space() deve ser o seu wrapper predefinido em qualquer comparação de texto. O HTML real é formatado de forma legível, pelo que o valor da cadeia de caracteres de uma célula é frequentemente "\n In stock\n" em vez de "In stock". Sem argumentos, opera no nó de contexto.

Não existe ends-with(), nem lower-case(), nem expressões regulares no XPath 1.0. Para ignorar maiúsculas e minúsculas, translate() com alfa-numéricos explícitos é a solução alternativa padrão. Bibliotecas do lado do servidor, como a lxml, suportam extensões EXSLT, incluindo re:test(); os navegadores e o Selenium não suportam.

Funções numéricas e booleanas

FunçãoFunção
count(node-set)Número de nós
position()Posição do nó de contexto
last()Tamanho do conjunto de nós de contexto
number(s)Converte num número
sum(node-set)Soma os valores numéricos
round(), floor(), ceiling()Conforme indicado
not(expr)Negação booleana
boolean(expr)Converte para booleano
true(), false()Booleanos literais

Os operadores de comparação são =, !=, <, >, <=, >=, com and e or para combinação. Note-se que, em contextos XML, < deve ser escapado como &lt;, razão pela qual, por vezes, se vêem expressões escritas com position() &lt; 4.

Uma subtileza que vale a pena conhecer: comparar um conjunto de nós com um valor é um teste existencial. //p = 'Price' é verdadeiro se qualquer parágrafo for igual a «Price». Isso é frequentemente o que se pretende dentro de um predicado e quase nunca o que se pretende ao nível superior.

Padrões que surgem constantemente

As expressões que realmente funcionam.

Corresponder corretamente a uma classe — o simples contains(@class, 'btn')

também corresponde a btn-primary

e unbtn

:

//div[contains(concat(' ', normalize-space(@class), ' '), ' btn ')]

Encontrar um valor pela sua etiqueta — o requisito de extração mais comum que existe:

//dt[normalize-space()='Price']/following-sibling::dd[1]
//th[normalize-space()='Weight']/following-sibling::td[1]
//td[preceding-sibling::td[1]='SKU']

Encontrar uma linha por uma célula e, em seguida, selecionar uma coluna diferente:

//tr[td[normalize-space()='SKU-1234']]/td[3]

Encontrar um contentor com base no seu conteúdo:

//div[contains(@class,'card')][.//span[contains(., 'Sold out')]]

Encontrar o primeiro elemento após um título:

//h2[normalize-space()='Specifications']/following-sibling::table[1]

Correspondência de texto sem distinção entre maiúsculas e minúsculas:

//p[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                          'abcdefghijklmnopqrstuvwxyz'), 'price')]

Excluir em vez de incluir — muitas vezes mais claro:

//tr[not(contains(@class,'header'))]
//li[not(contains(normalize-space(),'Advertisement'))]

Corresponder a qualquer um de dois tipos de elementos:

//*[self::button or self::a][normalize-space()='Continue']

Ignorar valores vazios:

//td[string-length(normalize-space()) > 0]

Extrair um atributo de um elemento correspondente:

//a[normalize-space()='Download']/@href

As Armadilhas

Classificadas de acordo com a frequência com que fazem as pessoas perder tempo.

A conversão de um conjunto de nós para uma cadeia de caracteres considera apenas o primeiro nó. contains(//p, 'Price') converte todo o conjunto de nós //p numa cadeia de caracteres, considerando apenas o primeiro parágrafo e ignorando o resto. Em vez disso, aplique o predicado a cada nó: //p[contains(., 'Price')]. Este é o erro mais comum em XPath.

. e text() são diferentes. O valor de cadeia de caracteres de um elemento é a concatenação de todos os seus nós de texto descendentes; text() devolve apenas os filhos diretos que são nós de texto, e a conversão para cadeia de caracteres retém o primeiro desses. Utilize ., a menos que pretenda excluir especificamente o conteúdo aninhado.

Numeração de eixo inverso. preceding-sibling::td[1] é o mais próximo, não o primeiro.

Espaços em branco. //td[.='In stock'] falha com HTML formatado. normalize-space() corrige isso.

Distinção entre maiúsculas e minúsculas. Tudo no XPath 1.0 distingue entre maiúsculas e minúsculas, incluindo os nomes dos elementos nos documentos XML.

Espaços de nomes predefinidos. Em XML com um espaço de nomes predefinido, //item não corresponde a nada — é necessário registar um prefixo e utilizá-lo. Os analisadores HTML normalmente poupam-lhe este trabalho; os analisadores XML não.

Caminhos absolutos das ferramentas de desenvolvimento do navegador. Estes codificam a estrutura exata num determinado momento e deixam de funcionar com qualquer alteração.

Correspondência excessiva com «contains()». A correspondência com «Price» também corresponde a «Historic Price». Utilize «normalize-space() = 'Price'» quando pretender igualdade.

Injeção de cadeias de caracteres não confiáveis. Interpolar a entrada do utilizador numa expressão constitui uma injeção de XPath. Utilize a ligação de variáveis sempre que a sua biblioteca o permitir. O XPath 1.0 não dispõe de caracteres de escape para aspas dentro de uma cadeia de caracteres literal, pelo que um valor que contenha ambos os caracteres de aspa requer concat().

XPath 1.0 versus versões posteriores

É importante saber isto porque um trecho de código que encontres online pode não funcionar onde precisas.

O XPath 1.0 é o que os navegadores implementam através de document.evaluate, o que o Selenium utiliza e o que a API comum do lxml fornece. Possui as funções listadas acima e nada mais.

O XPath 2.0 e 3.1 adicionam expressões regulares (matches(), replace()), funções de caso (upper-case(), lower-case()), ends-with(), tipos de sequência, expressões for e muito mais. Estão disponíveis em processadores XSLT 2.0+ e em algumas ferramentas XML, mas não estão disponíveis nos navegadores.

A regra prática: se uma expressão utilizar uma função que não conste nas tabelas acima, verifique se o seu ambiente a suporta antes de procurar a causa da falha. «Funciona num testador de XPath online, mas não no Selenium» é quase sempre devido a isto.

Quanto às lacunas que o XPath 1.0 deixa, a resposta é normalmente a sua linguagem de programação. Extraia com o XPath e, em seguida, aplique uma expressão regular em Python ou JavaScript, onde também pode inspecionar o que correspondeu.

Escrever seletores que resistam a uma reformulação

Uma ficha de referência indica o que é possível; esta secção trata de quais dessas opções escolher, porque a diferença entre um seletor que dura um ano e outro que deixa de funcionar na próxima terça-feira depende inteiramente daquilo em que se baseia.

Baseie-se no significado, não na posição. (//table)[3]/tr[2]/td[4] codifica a forma exata da página num determinado momento. Se alguém adicionar uma tabela acima, todos os números ficarão errados — sem que se note, porque a expressão continua a corresponder a algo. //th[normalize-space()='Weight']/following-sibling::td[1] codifica uma relação que resiste à reordenação, porque o rótulo se move juntamente com o valor.

Dê preferência a atributos estáveis em vez de atributos gerados. Os IDs e os atributos data-* escolhidos por um programador são muito mais duradouros do que os nomes de classe, que mudam sempre que alguém altera o estilo. Muitas estruturas front-end modernas geram nomes de classe com hash — css-1x9dj2k — que mudam a cada compilação; basear-se neles garante falhas.

Verifique se existem dados estruturados incorporados antes de escrever qualquer seletor. Muitas páginas contêm JSON-LD num bloco <script type="application/ld+json">, porque este alimenta as funcionalidades de pesquisa. A análise desses dados é significativamente mais estável do que a análise de HTML renderizado, uma vez que foi concebida para ser lida por máquinas e sobrevive inteiramente a reformulações visuais. Trinta segundos a verificar isso podem poupar uma tarde de manutenção de seletores.

Verifique a estrutura do que extrai. Este é o hábito que distingue um pipeline que falha de forma evidente de um que falha silenciosamente. Se um preço tiver de corresponder a um padrão de moeda, verifique-o. Se uma página de categoria nunca teve menos de vinte itens, considere que ter menos de vinte é um erro, em vez de um resultado. Um seletor que começa a corresponder ao elemento errado produz dados plausíveis, bem formados, mas errados — e nenhuma exceção é levantada em nenhum momento.

Mantenha os seletores num único local. Espalhadas por uma base de código, quarenta cadeias XPath representam quarenta responsabilidades de manutenção distintas. Reunidas num único módulo com nomes, constituem um mapa das suas dependências, e a atualização após uma reformulação demora uma hora em vez de um dia.

E teste com base no HTML guardado. Guardar uma cópia de cada página que analisa significa que, quando um seletor deixa de funcionar, pode comparar a marcação antiga com a nova e ver exatamente o que mudou. Voltar a carregar a página para depurar é mais lento, consome largura de banda e pode apresentar-lhe uma página diferente daquela em que ocorreu a falha.

Quando utilizar CSS em vez disso

O XPath é mais poderoso, mas menos legível. O CSS é a escolha padrão adequada para grande parte do trabalho de seleção.

Utilize CSS quando: estiver a selecionar por classe, id, atributo ou relação de descendência. div.card > p.price é mais claro do que o equivalente em XPath, é melhor suportado pelas ferramentas e, geralmente, mais rápido.

Utilize o XPath quando: precisar de fazer uma correspondência com base no conteúdo de texto, algo que o CSS não consegue fazer de todo; precisar de navegar até um pai ou antepassado; precisar de lógica posicional relativa a irmãos de uma forma que :nth-child não consiga expressar; ou estiver a consultar XML em vez de HTML.

Note-se que o CSS colmatou parte dessa lacuna. :has() permite a seleção condicional de irmãos e descendentes nos navegadores modernos, pelo que dt:has(+ dd) é agora expressável. O que o CSS ainda não consegue fazer é selecionar por texto, e a correspondência de texto é precisamente o que o padrão «label-value» requer.

Misturar ambos numa única base de código é adequado e sensato: CSS para os 90% mais simples, XPath para os 10% mais complexos.

Perguntas frequentes

Para que serve o XPath?

Para navegar e selecionar nós em documentos XML e HTML. Na prática, é utilizado para extração de dados da Web, automatização de testes de navegadores e consulta de ficheiros de configuração e de dados XML. Permite expressar relações — pais, irmãos, conteúdo de texto — que os seletores CSS não conseguem.

Qual é a diferença entre / e // no XPath?

Uma barra simples seleciona filhos diretos; duas barras selecionam descendentes em qualquer profundidade. //div/p corresponde a parágrafos cujo pai imediato é um div, enquanto //div//p corresponde a parágrafos em qualquer local dentro de um div.

Por que razão o meu XPath contains() não devolve nada?

Na maioria das vezes, porque lhe passou um conjunto de nós. O XPath converte um conjunto de nós numa cadeia de caracteres, selecionando o primeiro nó na ordem do documento e descartando o resto; por isso, contains(//p, 'x') apenas analisa o primeiro parágrafo. Escreva //p[contains(., 'x')] em vez disso.

Como seleciono por classe no XPath?

Utilize //div[contains(concat(' ', normalize-space(@class), ' '), ' name ')], que preenche o atributo para que apenas tokens inteiros correspondam. Um simples contains(@class, 'btn') também corresponde a btn-primary. Se estiver a selecionar apenas por classes, um seletor CSS é mais claro e, por predefinição, mais correto.

O XPath suporta expressões regulares?

Não no XPath 1.0, que é o que os navegadores e o Selenium implementam. O XPath 2.0 e versões posteriores adicionam matches() e replace(), e bibliotecas do lado do servidor, como o lxml, suportam o re:test() do EXSLT. Para automação de navegadores, extraia com o XPath e aplique a expressão regular na sua linguagem de programação.

Qual é a diferença entre //div[1] e (//div)[1]?

//div[1] aplica o predicado por elemento pai, selecionando o primeiro div sob cada elemento pai que tenha um — possivelmente muitos nós. (//div)[1] recolhe todos os divs pela ordem do documento e seleciona o primeiro, o que corresponde exatamente a um nó.

O XPath distingue maiúsculas de minúsculas?

Sim, em todos os casos — nomes de elementos, nomes de atributos e comparações de cadeias de caracteres. O XPath 1.0 não possui a função «lower-case()», pelo que a correspondência sem distinção de maiúsculas e minúsculas requer «translate()» com letras maiúsculas e minúsculas explícitas.

Devo usar seletores XPath ou CSS?

CSS para classes, IDs, atributos e relações de descendência — é mais claro e tem melhor suporte. XPath quando precisar de fazer correspondências com base no conteúdo de texto, navegar até antepassados ou expressar lógica posicional que o CSS não consegue. É normal usar ambos numa mesma base de código.

Conclusão

O núcleo útil do XPath é reduzido: «//» para pesquisar em qualquer lugar, predicados entre parênteses retos para filtrar, «@» para atributos, algumas funções de cadeia de caracteres e os eixos «sibling» para navegar em relação a algo que se possa identificar.

Três hábitos evitam a maior parte das dificuldades. Envolva as comparações de texto em normalize-space(), porque o HTML real é formatado de forma legível e uma correspondência exata falhará. Aplique contains() dentro de um predicado para que seja avaliado por nó, uma vez que a conversão de cadeias de caracteres de um conjunto de nós seleciona silenciosamente apenas o primeiro. E prefira a ancoragem em texto ou identificadores em vez da ancoragem em posição, porque a estrutura muda e o texto normalmente não.

Depois, lembre-se para que versão está a escrever. Os navegadores e o Selenium oferecem-lhe o XPath 1.0 — sem expressões regulares, sem lower-case(), sem ends-with() — e uma expressão que funcione num testador online pode não utilizar nenhuma dessas funcionalidades e, mesmo assim, falhar por um motivo que se encontra mais abaixo na lista. Quando precisar do que falta na versão 1.0, extraia com o XPath e faça o resto na sua linguagem de programação.