De volta ao blog

Dify + Scrapeless: Dê aos seus Agentes Dados da Web em Tempo Real com uma Ferramenta Personalizada

Emily Chen
Emily Chen

Advanced Data Extraction Specialist

20-Aug-2026

TL;DR:

  • O plugin Deep SerpApi no Mercado Dify expõe exatamente uma ferramenta com um parâmetro, query, então qualquer solicitação que precise de um resultado vertical, um deslocamento de página ou um site diferente deve vir de outro lugar.
  • Uma ferramenta personalizada é um arquivo OpenAPI. O Dify processa isso em uma única operação, scraperRequest, que alcança toda a família de atores Scrapeless scraper.* através de um único endpoint.
  • O Dify pré-preenche dois campos de autenticação com valores que esta API rejeita: o nome do cabeçalho é padrão para Authorization e o prefixo do cabeçalho é padrão para Basic. Qualquer padrão retorna 401 com {"code":14404,"message":"invalid access token"}.
  • O Dify tipa o objeto aninhado input como um parâmetro string, então um nó de Código que emite texto JSON é a maneira confiável de construí-lo dentro de um Fluxo de Trabalho.
  • Uma chamada de produto da Amazon retorna cerca de 2,2 MB, dos quais 1,9 MB é html bruto. Selecione result em um nó de Código antes que a carga útil chegue a um modelo.
  • Uma conta Scrapeless gratuita cobre cada solicitação neste guia.

Um agente Dify sem ferramenta web responde a partir de seus pesos de modelo e do que você carregou em sua base de conhecimento. Pergunte a ele sobre as páginas de maior classificação de hoje, o preço atual de um concorrente ou os encanadores que operam em uma cidade específica, e ele produzirá algo fluente e desatualizado.

O Dify resolve isso com ferramentas, e existem duas maneiras de adicionar uma. Este guia cobre a segunda: uma ferramenta personalizada construída a partir de um arquivo OpenAPI, que transforma a Scrapeless Scraping API em uma ação chamável em todos os agentes e fluxos de trabalho no seu espaço de trabalho.

O Que uma Ferramenta Personalizada Adiciona Que o Plugin Não

A listagem oficial do Deep SerpApi no Mercado Dify expõe uma ferramenta com um único parâmetro obrigatório, query, e um campo de credencial para a chave da API. Se uma consulta simples do Google é tudo o que seu fluxo de trabalho precisa, instale-a e pare de ler — são dois cliques e funciona, e o monitor de notícias empresariais construído no Dify mostra um fluxo de trabalho completo montado em torno disso.

O endpoint HTTP Scrapeless por trás disso aceita consideravelmente mais do que uma string de consulta. A mesma forma de solicitação seleciona o pacote local em vez de resultados da web, desloca-se para a segunda página desses resultados ou muda completamente para uma listagem da Amazon. Nada disso é acessível através de um único campo query.

Uma ferramenta personalizada fecha essa lacuna. Você cola um documento OpenAPI, o Dify lê as operações dele, e toda a família de atores se torna uma ferramenta anexável. Não há nada para instalar e nada para implantar, e o mesmo arquivo funciona no Dify Cloud e em uma instância auto-hospedada.

O Que a API de Extração Retorna

Um endpoint aceita cada solicitação: POST https://api.scrapeless.com/api/v1/scraper/request. O corpo transporta dois campos — actor nomeia o scraper, e input transporta os parâmetros desse scraper.

A resposta é JSON analisado em vez de HTML. Uma chamada scraper.google.search coloca organic_results no nível superior ao lado de metadata, pagination, e search_information. Adicionando tbm: lcl ao mesmo ator substitui isso por local_results.places, o bloco de negócios com avaliações, números de telefone e endereços. Uma chamada scraper.amazon aninha o produto analisado sob result.

Esse design de forma única é o que torna uma operação OpenAPI suficiente. Os detalhes dos parâmetros de cada ator estão na documentação da API de Extração.

Pré-requisitos

  • Um espaço de trabalho Dify — Cloud ou auto-hospedado na versão 1.0.0 ou posterior. A comportamento descrito aqui foi medido em uma instância auto-hospedada 1.16.1.
  • Uma chave API Scrapeless do painel.
  • Permissão do espaço de trabalho para adicionar ferramentas. O Dify restringe os endpoints de ferramentas personalizadas para administradores e proprietários do espaço de trabalho.

Passo 1: Importar o Esquema OpenAPI

No Dify, abra Ferramentas → Personalizado → Criar Ferramenta Personalizada e cole o documento abaixo. Ele é válido de acordo com a especificação OpenAPI 3.0.3, que é a versão que o analisador do Dify espera.

yaml Copy
openapi: 3.0.3
info:
  title: Scrapeless Scraper API
  version: "1.0.0"
servers:
  - url: https://api.scrapeless.com
paths:
  /api/v1/scraper/request:
    post:
      operationId: scraperRequest
      summary: Run a scraper actor and return structured data
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [actor, input]
              properties:
                actor:
                  type: string
                  description: Which scraper to run.
                  enum: [scraper.google.search, scraper.amazon]
                  example: scraper.google.search
                input:
                  type: object
                  description: Actor parameters. Keys depend on the actor.
                  additionalProperties: true
            examples:
              googleSearch:
                summary: Google SERP
                value:
                  actor: scraper.google.search
                  input:
                    q: web scraping api
              googleLocalPack:
                summary: Google local pack
                value:
                  actor: scraper.google.search
                  input:
                    q: plumbers in Austin, TX
                    tbm: lcl
              amazonProduct:
                summary: Amazon product by URL
                value:
                  actor: scraper.amazon
                  input:
                    action: product
                    url: https://www.amazon.com/dp/B09B8V1LZ3
      responses:
        '200':
          description: Parsed result. Shape depends on the actor.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
components:
  securitySchemes:
    ApiTokenAuth:
      type: apiKey
      in: header
      name: x-api-token

O Dify processa isso em exatamente uma ferramenta. O nome vem de operationId, então a ferramenta é chamada scraperRequest, e ela aceita dois parâmetros: actor e input. Os três exemplos nomeados aparecem no construtor de solicitações, o que economiza digitar a URL da Amazon à mão.

Passo 2: Preencha Todos os Quatro Campos de Autenticação

Escolha autenticação API Key e preencha cada campo. Dois dos quatro chegam pré-preenchidos com valores que esta API rejeita:

Campo O Que Definir O Que o Dify Preenche
Tipo de autenticação API Key (armazenado como api_key_header) None
Nome do cabeçalho x-api-token Authorization
Valor Sua chave de API Scrapeless vazio
Prefixo do cabeçalho Custom Basic

O campo de prefixo é aquele que confunde as pessoas. O Dify o concatena ao valor, então deixá-lo em Basic envia o cabeçalho x-api-token: Basic <your-key>. Isso não é o que o esquema de autenticação HTTP Básico significa — uma verdadeira credencial Básica é um par user:password codificado em base64 — e o Scrapeless espera a chave nua, então a solicitação é rejeitada. Bearer falha de forma idêntica. Apenas Custom passa o valor inalterado.

Deixar o nome do cabeçalho em Authorization falha da mesma maneira, pela mesma razão: a chave nunca chega ao cabeçalho que a API lê.

Ambos os erros produzem uma resposta, e você pode reproduzir qualquer um a partir de um terminal antes de tocar no Dify:

bash Copy
# Correct: bare key in x-api-token
curl -s -o /dev/null -w 'bare key      -> %{http_code}\n' \
  -X POST https://api.scrapeless.com/api/v1/scraper/request \
  -H "Content-Type: application/json" \
  -H "x-api-token: $SCRAPELESS_API_KEY" \
  -d '{"actor":"scraper.google.search","input":{"q":"web scraping api"}}'

# What Dify sends with the default prefix
curl -s -w '\nBasic prefix  -> %{http_code}\n' \
  -X POST https://api.scrapeless.com/api/v1/scraper/request \
  -H "Content-Type: application/json" \
  -H "x-api-token: Basic $SCRAPELESS_API_KEY" \
  -d '{"actor":"scraper.google.search","input":{"q":"web scraping api"}}'

# What Dify sends with the default header name
curl -s -w '\nAuthorization -> %{http_code}\n' \
  -X POST https://api.scrapeless.com/api/v1/scraper/request \
  -H "Content-Type: application/json" \
  -H "Authorization: $SCRAPELESS_API_KEY" \
  -d '{"actor":"scraper.google.search","input":{"q":"web scraping api"}}'
text Copy
bare key      -> 200
{"code":14404,"message":"invalid access token"}
Basic prefix  -> 401
{"code":14404,"message":"invalid access token"}
Authorization -> 401

Um 401 aqui é o servidor informando que a credencial que recebeu não é uma que aceita, que é exatamente para isso que a especificação de semântica HTTP reserva esse status. O corpo restringe ainda mais: o código 14404 é especificamente um token inutilizável, não uma solicitação malformada.

Passo 3: Execute o Teste Integrado

O painel de testes do Dify chama o endpoint com as credenciais que você acabou de inserir. Preencha os dois parâmetros:

json Copy
{
  "actor": "scraper.google.search",
  "input": "{\"q\": \"web scraping api\"}"
}

Uma configuração funcional retorna cerca de 15 KB de JSON SERP. Um prefixo quebrado retorna uma única string de erro que carrega o corpo upstream literalmente: Request failed with status code 401 and {"code":14404,"message":"invalid access token"}.

Note a citação na carga de teste. O Dify achata propriedades aninhadas do corpo da solicitação, então input é registrado como um parâmetro string em vez de um objeto — o esquema analisado relata actor e input ambos como string, ambos obrigatórios. Um verdadeiro objeto JSON funciona no painel também, porque o Dify normaliza qualquer forma no objeto que a API espera. Essa conversão é importante: uma solicitação construída manualmente contra o endpoint tem que enviar um objeto, e uma string lá volta como 400 {"message":"invalid input body"}.

Salve o provedor uma vez que o teste retorna dados. scraperRequest então aparece na lista de ferramentas para cada aplicativo no espaço de trabalho.

Construindo isso em um plano gratuito? Crie uma conta Scrapeless e as solicitações deste guia rodam na cota gratuita.

O Que Retorna

O envelope depende do ator, e cada forma deseja um manuseio diferente a jusante.

Busca na web. scraper.google.search com {"q": "web scraping api"} retornou oito organic_results em uma resposta de 15 KB, junto a metadata, pagination, search_information, related_searches, e um bloco inline_videos. Cada resultado carrega title, link, snippet, source, position, e snippet_highlighted_words.

Pacote local. Adicionar tbm: lcl substitui organic_results por local_results.places — 20 negócios por solicitação. Configurar start: 20 retorna a próxima página; ao longo de duas páginas consecutivas de uma consulta, 37 dos 40 registros eram distintos, então um fluxo que armazena ambas as páginas deve ser baseado em algo estável em vez de presumir que não há repetições.

Os campos do pacote local precisam de uma limpeza antes de chegarem a um CRM ou a uma planilha:

  • phone, type, e hours chegam preenchidos com um espaço à frente, e algumas strings de horário usam um espaço estreito sem quebra em vez de um normal.
  • phone tinha um valor em forma de telefone em 15 dos 20 registros em uma captura; o restante carregava horários de funcionamento ou um rótulo de serviço, como Online estimates.
  • place_id, place_id_search, lsig, e thumbnail estavam vazios em todos os 20 registros.
  • gps_coordinates está presente, mas lê {"latitude": 0, "longitude": 0}, então passa na verificação de veracidade enquanto não carrega localização.

Amazon. scraper.amazon com action: product retornou 2.226.755 bytes. O produto analisado sob result tem 4.608 bytes em 63 campos; os restantes 1.960.588 bytes são o html bruto da listagem. Entregar toda essa carga a um modelo é caro e sem sentido.

Corte a Resposta Antes de Chegar ao Modelo

Coloque um nó de Código diretamente após o nó da Ferramenta. Ele executa Python 3 ou JavaScript, pega a saída da ferramenta como uma variável de entrada e retorna um dicionário que nós seguintes leem por chave. Selecionar campos lá não custa nada e mantém o contexto do modelo pequeno:

python Copy
def main(response: dict) -> dict:
    places = (response.get("local_results") or {}).get("places") or []
    rows = []
    for place in places:
        contact = (place.get("phone") or "").strip()
        digits = sum(character.isdigit() for character in contact)
        rows.append({
            "name": (place.get("title") or "").strip(),
            "category": (place.get("type") or "").strip(),
            "rating": place.get("rating"),
            "reviews": place.get("reviews") or 0,
            "phone": contact if digits >= 10 else None,
            "note": None if digits >= 10 else contact,
            "address": (place.get("address") or "").strip(),
        })
    return {"rows": rows, "count": len(rows)}


# Local check against a live response. Leave everything below out of the Code node.
if __name__ == "__main__":
    import json, os, urllib.request

    body = json.dumps({
        "actor": "scraper.google.search",
        "input": {"q": "plumbers in Austin, TX", "tbm": "lcl"},
    }).encode()
    call = urllib.request.Request(
        "https://api.scrapeless.com/api/v1/scraper/request",
        data=body,
        headers={"Content-Type": "application/json",
                 "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
    )
    with urllib.request.urlopen(call, timeout=180) as reply:
        cleaned = main(json.load(reply))

    print(cleaned["count"], "rows")
    print(json.dumps(cleaned["rows"][0], ensure_ascii=False))

O bloco acima também serve como uma verificação local: execute-o com sua chave no ambiente e ele busca um pacote local ao vivo, aplica a mesma função e imprime a primeira linha limpa. Observe que uma chamada direta envia input como um objeto — a API responde uma string com 400 {"message":"invalid input body"}. Dify converte a forma da string para você ao sair, e é por isso que o mesmo valor funciona em ambos os lugares.

A limpeza transforma 20 registros brutos em 20 utilizáveis: nomes e categorias sem espaços em branco soltos, um número real em phone quando o campo contém um, e o texto de horários de funcionamento movido para note em vez de ser escrito em uma coluna de telefone.

Para a forma da Amazon, o mesmo nó é uma linha única — return {"product": response["result"]} — e elimina 99% da carga útil.

Anexe a um Agente ou a um Fluxo de Trabalho

Ambas as superfícies usam a mesma ferramenta salva, e a escolha é sobre quem escolhe os parâmetros.

Em um Agente, o modelo decide quando chamar scraperRequest e o que colocar em actor e input. Isso funciona quando as instruções nomeiam a ferramenta e a condição de dados explicitamente:

text Copy
When a question depends on current web content, call scraperRequest with
actor "scraper.google.search" and input {"q": "<the search terms>"}, read the
organic_results, and answer from those. Do not answer from memory when the
question is about current prices, rankings, or availability.

Em um Fluxo de Trabalho, você fixa actor no nó da Ferramenta e permite que um nó a montante forneça apenas a consulta. Como input é um parâmetro de string, o padrão confiável é um nó de Código que constrói o texto JSON:

python Copy
def main(query: str) -> dict:
    import json
    return {"payload": json.dumps({"q": query, "tbm": "lcl"})}

Conecte payload ao campo input do nó da Ferramenta. A própria documentação de ferramentas do Dify cobre a fiação do nó circundante com mais profundidade.

Se Você Alojá-lo Localmente o Dify

Instâncias auto-hospedadas roteiam HTTP da ferramenta por meio de um container ssrf_proxy dedicado em vez de deixar o container da API alcançar a internet diretamente. Quando esse serviço não está em execução, chamadas à ferramenta falham com um erro de DNS — [Errno -3] Temporary failure in name resolution — que lê como uma URL quebrada em vez de um container ausente. Levante toda a pilha de composição, não apenas api e web, e a mesma ferramenta funciona idêntica à Nuvem.

O comportamento neste guia foi medido em uma instância auto-hospedada 1.16.1: o esquema foi parseado para uma ferramenta, o teste de credenciais retornou 15.648 bytes de JSON de SERP com Custom como prefixo e uma string 401 com Basic, e o provedor salvo listou scraperRequest como uma ferramenta conectável.

Conclusão

O plugin Marketplace cobre uma string de consulta. Uma ferramenta personalizada cobre o endpoint por trás dela, que é o que um fluxo de leads precisa assim que começa a ler pacotes locais, paginando através deles e limpando os campos antes que eles cheguem a qualquer lugar.

O custo de configuração é um arquivo OpenAPI e quatro campos de autenticação — dois dos quais o Dify preenche incorretamente por padrão. Acertar isso e cada ator na família se torna disponível para cada aplicativo no espaço de trabalho, com um nó de Código fazendo a modelagem que mantém as cargas úteis pequenas e as colunas limpas.

Pronto para conectá-lo? Comece com uma conta gratuita do Scrapeless, pegue sua chave de API e cole o esquema acima em seu espaço de trabalho. Os limites de uso e plano estão listados na página de preços do Scrapeless.

FAQ

Q: Devo usar o plugin Deep SerpApi ou uma ferramenta personalizada?

Use o plugin quando uma consulta simples no Google é tudo o que você precisa — ele expõe uma ferramenta com um único parâmetro query e leva dois cliques para instalar. Use uma ferramenta personalizada quando precisar do pacote local, um deslocamento de página, uma listagem da Amazon ou qualquer outro ator, porque esses parâmetros não são acessíveis por meio daquele campo único.

Q: Por que minha ferramenta personalizada do Dify retorna 401 quando a mesma chave funciona no curl?

Dois padrões do Dify enviam a chave em uma forma que a API não lê. O nome do cabeçalho padrão é Authorization em vez de x-api-token, e o prefixo do cabeçalho padrão é Basic, o que faz com que o Dify envie x-api-token: Basic <key>. Defina o nome do cabeçalho para x-api-token e o prefixo para Custom.

Q: Por que o campo input é uma string em vez de um objeto?

O Dify achata as propriedades do corpo da solicitação aninhadas ao analisar um documento OpenAPI, então um objeto aninhado se torna um parâmetro de string. O Dify aceita qualquer uma das formas e normaliza antes que a solicitação saia, portanto, um nó de Código emitindo json.dumps(...) é a maneira confiável de construí-lo em um Fluxo de Trabalho. Uma chamada direta para o endpoint é mais rigorosa e requer um objeto.

Q: Isso funciona no Dify Cloud assim como em auto-hospedado?

Sim. A ferramenta personalizada é um documento OpenAPI mais credenciais, sem nada para instalar em nenhum dos dois. Instâncias auto-hospedadas têm um requisito extra: o container ssrf_proxy deve estar em execução, pois a saída HTTP da ferramenta é roteada por meio dele.
Q: Quantos resultados uma solicitação retorna?

Uma pesquisa na web retornou oito resultados orgânicos na captura utilizada para este guia, e as contagens de resultados variam por consulta. O pacote local retorna 20 lugares por solicitação, e start: 20 busca a próxima página; páginas consecutivas de uma consulta se sobrepõem ligeiramente, então deduplicate na gravação.

Q: Como faço para evitar que a resposta da Amazon inunde o contexto do modelo?

Selecione result em um nó de Código colocado após o nó de Ferramenta. Uma chamada de produto retornou 2.226.755 bytes, dos quais 1.960.588 eram o campo bruto html e apenas 4.608 eram o produto analisado, então retornar {"product": response["result"]} mantém tudo útil e descarta o resto.

Q: Uma ferramenta personalizada pode atender vários atores?

Sim, e esse é o ponto do design. O endpoint recebe actor mais input, então uma única operação scraperRequest atinge todos os atores aos quais sua conta tem acesso. Adicionar um ao enum no esquema o expõe no construtor de solicitações sem uma segunda ferramenta.

Q: Onde deve ficar a chave da API?

No campo de credenciais do provedor da ferramenta, que o Dify armazena como um segredo e injeta no momento da chamada. Mantê-la lá em vez de em um parâmetro de nó significa que um fluxo de trabalho exportado ou um aplicativo duplicado não carrega a chave com ele.

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