🎯 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

Forneça uma Pesquisa na Web Local LLM Ao Vivo com Ollama + Scrapeless

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

14-Jul-2026

Um modelo em execução na sua própria máquina não sabe nada além de seu limite de treinamento. Pergunte a um Llama local, Qwen ou um ponto de verificação Mistral sobre uma manchete desta semana e ele ou se recusa ou, pior, afirma algo plausível e errado. O perfil de risco de IA Generativa do NIST tem um nome para o segundo modo de falha: confabulação, definido como um sistema que "gera e apresenta de forma confiante conteúdo errado ou falso em resposta a solicitações." Um modelo sem acesso a dados atuais não pode evitá-lo quando a pergunta é sobre o dia de hoje.

A solução não é um modelo maior. É uma ferramenta de busca que o modelo pode chamar, conectada a uma API de busca que retorna resultados reais, com os resultados alimentados de volta na mesma conversa antes que o modelo escreva sua resposta final. Este guia conecta esse padrão do início ao fim: Ollama executando um modelo que chama ferramentas inteiramente em seu próprio hardware, e Scrapeless Deep SerpApi como o backend de busca que o modelo utiliza. Cada solicitação e resposta mostrada abaixo é uma execução real capturada, não uma transcrição simulada.

O Que Esta Integração Permite

Um modelo local com uma ferramenta de busca anexada pode responder a perguntas cujos pesos sozinhos não conseguem:

  • Eventos atuais e preços. Um modelo treinado há meses não pode conhecer os números deste trimestre; uma chamada de busca ao vivo pode.
  • Verificação de fatos de sua própria recordação. O modelo declara uma resposta, então uma chamada de busca confirma ou corrige antes que a resposta final seja enviada.
  • Agentes offline-primeiro com uma dependência de rede estreita. Tudo — os pesos, o raciocínio, a lógica de seleção da ferramenta — é executado na máquina local. A única chamada de saída é a própria solicitação de busca, restrita exatamente à consulta que o modelo escolheu fazer.
  • Modelos pequenos superando seus dados de treinamento. O modelo neste guia possui 0,5 bilhão de parâmetros. Não precisa saber nada sobre missões a Marte; precisa reconhecer que a pergunta exige uma busca e formular uma consulta razoável.

Por Que Deep SerpApi para a Ferramenta de Busca

Ollama oferece seu próprio recurso de busca hospedado (ollama.com/api/web_search), e é um padrão razoável para um protótipo rápido. Também requer uma conta Ollama, uma OLLAMA_API_KEY, e roteia cada consulta pela própria nuvem do Ollama — o modelo permanece local, mas a etapa de busca não fica fora da infraestrutura do Ollama mais do que ficaria com qualquer outro fornecedor de busca hospedado. Seu limite padrão documentado é de 5 resultados por chamada, 10 no máximo.

Deep SerpApi é um endpoint de busca estruturada dedicado: um POST autenticado retorna os resultados orgânicos do Google, buscas relacionadas, paginação e (dependendo da consulta) dados de vídeo e painel de conhecimento em JSON analisado — não um resumo reduzido. A própria página de produto da Scrapeless lista cobertura em "20+ cenários de SERP do Google e motores de busca principais" (Busca, Notícias, Mapas, Compras, Tendências e mais), tempos de resposta de "1-2 segundos", e um nível gratuito de "2.000 Chamadas de API Gratuitas" sem cartão necessário. O uso pago varia de "apenas $1,05/1K consultas." Se um projeto já depende da Scrapeless para outro trabalho de coleta de dados, ou precisa do esquema de resultados orgânicos mais completo em vez de um resumo curto, conectar a chave Deep SerpApi da mesma conta no loop de chamada de ferramentas mantém um provedor e uma conta em vez de dois.

Obtenha uma chave de API gratuita inscrevendo-se — sem cartão necessário: app.scrapeless.com.

Pré-requisitos

  • Uma máquina Linux, macOS ou WSL2 com pelo menos 2 GB de RAM livre (o modelo deste guia precisa de bem menos de 1 GB uma vez carregado; uma GPU é opcional e apenas acelera a inferência).
  • curl e Python 3.9 ou mais recente.
  • Uma conta Scrapeless e uma chave de API da página de Gerenciamento de Chaves de API do painel.
  • Sem conta Ollama e sem OLLAMA_API_KEY — este caminho nunca chama o serviço hospedado do Ollama.

Instalar e Executar um Modelo que Chama Ferramentas Localmente

Instale o Ollama:

bash Copy
curl -fsSL https://raw.githubusercontent.com/ollama/ollama/main/scripts/install.sh | sh

Em um host Linux gerenciado pelo systemd (incluindo WSL2 com systemd habilitado), o instalador registra e inicia um serviço ollama automaticamente, ouvindo em 127.0.0.1:11434. Confirme o binário e o serviço:

bash Copy
ollama --version
# a versão do ollama é 0.31.2

Baixe um modelo pequeno capaz de chamar ferramentas. Os pontos de verificação ajustados para instrução do Qwen2.5 suportam chamadas de função até o tamanho de 0,5 bilhão de parâmetros, o que mantém o download e o espaço de memória pequenos:

bash Copy
ollama pull qwen2.5:0.5b

O ollama list em seguida confirma que o modelo é local: uma entrada de 397 MB chamada qwen2.5:0.5b, pronta para atender sem qualquer acesso à rede adicional.
Nem todo modelo executável localmente suporta a chamada de ferramentas — verifique a página de um modelo na biblioteca da Ollama em busca de uma tag "Ferramentas" antes de construir um loop de agente ao redor dele. Modelos maiores como Qwen2.5, Llama 3.1 e pontos de verificação Mistral carregam a mesma tag se 0.5B provar ser pequeno demais para uma determinada tarefa.

Obtenha uma chave API do Scrapeless gratuita enquanto o modelo é baixado — sem necessidade de cartão: app.scrapeless.com.

Verifique o Endpoint Deep SerpApi

Deep SerpApi assume uma forma para cada cenário: um nome de ator mais um objeto input, documentado em docs.scrapeless.com. O cenário de busca no Google usa o ator scraper.google.search:

bash Copy
curl -s -X POST "https://api.scrapeless.com/api/v1/scraper/request" \
  -H "x-api-token: $SCRAPELESS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "actor": "scraper.google.search",
    "input": {"q": "últimas notícias sobre a missão de Retorno da Amostra de Marte", "gl": "us", "hl": "pt"}
  }'

Uma chamada ao vivo para essa consulta retorna HTTP 200 com um corpo JSON contendo estes campos de nível superior: organic_results, pagination, related_searches, search_information, inline_videos, video_results e metadata. Cada entrada em organic_results contém position, title, link, redirect_link, favicon, snippet, snippet_highlighted_words e source. A resposta é um simples JSON — sem streaming, sem sessão para manter aberta, um pedido entrando e um documento saindo. Um pedido que não terminou do lado do servidor retorna HTTP 201 com um taskId; o caso ordinário para uma consulta de busca no Google é o síncrono 200 mostrado acima.

Defina e Anexe a Ferramenta de Busca

O endpoint /api/chat da Ollama aceita uma matriz tools moldada como definições de função JSON Schema. Defina uma ferramenta, web_search, e passe-a junto com a conversa:

python Copy
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "web_search",
            "description": "Pesquisar na web ao vivo por informações atuais e retornar os principais resultados orgânicos com títulos, links e trechos.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "A consulta de pesquisa"}
                },
                "required": ["query"],
            },
        },
    }
]

Anexe TOOLS a cada pedido /api/chat para que o modelo sempre saiba que a ferramenta existe:

python Copy
import json
import urllib.request

OLLAMA_URL = "http://127.0.0.1:11434/api/chat"
MODEL = "qwen2.5:0.5b"

def ollama_chat(messages):
    body = json.dumps({"model": MODEL, "stream": False, "messages": messages, "tools": TOOLS}).encode()
    req = urllib.request.Request(OLLAMA_URL, data=body, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=180) as resp:
        return json.load(resp)

O modelo nunca chama a Deep SerpApi em si — ele apenas emite uma entrada tool_calls nomeando web_search com os argumentos que escolheu. Uma função Python leve faz o trabalho HTTP real e devolve o resultado moldado:

python Copy
import os

def web_search(query: str) -> str:
    body = json.dumps({
        "actor": "scraper.google.search",
        "input": {"q": query, "gl": "us", "hl": "pt"},
    }).encode()
    req = urllib.request.Request(
        "https://api.scrapeless.com/api/v1/scraper/request",
        data=body,
        headers={
            "x-api-token": os.environ["SCRAPELESS_API_KEY"],
            "Content-Type": "application/json",
        },
    )
    with urllib.request.urlopen(req, timeout=60) as resp:
        data = json.load(resp)
    results = data.get("organic_results", [])[:3]
    shaped = [
        {"title": r.get("title"), "link": r.get("link"), "snippet": r.get("snippet")}
        for r in results
    ]
    return json.dumps(shaped)

Recortar para os três principais resultados antes de retornar a saída da ferramenta mantém a segunda chamada /api/chat pequena — um modelo com 0,5 bilhão de parâmetros tem uma janela de contexto limitada, e a resposta completa contém links de paginação, favicons e blocos de pesquisas relacionadas que o modelo não precisa para responder à pergunta.

Uso Orientado por Prompt: Observando o Modelo Decidir

Coloque as peças juntas: envie um prompt que necessita de informações atuais, deixe o modelo solicitar a ferramenta, execute esse pedido contra a Deep SerpApi e envie o resultado de volta para uma resposta final fundamentada.

python Copy
import json
import os
import urllib.request

OLLAMA_URL = "http://127.0.0.1:11434/api/chat"
SCRAPELESS_URL = "https://api.scrapeless.com/api/v1/scraper/request"
MODEL = "qwen2.5:0.5b"

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "web_search",
            "description": "Pesquise na web ao vivo por informações atuais e retorne os principais resultados orgânicos com títulos, links e trechos.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "A consulta de pesquisa"}
                },
                "required": ["query"],
            },
        },
    }
]

def ollama_chat(messages):
    body = json.dumps({"model": MODEL, "stream": False, "messages": messages, "tools": TOOLS}).encode()
    req = urllib.request.Request(OLLAMA_URL, data=body, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=180) as resp:
        return json.load(resp)

def web_search(query: str) -> str:
    body = json.dumps({
        "actor": "scraper.google.search",
        "input": {"q": query, "gl": "us", "hl": "en"},
    }).encode()
    req = urllib.request.Request(
        SCRAPELESS_URL,
        data=body,
        headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"], "Content-Type": "application/json"},
    )
    with urllib.request.urlopen(req, timeout=60) as resp:
        data = json.load(resp)
    results = data.get("organic_results", [])[:3]
    return json.dumps([
        {"title": r.get("title"), "link": r.get("link"), "snippet": r.get("snippet")}
        for r in results
    ])

messages = [{"role": "user", "content":
    "Quais são as últimas manchetes sobre a missão de Retorno de Amostras de Marte hoje? "
    "Use a ferramenta de busca se precisar de informações atuais."}]

first_turn = ollama_chat(messages)
print(json.dumps(first_turn["message"], indent=2))

tool_call = first_turn["message"]["tool_calls"][0]
query = tool_call["function"]["arguments"]["query"]
result = web_search(query)

messages.append(first_turn["message"])
messages.append({"role": "tool", "content": result, "tool_name": "web_search"})

second_turn = ollama_chat(messages)
print(json.dumps(second_turn["message"], indent=2))

Uma execução ao vivo contra qwen2.5:0.5b imprime isto na primeira rodada — ainda sem resposta final, apenas um pedido de ferramenta:

json Copy
{
  "role": "assistant",
  "content": "",
  "tool_calls": [
    {
      "id": "call_dwndere1",
      "function": {
        "index": 0,
        "name": "web_search",
        "arguments": {
          "query": "Últimas Manchetes da Missão de Retorno de Amostras de Marte"
        }
      }
    }
  ]
}

O modelo leu o prompt, reconheceu que precisava de informações atuais e escolheu sua própria consulta de pesquisa — a formulação desta execução veio do modelo, não de uma cópia da frase do usuário. O código de chamada executa web_search(query="Últimas Manchetes da Missão de Retorno de Amostras de Marte") contra o Deep SerpApi, recebe três resultados moldados e os adiciona como uma mensagem de role: "tool" antes de enviar a conversa para /api/chat uma segunda vez.

O Que Você Recebe de Volta

A segunda instrução print é a resposta real do modelo, fundamentada no que a chamada de busca retornou:

json Copy
{
  "role": "assistant",
  "content": "Aqui estão algumas das últimas manchetes sobre a missão de Retorno de Amostras de Marte:\n\n- [Retorno de Amostras de Marte - Missões de Marte](https://www.jpl.nasa.gov/missions/mars-sample-return-msr/)\n  - Este link leva você ao site da NASA que contém informações sobre o programa de Retorno de Amostras de Marte.\n- [Retorno de Amostras de Marte da NASA-ESA](https://en.wikipedia.org/wiki/NASA-ESA_Mars_Sample_Return)\n  - A página da Wikipédia sobre o projeto também está disponível, fornecendo informações mais detalhadas sobre a missão e seus custos.\n\nAqui estão alguns links para artigos relacionados à missão de Retorno de Amostras de Marte:\n\n1. [O Retorno de Amostras de Marte da NASA Está Morto, Abrindo Caminho Para a China](https://www.universetoday.com/articles/nasas-mars-sample-return-is-dead-paving-the-way-for-china/)\n  - Este artigo fornece mais informações sobre o status atual da missão de Retorno de Amostras de Marte.\n\nEspero que isso ajude! Deixe-me saber se você precisa de outros artigos ou atualizações."
}

Cada link nessa resposta remete a um dos três resultados que web_search realmente retornou — o modelo resumiu e reorganizou-os em sua própria lista, em vez de inventar algo novo desta vez. Isso não é uma garantia: um modelo com 0,5 bilhões de parâmetros ainda pode produzir um detalhe com aparência plausível que nunca esteve no resultado da ferramenta, mesmo com resultados de pesquisa reais sentados em seu contexto. A fundamentação reduz as chances de que isso aconteça; não as elimina, e um sistema de produção que extrai links da resposta de um modelo deve verificar cada um contra a saída da ferramenta antes de tratar como fato. O mesmo padrão de pedido e resposta se mantém independentemente do tópico da consulta: o modelo decide quando pesquisar, a chamada da ferramenta é a única viagem de rede que os próprios pesos do modelo não possuem, e a segunda conclusão nunca é executada até que o resultado da ferramenta esteja na conversa.

Conclusão

Conectar um modelo local à Deep SerpApi envolveu uma definição de ferramenta, uma função HTTP e duas chamadas de /api/chat — o modelo gerencia o raciocínio sobre quando pesquisar e o que perguntar, da mesma forma que um framework de agente de modelo hospedado faria, mas cada token de geração permanece na máquina que o executa. O padrão se expande além deste único exemplo: troque o prompt, troque o modelo ou amplie TOOLS com mais funções, e o mesmo loop de chamada-para-ferramenta-resposta mantém o resto.

Comece grátis — sem cartão necessário: app.scrapeless.com. Referência completa de parâmetros em docs.scrapeless.com, e preços atuais por consulta em scrapeless.com/en/pricing. Para a diferença entre um endpoint SERP como este e os atores da Scrapeless que capturam as próprias respostas de uma plataforma de IA hospedada, veja a comparação SERP-API versus LLM-scraper.

FAQ

P: Quais modelos locais suportam chamadas de ferramenta?

Qualquer modelo classificado como "Tools" na biblioteca de modelos da Ollama funciona com este padrão. Qwen2.5 (até 0.5B), Llama 3.1 e 3.2, Mistral e IBM Granite oferecem checkpoints capazes de chamadas de ferramenta. Um modelo sem essa etiqueta pode ainda emitir JSON no formato de tool_calls como texto simples, que o código de chamada deve analisar manualmente em vez de ler um campo estruturado — verifique a etiqueta antes de construir em torno de um determinado modelo.

P: Alguma disso requer uma conexão com a internet para o próprio modelo?

Não. O modelo, o prompt e o raciocínio são executados na máquina local. A única solicitação de saída é a chamada de ferramenta web_search para a Deep SerpApi, limitada exatamente à consulta que o modelo gerou — nada mais sobre a execução toca a rede.

P: Por que não usar a busca na web integrada da Ollama em vez de uma chave de API separada?

A busca hospedada da Ollama (ollama.com/api/web_search) é uma opção legítima para um protótipo rápido, e não precisa de uma conta separada além da própria Ollama. Ela exige uma OLLAMA_API_KEY vinculada a uma conta gratuita da Ollama, limita os resultados a 10 por chamada e retorna uma lista de resultados genérica em vez do esquema completo de resultados orgânicos do Google (posições, pesquisas relacionadas, paginação, verticais). A Deep SerpApi é a melhor escolha quando um projeto precisa desse esquema mais completo, cenários não-Google-Search, ou já executa outros trabalhos através de uma conta Scrapeless.

P: O que acontece se a chamada de pesquisa falhar?

Uma solicitação malformada retorna HTTP 400; uma chave de API inválida ou ausente retorna um erro de autenticação; uma consulta que não foi concluída do lado do servidor retorna HTTP 201 com um taskId em vez de um corpo de resultado. Verifique o código de status antes de assumir que organic_results existe na resposta, da mesma forma que qualquer cliente HTTP verifica uma resposta antes de analisar seu corpo.

P: Posso direcionar para um país ou idioma diferente do inglês?

Sim — gl define o código do país do Google e hl define o idioma da interface em cada solicitação de scraper.google.search; ambos são campos de string comuns no objeto input, definidos por chamada.

P: O modelo alguma vez chama a Deep SerpApi diretamente?

Não. O modelo apenas emite uma entrada tool_calls descrevendo qual função executar e com quais argumentos — ele não tem acesso à rede por conta própria. O código Python que faz a chamada possui a solicitação HTTP real, que é também o que mantém a chave da API fora do contexto do modelo.

P: É seguro direcionar isso para buscar resultados de pesquisa em vez de uma API?

A Deep SerpApi retorna dados do Google já analisados por meio de um endpoint autenticado, então não há preocupação com robots.txt ou limitação de taxa do lado do chamador — esse trabalho de infraestrutura acontece no lado da Scrapeless. Qualquer um que esteja construindo o equivalente ao raspar as páginas de resultados do Google diretamente deve ler o Protocolo de Exclusão de Robôs e os próprios termos do alvo primeiro; um endpoint de busca gerenciado existe especificamente para evitar essa classe de problema.

P: O que acontece realmente quando o modelo "decide" pesquisar?
Este é o padrão de recuperar-para-gerar descrito na original pesquisa de geração aumentada por recuperação: um modelo condiciona sua saída final a documentos obtidos no momento da inferência, em vez de apenas ao que está incorporado em seus pesos. A chamada de ferramentas é o mecanismo que modelos modernos ajustados para chat usam para acionar essa recuperação, no meio da conversa, em vez de uma etapa fixa de recuperação antes de cada prompt.

P: O fato de se apoiar em dados evita que o modelo invente coisas?

Não. Isso reduz a confabulação sobre os fatos específicos que o resultado da busca realmente cobre, mas um modelo pequeno ainda pode atribuir erroneamente, resumir em demasia ou adicionar um detalhe que não estava na saída da ferramenta. Trate a segunda interação como um rascunho informado por dados reais, não como uma citação autoritativa — para qualquer afirmação de peso, compare as alegações do modelo com a carga útil de organic_results que ele realmente recebeu antes de confiar nelas.

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