
Adélia Cruz
Neural Network Developer

Um agente de IA pode receber um registro aparentemente válido da página errada. Uma tela de login pode conter um título, um documento incompleto pode ser analisado com sucesso e um modelo pode retornar JSON mesmo quando os fatos solicitados estão ausentes. Uma arquitetura de raspagem de dados com IA precisa de decisões separadas para alcançar a fonte e interpretar seu conteúdo.
Este tutorial projeta essa fronteira em torno de um instantâneo imutável e um contrato de registro versado. O fluxo de trabalho se aplica à coleta autorizada de avisos públicos, atualizações de documentação e outras informações da web permitidas. CapSolver aparece como uma capacidade de suporte a CAPTCHA na camada de acesso. O exemplo executável mostra então como classificar os resultados da coleta, extrair um pequeno conjunto de registros e preservar evidências quando a validação falha.
A camada de acesso deve retornar um instantâneo utilizável ou uma falha explícita; a camada de extração deve retornar registros candidatos vinculados a esse instantâneo. Mantenha ambos os contratos estáveis mesmo quando o runtime do navegador, o analisador ou o modelo mudarem.
O pipeline é: solicitação de coleta aprovada → adaptador de acesso → instantâneo retido → adaptador de extração → validação → armazenamento de registros aceitos → agente. Nesse design, a extração pode ser executada novamente a partir de evidências armazenadas sem reabrir um navegador.
Forneça ao adaptador de acesso uma fonte aprovada, uma identidade de tarefa, um orçamento de tempo e um contexto de sessão permitido. Seu trabalho inclui escolher a representação necessária, esperar pelo conteúdo relevante, preservar a posse da sessão e classificar falhas. A configuração de rede e o renderização JavaScript pertencem à sua infraestrutura HTTP ou de navegador.
A saída deve registrar as localizações da fonte solicitada e final, o horário da observação, o tipo de representação, o resumo do conteúdo e a evidência de prontidão. Evite um único sinalizador de "sucesso" que esconda qual página realmente carregou. Um URL final e um status HTTP ajudam, mas também é necessário verificar a identidade do documento esperado e as regiões de conteúdo necessárias.
Forneça ao extrator uma referência ao instantâneo, a versão do esquema e as definições de campo. Ele não deve navegar silenciosamente, alterar credenciais ou selecionar outra rota de rede. Retorne campos ausentes ou ambíguos explicitamente em vez de pedir ao adaptador de acesso para continuar tentando até que algum valor apareça.
O glossário de raspagem de dados com IA descreve o uso mais amplo da IA na coleta e interpretação de informações da web. Essa fronteira também suporta extração determinística: atributos estáveis ou dados estruturados documentados podem ser suficientes. Use um modelo quando a interpretação for necessária, mantendo o mesmo contrato de validação posterior.
Um instantâneo utilizável deve conter a evidência necessária para os campos solicitados, em uma representação que o extrator compreenda. Selecione HTML, DOM renderizado ou uma captura de tela de acordo com esse requisito.
O HTML bruto é apropriado quando a resposta já contém o conteúdo relevante. Se os campos necessários aparecerem apenas após a execução do lado do cliente, um adaptador de navegador deve capturar o DOM renderizado após uma verificação de prontidão específica para a tarefa. Defina a prontidão como uma condição observável, como o contêiner esperado do registro e o marcador de conclusão, em vez de um sono fixo universal.
Registre qual representação foi capturada. Um analisador testado com marcação renderizada não deve receber uma estrutura HTML inicial sem uma mudança explícita no contrato. Se uma região necessária estiver ausente, classifique o instantâneo como incompleto antes de tentar a extração.
Uma captura de tela fornece pixels de uma viewport específica em um momento específico. Para extração baseada em captura de tela, retenha as dimensões da imagem, o contexto da captura e uma referência de região para cada campo extraído. Se um valor estiver fora da vista capturada, retorne-o como ausente; a familiaridade de um modelo com layouts semelhantes não é evidência para esse valor.
Não converta uma estimativa visual em um número exato sem registrar a incerteza. Onde ambas as evidências de DOM e visual estiverem disponíveis, use discordâncias como casos de revisão. O exemplo abaixo implementa apenas um adaptador de HTML; um adaptador de visão precisaria de suas próprias verificações de evidência e conjunto de avaliação.
A decisão de reiniciar deve nomear a camada falha, o benefício esperado de outra tentativa e o orçamento restante. Mantenha os reinícios de coleta e interpretação separados para que um erro de extração não crie tráfego não controlado.
| Observação | Camada responsável | Ação recomendada |
|---|---|---|
| Tempo limite de leitura ou erro temporário selecionado | Acesso | Reinicie apenas uma leitura permitida dentro de seu orçamento de tempo e tentativas |
| HTTP 429 ou cooldown solicitado pelo serviço | Acesso | Adie para um agendador compartilhado e preserve o sinal de cooldown |
| HTTP 401/403 ou autorização ambígua | Acesso | Parem e revisem o caminho de acesso permitido |
| Desafio de CAPTCHA reconhecido | Acesso | Parem para revisão de elegibilidade e tarefa compatível |
| Resposta vazia, documento incorreto ou região necessária ausente | Acesso | Retenha evidências diagnósticas e investigue a prontidão |
| Campo ausente, data inválida, registro duplicado ou incompatibilidade de esquema | Extração/validação | Quarantine o candidato e repita contra o instantâneo |
| Formato válido, mas significado não suportado | Validação | Rejeite ou solicite revisão; não trate texto fluido como evidência |
A semântica HTTP importa ao implementar a primeira linha. As regras de retry e idempotência do RFC 9110 distinguem operações que podem ser repetidas com segurança de operações cujos efeitos podem ser incertos. Não reutilize um loop de retry de leitura para submissões de formulário ou outras ações que mudem o estado.
O cabeçalho Retry-After pode expressar um atraso ou uma data HTTP. Preservar o valor para agendamento. Um trabalhador local não deve substituir um espera solicitada pelo servidor por um backoff mais curto, e trabalhadores compartilhando o mesmo escopo de coleta permitido devem compartilhar o estado de cooldown.
O CapSolver deve lidar apenas com uma tarefa de CAPTCHA documentada após seu fluxo de trabalho ter estabelecido permissão, compatibilidade de tarefa e contexto de sessão necessário. Uma resposta 403, uma página vazia e um widget de CAPTCHA são observações distintas; evite mapear todas elas para uma solicitação de solução.
O contrato createTask do CapSolver requer o objeto de tarefa apropriado. Para trabalho assíncrono, getTaskResult retorna o status e a saída da tarefa. O adaptador de acesso permanece responsável por aplicar a integração documentada e verificar o destino posteriormente.
Uma tarefa concluída não é um instantâneo de página validado. Reconfirme a identidade do documento e as condições de prontidão antes de entregar o conteúdo para extração. Estabeleça um orçamento separado para desafios e pare quando o desafio for incompatível, a autorização for ambígua ou a página esperada permanecer inacessível. A pilha de infraestrutura de navegador para agente de IA fornece orientação relacionada sobre posse de runtime e evidências de sessão.
Resgate seu Código de Bônus do CapSolver
Aumente seu orçamento de automação instantaneamente!
Use o código de bônus CAP26 ao recarregar sua conta do CapSolver para obter um bônus adicional de 5% em cada recarga — sem limites.
Resgate-o agora em seu Painel do CapSolver
O seguinte fluxo Python classifica respostas de acesso sintéticas, retém HTML aceito, extrai campos de anúncios e retorna JSON estruturado. Salve-o como pipeline_example.py e execute-o com Python 3.9 ou superior; ele usa apenas a biblioteca padrão.
A função fetch é um adaptador de leitura somente leitura. Aqui, ela fornece fixtures em memória, e a demonstração desativa o sono. Nenhum site, serviço de navegador, modelo ou API de CAPTCHA é acessado. Os campos challenge e ready representam observações fornecidas por um adaptador de acesso; o exemplo não implementa um detector de desafio universal.
O parser usa os callbacks do HTMLParser do Python para um contrato de marcação deliberadamente pequeno: cada article contém um h2, um ID de registro e uma data de publicação. Não é um analisador DOM geral ou validador para HTML malformado arbitrário.
from dataclasses import dataclass
from datetime import date
from hashlib import sha256
from html.parser import HTMLParser
import json
import time
class PipelineError(Exception):
def __init__(self, stage, reason, retry_after=""):
self.stage, self.reason = stage, reason
self.retry_after = retry_after
super().__init__(f"{stage}:{reason}")
@dataclass(frozen=True)
class Reply:
status: int
body: str = ""
content_type: str = "text/html"
challenge: bool = False
ready: bool = True
retry_after: str = ""
def access(fetch, wait=time.sleep):
# fetch is a read-only adapter; all values below are application policy.
for attempt in range(2):
try:
reply = fetch()
except TimeoutError:
if attempt == 0:
wait(0.5)
continue
raise PipelineError("access", "timeout_exhausted")
if reply.status == 429:
# Pass Retry-After to a shared scheduler; do not retry here.
raise PipelineError("access", "defer_rate_limit", reply.retry_after)
if reply.status in (401, 403):
raise PipelineError("access", "authorization_review")
if reply.challenge:
raise PipelineError("access", "challenge_review")
if reply.status == 503 and reply.retry_after:
raise PipelineError("access", "defer_service", reply.retry_after)
if reply.status in (502, 503, 504) and attempt == 0:
wait(0.5)
continue
if reply.status != 200:
raise PipelineError("access", "http_status")
if reply.content_type.split(";")[0].strip().lower() != "text/html":
raise PipelineError("access", "representation_mismatch")
if not reply.ready or not reply.body.strip():
raise PipelineError("access", "incomplete_snapshot")
return reply.body
raise PipelineError("access", "attempts_exhausted")
class BulletinParser(HTMLParser):
# This small parser supports only the documented fixture markup.
def __init__(self):
super().__init__(convert_charrefs=True)
self.rows, self.current, self.in_title = [], None, False
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == "article":
if self.current is not None:
raise PipelineError("extraction", "nested_record")
self.current = {"id": attrs.get("data-id", ""),
"published": attrs.get("data-published", ""),
"title_parts": [], "title_count": 0}
elif tag == "h2" and self.current is not None:
self.current["title_count"] += 1
self.in_title = True
def handle_data(self, data):
if self.current is not None and self.in_title:
self.current["title_parts"].append(data)
def handle_endtag(self, tag):
if tag == "h2":
self.in_title = False
if tag == "article" and self.current is not None:
self.rows.append(self.current)
self.current, self.in_title = None, False
def extract(html):
parser = BulletinParser()
parser.feed(html)
parser.close()
if parser.current is not None or not parser.rows:
raise PipelineError("extraction", "record_structure")
records, seen = [], set()
for row in parser.rows:
title = " ".join("".join(row["title_parts"]).split())
if not row["id"].strip() or not title or row["title_count"] != 1:
raise PipelineError("extraction", "required_field")
try:
published = date.fromisoformat(row["published"]).isoformat()
except ValueError:
raise PipelineError("extraction", "invalid_date")
if row["id"] in seen:
raise PipelineError("extraction", "duplicate_id")
seen.add(row["id"])
records.append({"id": row["id"], "title": title,
"published": published})
return records
def run(fetch, archive, wait=time.sleep):
html = access(fetch, wait)
digest = sha256(html.encode("utf-8")).hexdigest()
archive[digest] = html # In-memory evidence retained even if parsing fails.
records = extract(html)
return {"schema_version": "bulletins.v1", "source_id": "fixture:bulletins",
"snapshot_sha256": digest,
"records": records}
if __name__ == "__main__":
html = ('<article data-id="notice-1" data-published="2026-09-10">'
'<h2>Maintenance window announced</h2></article>')
replies = iter([Reply(503), Reply(200, html)])
archive = {}
output = run(lambda: next(replies), archive, wait=lambda seconds: None)
print(json.dumps(output, indent=2))
A demonstração recebe uma resposta 503 sintética seguida por uma resposta HTML elegível. Ela produz este resultado:
{
"schema_version": "bulletins.v1",
"source_id": "fixture:bulletins",
"snapshot_sha256": "6ed8df5a98ee53e2889feb5ef7ed4dd8d549dba82882580418d4ca9656b7d46b",
"records": [
{
"id": "notice-1",
"title": "Maintenance window announced",
"published": "2026-09-10"
}
]
}
Cada registro deve ter um ID, um título não vazio e uma data analisável. IDs duplicados rejeitam o lote. O resumo de instantâneo conecta a saída ao HTML retido, e erros de extração deixam esse HTML no arquivamento de propriedade do chamador para replay.
O limite de tentativas de 2 e o atraso de meio segundo são políticas de exemplo da aplicação, não recomendações do provedor. O loop adia imediatamente um 429, preserva um cooldown de 503 e para em caso de autorização ou revisão de desafio. Um erro em extract não pode chamar fetch novamente.
Implemente admissão de fonte, verificação de redirecionamento, decodificação de conteúdo suportada, timeout por solicitação e um prazo geral antes de conectar o exemplo a um transporte real. Um fetch síncrono que nunca retorna não é limitado por um contador de tentativas. Passe o prazo restante para o transporte e inclua os intervalos de repetição nesse orçamento.
Substitua o arquivamento em memória por armazenamento controlado e adicione horários de observação, identidade real da fonte, versão do extrator e versão do esquema aos metadados. Aplicar limites de tamanho antes da decodificação ou análise. Um instantâneo falho ou incompleto pode ainda ser evidência diagnóstica útil, mas mantenha-o separado do conjunto de instantâneos elegíveis para extração.
Dados aceitos precisam de verificações de significado e cobertura além da estrutura JSON. O exemplo valida seu contrato pequeno e determinístico; um serviço de extração geral precisa de uma política de aceitação mais rica.
Comece com definições de campo. Uma data de publicação, data de atualização e timestamp de coleta descrevem eventos diferentes. Especifique qual o agente precisa e rejeite substituições. Para campos gerados por modelo, anexe uma faixa de origem ou região visual e verifique se a evidência apoia o significado do campo. Uma palavra correspondente em algum lugar da página é fraca demais para campos como preço, disponibilidade ou data.
Verifique a completude no nível de coleta. Um array vazio pode significar "nenhum registro", mudança de layout, paginação incompleta ou falha na extração. Aceite um resultado vazio apenas quando a fonte fornece um estado vazio explícito e verificado. O exemplo rejeita uma lista vazia porque não tem esse contrato.
Defina uma janela de frescor para a tarefa. Reextrair um instantâneo antigo pode corrigir um problema no parser, mas não torna a observação subjacente atual. Inclua identidade do instantâneo e versões do extrator/esquema na chave de replay, depois publique os registros aceitos por meio de uma operação de armazenamento idempotente. Mantenha os candidatos rejeitados disponíveis para revisão limitada em vez de misturá-los ao conjunto de trabalho do agente.
Trate o conteúdo da página como entrada não confiável em todo o processo. As orientações de injeção de prompt da OWASP descrevem riscos de instruções embutidas em conteúdo externo. Mantenha ferramentas de extração isoladas de credenciais e ações significativas; o texto da fonte não deve adquirir autoridade para alterar o escopo da coleta ou enviar dados para outro lugar.
Testes de limites devem verificar tanto o resultado retornado quanto a ausência de trabalho extra não desejado. Um teste de parser que passa não comprova que a camada de acesso pare corretamente.
Para este exemplo, teste um timeout seguido de sucesso, erros temporários repetidos, uma resposta 200 marcada como desafio, um 429 com período de espera, uma representação não suportada, títulos ausentes, datas inválidas e IDs duplicados. Conte as chamadas do adaptador: o caso de desafio deve parar após uma chamada e uma falha na análise deve preservar o instantâneo sem outra tentativa de acesso.
A suite de testes local correspondente passou 21 testes para o pipeline de fixture, incluindo exaustão de tentativas, preservação de cooldown, retenção de instantâneos e replay determinístico. Esses são testes de software sintético, não taxa de sucesso de fonte ao vivo ou benchmark de extração de modelo.
Antes da implantação, adicione uma pequena fonte permitida e teste a prontidão para renderização real, tratamento de redirecionamento, expiração de sessão, cancelamento de transporte e evidência de saída. Meça instantâneos elegíveis e registros aceitos separadamente. Essa divisão lhe diz se deve melhorar a aquisição ou interpretação quando a taxa de aceitação final mudar.
Uma arquitetura de coleta de web para agente de IA se torna mais fácil de operar quando cada etapa tem uma saída observável e um proprietário claro. Mantenha o contrato de acesso focado em instantâneos elegíveis, o contrato de extração focado em campos candidatos e a validação focada em evidência, completude e frescor.
Comece com o fluxo local, execute os caminhos negativos e conecte uma fonte permitida apenas após os limites do adaptador estarem explícitos. Para fluxos que precisam de tratamento documentado de CAPTCHA, avalie CapSolver dentro desse limite de acesso e verifique o destino antes que a extração retome.
Q: Qual é a diferença entre uma camada de acesso à web e uma camada de extração de dados?
A camada de acesso obtém um instantâneo de página elegível e classifica falhas na aquisição. A camada de extração interpreta esse instantâneo em campos candidatos. Uma verificação de aceitação separada determina se os registros resultantes são adequados para o agente.
Q: Um modelo de IA deve receber HTML, um instantâneo do DOM ou uma captura de tela?
Use a representação que contenha evidência para os campos solicitados. HTML pode ser adequado para conteúdo fornecido pelo servidor, DOM renderizado pode capturar conteúdo do lado do cliente e capturas de tela podem apoiar interpretação visual com referências de região e verificações de incerteza.
Q: Um campo ausente deve causar outra solicitação de página?
Um campo ausente deve primeiro acionar revisão ou reextração do instantâneo retido. Solicite uma nova página apenas quando a evidência mostrar que o instantâneo é incompleto ou obsoleto e a política de acesso permitir outra tentativa.
Q: Onde o CapSolver se encaixa nessa arquitetura?
O CapSolver se encaixa em uma interface de tarefa de CAPTCHA suportada na camada de acesso para fluxos autorizados. Sua aplicação detém a elegibilidade da tarefa, contexto da sessão, orçamento de repetição e validação do destino após a conclusão da tarefa.
Q: O exemplo em Python realiza coleta de web com IA ao vivo?
Não. O exemplo executa um pipeline de fixture HTML localmente e testa seus contratos. Uma implantação ao vivo deve adicionar um adaptador de acesso permitido; extração baseada em modelo ou visual também precisa de sua própria implementação e avaliação baseada em evidência.
Avaliar serviços de CAPTCHA para empresas com um piloto focado que abrange compatibilidade das tarefas, resultados aceitos, atribuição de custos, evidências de segurança e suporte.

Use uma lista de verificação do servidor MCP de produção para revisar permissões das ferramentas, isolamento de inquilinos, entradas, tratamento de falhas, registros e evidências de lançamento antes da implantação.
