🎯 Um navegador em nuvem personalizável e anti-detecção alimentado por Chromium desenvolvido internamente, projetado para rastreadores web e agentes de IA. 👉Experimente agora
De volta ao blog

A Árvore de Acessibilidade Não É uma Página Mais Barata: Medindo o Que os Agentes Lêem

Michael Lee
Michael Lee

Expert Network Defense Engineer

07-Aug-2026

TL;DR:

  • A árvore de acessibilidade é o que a maioria dos agentes de navegador alimenta em seu modelo em vez de HTML bruto, recuperado através do Protocolo DevTools do Chrome com Accessibility.getFullAXTree.
  • Não é uma compressão da página. Em uma página de catálogo ao vivo: HTML bruto 9.824 tokens, innerText 582, árvore de acessibilidade completa 5.951 — a árvore custa 10.2× texto simples.
  • O motivo é visível nos papéis dos nós: de 1.401 nós, 267 são StaticText e 391 são InlineTextBox, então a maioria das strings é armazenada duas vezes.
  • Filtrar para papéis interativos dá 742 tokens em 114 nós — 1.3× innerText — enquanto mantém tudo o que um agente precisa clicar.
  • Medido através do Chromium local e do Scrapeless Scraping Browser, cada número foi idêntico, então a representação da página de um agente não drift entre ambientes.
  • O plano gratuito do Scrapeless cobre a execução de navegador em nuvem neste guia.

Todo agente de navegador precisa responder a uma pergunta antes de poder fazer qualquer coisa: o que você entrega ao modelo? Um documento HTML de 51.004 caracteres não se encaixa em um orçamento de prompt sensato, e uma captura de tela custa tokens de imagem e perde strings exatas. A terceira resposta usual é a árvore de acessibilidade.

Essa resposta está certa sobre a forma e errada sobre o preço. A árvore carrega papéis e nomes — link, button, heading — que é exatamente o que um agente precisa para decidir onde clicar. Ela é também, sem filtros, uma ordem de magnitude mais cara do que o texto simples da página.

Este guia puxa a árvore via CDP, mede-a contra as alternativas na mesma página ao vivo, e mostra o filtro que vale a pena enviar.

O Que é a Árvore de Acessibilidade

O navegador constrói uma segunda árvore ao lado do DOM, para leitores de tela. Cada nó carrega um role — um dos tipos de controle definidos pela especificação WAI-ARIA — e um name, a string que um leitor de tela anuncia, derivada pelo algoritmo em o Cálculo de Nome e Descrição Acessíveis. Envolvimentos de apresentação colapsam, atributos aria-* são resolvidos e elementos interativos são rotulados.

Essa estrutura é o motivo pelo qual os agentes gostam dela. link: Books to Scrape é diretamente acionável de uma maneira que um <div class="col-sm-8 h1"><a href="..."> não é. A árvore é exposta pelo domínio de Acessibilidade de o Protocolo DevTools do Chrome, e é os mesmos dados que o Chrome renderiza em seu próprio painel de acessibilidade. Se o CDP em si é novo, o primer do protocolo cobre o transporte sobre o qual este artigo se baseia.

Instalar

bash Copy
pip install playwright tiktoken
playwright install chromium

tiktoken está aqui apenas para contar tokens; a extração precisa apenas do Playwright. A execução de verificação usou Playwright 1.59.0 e tiktoken 0.12.0.

Puxar a Árvore

O Playwright expõe uma sessão CDP bruta, que é como você alcança domínios que ele não envolve:

python Copy
    cdp = page.context.new_cdp_session(page)
    nodes = cdp.send("Accessibility.getFullAXTree")["nodes"]

Cada nó é um dicionário cuja role e name são eles mesmos objetos com uma chave value. A maioria dos nós não tem nome algum — contêineres, nós ignorados e caixas de layout — então a projeção útil é papel mais nome para os nomeados:

python Copy
def ax_lines(nodes, roles=None):
    lines = []
    for node in nodes:
        role = (node.get("role") or {}).get("value", "")
        name = ((node.get("name") or {}).get("value") or "").strip()
        if not name:
            continue
        if roles is not None and role not in roles:
            continue
        lines.append(f"{role}: {name}")
    return lines

Em um catálogo de livros ao vivo que gera linhas como:

text Copy
RootWebArea: All products | Books to Scrape - Sandbox
heading: All products
link: Books to Scrape
StaticText: We love being scraped!
link: Home
StaticText: /
InlineTextBox: /

Duas dessas sete linhas são o mesmo barra. Essa duplicação é toda a história do custo.

Meça Contra as Alternativas

Conte tokens para as três representações da página idêntica:

python Copy
def measure(page, label):
    html = page.content()
    text = page.evaluate("document.body.innerText")
    cdp = page.context.new_cdp_session(page)
    nodes = cdp.send("Accessibility.getFullAXTree")["nodes"]

    full = "\n".join(ax_lines(nodes))
    acts = "\n".join(ax_lines(nodes, INTERACTIVE))
    roles = [(n.get("role") or {}).get("value", "") for n in nodes]
text Copy
  raw html            tokens=  9824  chars=51004
  innerText           tokens=   582  chars=2029
  AX full             tokens=  5951  named_nodes=864
  AX interactive only tokens=   742  nodes=114
  AX total nodes      1401
  StaticText nodes    267
  InlineTextBox nodes 391
  price in html/text/ax: True/True/True

A árvore de acessibilidade completa custa 5.951 tokens contra os 582 do innerText. É 10.2× o texto simples da mesma página, e cerca de 60% do HTML bruto que deveria substituir.

As contagens de papéis explicam isso. De 1.401 nós, 267 são StaticText e 391 são InlineTextBox — 658 nós, quase metade da árvore, dedicados a texto que a página já contém uma vez. Nós InlineTextBox são fragmentos de layout: uma única frase quebrada em duas linhas renderizadas se torna duas delas. Enviar a árvore completa significa pagar por cada string pelo menos duas vezes.

Vale a pena afirmar claramente: nada foi perdido. O preço £51.77 está presente no HTML, em innerText, e na árvore de acessibilidade. Nesta página, a árvore é mais cara, não menos completa.

Filtre para O Que Um Agente Pode Agir

Um agente lendo uma página precisa de texto. Um agente operando uma página precisa das coisas que ele pode clicar e digitar. Esses são um pequeno conjunto de papéis:

python Copy
INTERACTIVE = {"link", "button", "textbox", "combobox", "checkbox", "radio", "menuitem", "tab"}

Passar esse conjunto para a mesma função colapsa a árvore para 114 nós e 742 tokens — 1.3× innerText, e 8× mais barato do que a versão não filtrada. Cada link e controle mantém seu nome acessível, que é a que uma instrução de clique se refere.
Isso sugere uma divisão em vez de uma escolha. Use innerText quando o modelo precisar ler e extrair, use a árvore filtrada por função quando tiver que decidir o que operar, e envie ambos quando a tarefa precisar de ambos - juntas elas são 1.324 tokens, ainda um oitavo do HTML bruto. O guia do loop do agente cobre o que acontece depois que essa decisão é tomada.

Nada acima precisa de um navegador local. O Navegador de Scraping Scrapeless fala o mesmo protocolo, então a sessão CDP e a chamada de acessibilidade não mudam — apenas a conexão difere:

python Copy
    endpoint = (
        "wss://browser.scrapeless.com/api/v2/browser"
        f"?token={os.environ['SCRAPELESS_API_KEY']}&sessionTTL=180&proxyCountry=ANY"
    )
    with sync_playwright() as p:
        browser = p.chromium.connect_over_cdp(endpoint, timeout=90000)
        page = browser.new_page()
        page.goto(URL, wait_until="domcontentloaded")
        measure(page, "Scrapeless Scraping Browser")
        browser.close()

A execução na nuvem retornou números idênticos em cada métrica: 9.824 / 582 / 5.951 / 742 tokens, 1.401 nós, a mesma contagem de StaticText e InlineTextBox. Isso tem uma consequência prática. Uma representação de página que muda entre seu laptop e a produção tornaria o comportamento do agente irreproduzível; esta não faz isso. Mantenha a chave no ambiente como SCRAPELESS_API_KEY, e veja a introdução ao Navegador de Scraping para os parâmetros restantes da sessão.

Começar leva um minuto - crie uma conta gratuita Scrapeless e o plano gratuito cobre essa execução.

Execute-o

bash Copy
export SCRAPELESS_API_KEY="your-api-key"
python3 ax_demo.py

A saída completa da execução de verificação:

text Copy
playwright 1.59.0 | tiktoken 0.12.0
[local chromium]
  raw html            tokens=  9824  chars=51004
  innerText           tokens=   582  chars=2029
  AX full             tokens=  5951  named_nodes=864
  AX interactive only tokens=   742  nodes=114
  AX total nodes      1401
  StaticText nodes    267
  InlineTextBox nodes 391
  price in html/text/ax: True/True/True

[Scrapeless Scraping Browser]
  raw html            tokens=  9824  chars=51004
  innerText           tokens=   582  chars=2029
  AX full             tokens=  5951  named_nodes=864
  AX interactive only tokens=   742  nodes=114
  AX total nodes      1401
  StaticText nodes    267
  InlineTextBox nodes 391
  price in html/text/ax: True/True/True

ratios vs innerText: html=16.9x  ax_full=10.2x  ax_interactive=1.3x

Resolução de Problemas

Accessibility.getFullAXTree retorna muito poucos nós. A árvore é construída de forma preguiçosa. Navegue e espere pelo conteúdo antes de solicitá-lo e chame Accessibility.enable primeiro se o seu cliente não o fizer implicitamente.

Cada nó tem um nome vazio. Você está lendo node["name"] diretamente. Tanto role quanto name são objetos — a string está em node["name"]["value"].

As contagens de nós diferem entre duas execuções da mesma página. Nós InlineTextBox seguem a quebra de linha, então uma largura de viewport diferente altera quantos há. Defina uma viewport explícita quando a contagem em si for importante.

A árvore omite algo visível na tela. Conteúdo marcado como aria-hidden, e texto gerado puramente por CSS ::before/::after, está intencionalmente ausente. Leia esses do DOM em vez disso; a árvore de acessibilidade não é um substituto para isso.

Funções parecem desconhecidas. StaticText, InlineTextBox, e RootWebArea são funções internas do Chrome em vez de ARIA, que é o motivo pelo qual a filtragem em uma lista de permissão apenas ARIA elimina a maior parte da árvore. Os Mapeamentos da API de Acessibilidade Central definem quais funções um navegador é obrigado a expor; qualquer coisa além desse conjunto é específica do mecanismo.

Conclusão

A árvore de acessibilidade é uma boa resposta ao que deve ser dado a um agente, e um mau padrão em sua forma bruta. Na página medida aqui, custa 5.951 tokens — dez vezes o texto simples que frequentemente se presume que comprime — porque quase metade de seus nós existe para descrever texto que a página já afirmou uma vez.

Filtrada para as funções em que um agente pode agir, a mesma árvore tem 742 tokens e ainda nomeia cada controle. Essa é a versão a ser colocada em um prompt, emparelhada com innerText quando a tarefa também requer leitura. Meça ambos em seu próprio alvo antes de escolher: os números aqui vêm de uma página de catálogo, e a proporção depende inteiramente de quão grande parte da página é prosa e quão grande parte são controles.

Pronto para tentar? Comece com o plano gratuito Scrapeless e veja o preço atual para volumes maiores.

FAQ

Q: Devo enviar a árvore de acessibilidade em vez do HTML?

Envie uma versão filtrada dela. Sem filtragem, mediu 5.951 tokens contra 9.824 para o HTML bruto — uma economia, mas muito menos do que o esperado. Restrita a funções interativas, cai para 742, que é onde a redução real está.

Q: A árvore de acessibilidade é mais barata que texto simples?

Não, e essa é a concepção comum. Na página medida aqui, custou 10,2× innerText. O valor da árvore está nos rótulos de função que ela adiciona, não em um carregamento menor.

Q: Por que há tantos nós InlineTextBox?
Eles são fragmentos de layout — um por linha de texto renderizada. Uma sentença que se quebra em duas linhas produz dois deles, em cima do nó StaticText que contém a mesma string. É por isso que 658 de 1.401 nós na página de teste eram duplicação de texto.

P: A árvore contém tudo na página?

Não exatamente. O conteúdo aria-hidden e o texto gerado por pseudo-elementos CSS são deliberadamente excluídos. Na página medida aqui nada do que era necessário estava faltando — o preço apareceu nas três representações — mas confirme isso em seu próprio alvo, em vez de assumir.

P: Eu preciso de um Chrome local para ler a árvore de acessibilidade?

Não. A execução na nuvem neste guia produziu números idênticos em byte ao Chromium local, porque ambos falam o mesmo protocolo. Apenas a linha de conexão muda.

Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.

Artigos mais populares

Catálogo