Durante vinte anos, extrair dados de páginas web significava escrever seletores: encontrar o elemento, capturar o texto, corrigir quando o site muda. Os modelos de linguagem de grande escala oferecem um acordo diferente. Dê ao modelo a página, descreva os campos que você quer, e receba dados estruturados de volta, sem seletores para escrever e nenhum para quebrar numa reformulação.
O acordo é real, mas tem um preço, uma velocidade e um modo de falha, e os três valem a pena ser medidos antes de reconstruir um pipeline em torno disso. Então nós os medimos. Este texto relata um teste pequeno e honesto em páginas reais, o que os erros revelaram, quanto custa em escala, e onde um modelo se encaixa num pipeline de extração.
Principais conclusões
- Em 18 artigos de notícias reais, um modelo Claude de grande porte extraiu todos os títulos com exatidão, 17 de 18 datas e 14 de 18 listas de autores, avaliados em comparação com os dados estruturados da própria página.
- A maioria dos “erros” não foram erros do modelo. Em toda página em que os autores divergiam, os dados estruturados traziam um placeholder genérico; em duas delas o modelo relatou a assinatura que a página visível realmente mostrava.
- O modelo não inventou nada: todo título e autor que ele retornou aparece no texto da página. Ainda assim, cometeu um erro real, atribuindo a autoria a um fotógrafo.
- Custou cerca de 1,9 centavo de dólar por página no preço de tabela e levou uma mediana de 2,4 segundos. Fazer o parsing de dados estruturados custa quase nada e leva milissegundos.
- Use modelos onde seletores são caros de manter, como muitos templates de site diferentes ou campos sem fonte estruturada, e valide tudo o que eles retornam.
O que testamos
| Configuração | Valor |
|---|---|
| Páginas | 18 artigos reais das seções principais de um grande veículo de notícias, coletados em 28 de setembro de 2026 |
| Entrada do modelo | O texto visível da página, incluindo navegação e outros elementos de página, com média de cerca de 8.700 caracteres |
| Campos | Título, data de publicação como exibida na página, e nomes dos autores |
| Modelo | Claude Opus 5, com esforço baixo, com um schema JSON restringindo a saída |
| Gabarito | Os próprios dados estruturados JSON-LD da mesma página |
| Pontuação | Título e data devem coincidir exatamente; listas de autores devem coincidir como conjuntos |
O gabarito é deliberadamente o tipo de dado abordado em pare de fazer parsing de HTML: os dados estruturados que os veículos embutem para os motores de busca. Geralmente estão corretos. Como se constatou, não sempre.
Resultados
| Medida | Resultado |
|---|---|
| Título correto | 18 de 18 |
| Data correta | 17 de 18 |
| Autores corretos | 14 de 18 |
| Valores extraídos encontrados no texto da página | 18 de 18 títulos, 18 de 18 listas de autores |
| Tokens por página | cerca de 3.380 de entrada, 66 de saída |
| Latência | mediana de 2,4 s, faixa de 1,8 a 10,6 s |
| Custo da execução | US$ 0,33 no preço de tabela, cerca de 1,9 centavo de dólar por página |
Os erros foram a parte interessante
Os números do título subestimam o modelo e sobrestimam o gabarito. Olhando cada discordância:
- Uma coluna de opinião. Os dados estruturados listavam o autor como um placeholder genérico de repórter da equipe. A assinatura visível nomeava o colunista real. O modelo retornou o colunista.
- Uma matéria de agência. Os dados estruturados novamente traziam o placeholder genérico; a assinatura visível dizia “Staff and agencies”. O modelo retornou o que a página mostrava.
- Uma página de inscrição para newsletter que havia entrado no conjunto por engano. Ela não mostrava autor nem data. Os dados estruturados forneciam um autor genérico e uma data mesmo assim; o modelo deixou os dois campos vazios em vez de inventar.
- Um ensaio fotográfico. Os dados estruturados traziam o mesmo placeholder genérico. A página atribuía as fotografias a um fotógrafo nomeado, e o modelo retornou o fotógrafo como autor. Esse é um erro genuíno.
Assim, das quatro páginas com discordância, duas refletiam o gabarito sendo menos preciso que a página visível, uma foi o modelo corretamente se recusando a adivinhar, e uma foi um erro real. Isso muda a pergunta que vale fazer. Dados estruturados são um padrão sólido, mas não são a verdade absoluta, e um modelo lendo a página visível pode identificar onde eles estão errados, assim como pode ocasionalmente interpretar mal o que vê.
Quanto custa em escala
O teste custou US$ 0,33 para 18 páginas no preço de tabela do Claude Opus 5 de US$ 5 por milhão de tokens de entrada e US$ 25 por milhão de tokens de saída. Isso equivale a cerca de 1,9 centavo de dólar por página, o que dá aproximadamente US$ 18.600 por milhão de páginas. A Batch API da Anthropic reduz esses preços de token à metade para trabalhos que podem esperar. Modelos menores são mais baratos por token novamente, o Claude Haiku 4.5 está listado a US$ 1 e US$ 5, mas não os testamos aqui, e a precisão deles nas suas páginas é algo a ser medido, não presumido.
A latência também importa. Uma mediana de 2,4 segundos por página, com pontos fora da curva ocasionais, é adequada para monitoramento e enriquecimento e uma restrição real para rastreamento de alto volume. Fazer o parsing de JSON-LD ou executar seletores leva milissegundos e custa efetivamente nada além da busca. Esses custos de extração se somam aos custos de coleta, motivo pelo qual custo por registro limpo deveria incluir ambos.
Quando usar qual
| Situação | Melhor abordagem |
|---|---|
| A página publica os campos em JSON-LD ou JSON embutido | Faça o parsing dos dados estruturados |
| Alto volume de um ou poucos templates de site | Seletores ou dados estruturados, com validação |
| Muitos sites diferentes, cada um com seu próprio template | Um modelo, validado, possivelmente gerando seletores que você depois reaproveita |
| Campos que só existem em texto corrido, como termos, elegibilidade ou especificações | Um modelo |
| Dados estruturados falham na validação numa página | Um modelo como alternativa |
| Baixo volume, alto valor, mudança frequente de layout | Um modelo |
Os pipelines mais robustos combinam os dois. Faça o parsing dos dados estruturados primeiro, recorra a um modelo quando um campo obrigatório estiver ausente ou falhar na validação, e registre qual método produziu cada registro, o mesmo padrão de cadeia de alternativas descrito para dados estruturados. Onde um template de site cobre milhares de páginas, também pode valer a pena ter um modelo propondo seletores uma vez e executar esses seletores de forma barata em cada página, com o modelo em espera para quando eles quebrarem.
Usando um modelo com segurança
Quatro práticas transformam a extração por modelo de impressionante em confiável.
Restrinja a saída. Um schema JSON faz o modelo retornar os campos e tipos que você pediu; ainda assim, verifique o motivo de parada, já que uma resposta recusada ou truncada não tem nada para ser interpretado. Instrua o modelo a deixar um campo vazio quando a página não o mostra; em nosso teste, foi exatamente isso que ele fez.
Verifique o embasamento. Toda string extraída que deveria aparecer na página, como um nome, um título ou o nome de um produto, deve ser encontrada no texto da página. É uma verificação barata que pega valores inventados. Ela não vai pegar um nome real atribuído ao campo errado, como mostra o caso do fotógrafo, então é um filtro, não uma prova.
Faça amostragem para revisão humana. Avalie uma pequena amostra aleatória a cada semana em comparação com a leitura de uma pessoa da página, e acompanhe a precisão por campo e por site ao longo do tempo.
Trate o texto da página como entrada não confiável. Uma página é escrita por outra pessoa. Use modelos em conteúdo web apenas para extração, nunca deixe o conteúdo da página desencadear ações, e mantenha as instruções do modelo separadas do conteúdo da página.
Esta é a chamada de extração que usamos, seguida da verificação de embasamento:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const SCHEMA = {
type: "object",
properties: {
headline: { type: "string" },
date_published: { type: "string", description: "YYYY-MM-DD, as shown on the page" },
authors: { type: "array", items: { type: "string" } },
},
required: ["headline", "date_published", "authors"],
additionalProperties: false,
};
export async function extractArticle(pageText) {
const response = await client.beta.messages.create({
model: "claude-opus-5",
max_tokens: 2000,
betas: ["server-side-fallback-2026-07-01"],
fallbacks: "default",
output_config: { effort: "low", format: { type: "json_schema", schema: SCHEMA } },
messages: [{
role: "user",
content:
"Below is the visible text of a news article web page, including navigation and other page furniture. " +
"Extract the article's headline exactly as written, its publication date as shown on the page (YYYY-MM-DD), " +
"and the author names. Leave a field empty if the page does not show it.\n\n<page>\n" + pageText + "\n</page>",
}],
});
if (response.stop_reason === "refusal") return null;
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
return { record: JSON.parse(text), usage: response.usage };
}
// Grounding check: every extracted string must actually appear in the page text.
export function grounded(record, pageText) {
const norm = (s) => s.replace(/[‘’]/g, "'").replace(/[“”]/g, '"').replace(/\s+/g, " ").toLowerCase();
const page = norm(pageText);
return {
headline: page.includes(norm(record.headline)),
authors: record.authors.every((a) => page.includes(norm(a))),
};
}
A entrada importa tanto quanto o modelo. Um modelo só pode extrair o que a página realmente contém, então uma página de bloqueio, um aviso de consentimento ou uma casca vazia produz uma extração confiante do conteúdo errado. Valide o que você buscou antes de extrair dele, como abordado em a taxa de falha silenciosa, e busque a partir do mercado cuja versão da página você precisa.
Os limites deste teste
Dezoito páginas de um único veículo é uma amostra pequena, escolhida para ser honesta em vez de definitiva. Artigos de notícias também são um caso fácil: títulos claros, assinaturas visíveis, datas bem identificadas. Páginas de produtos com variantes, preços e disponibilidade, ou páginas em outros idiomas, se comportarão de forma diferente. Testamos um modelo em um nível de esforço. O método é simples de repetir nas suas próprias páginas, e suas próprias páginas são o único benchmark que importa.
Conclusão
Um modelo lendo a página acertou todos os títulos, não inventou nada, e em vários casos relatou a página de forma mais fiel do que os próprios dados estruturados da página. Também atribuiu erroneamente um autor uma vez, custou centavos em vez de fração de centavo, e levou segundos em vez de milissegundos.
Isso o torna uma ferramenta forte para as partes da extração que os seletores lidam mal: muitos templates, campos apenas em texto corrido e alternativas para quando os dados estruturados falham. Não é um substituto para dados estruturados onde dados estruturados existem. Faça o parsing do que a página publica, recorra a um modelo onde não publica, valide ambos, e registre qual dos dois você usou.
Fontes e referências
- Anthropic, Preços. Preços de modelo e Batch API no momento do teste.
- Schema.org, NewsArticle.
- Teste realizado pela Shifter em 28 de setembro de 2026 com 18 artigos de notícias publicamente acessíveis, usando o código acima.