Pular para o conteúdo principal

Integração do A-Parser com Redis: API avançada

Comparação com HTTP API

A-Parser Redis API foi desenvolvido para substituir os métodos oneRequest e bulkRequest para uma implementação de maior desempenho e suporte a cenários de uso adicionais:

  • o Redis atua como servidor de consultas e resultados
  • possibilidade de solicitar resultados de forma assíncrona ou em modo de bloqueio
  • possibilidade de conectar múltiplos scrapers (tanto no mesmo servidor quanto em servidores diferentes) para processar consultas com um único ponto de entrada
  • possibilidade de definir o número de threads para processar consultas e visualizar logs de operação
  • possibilidade de organizar timeouts nas operações
  • Expire automático de resultados não reclamados

Tópico de discussão no fórum

Pré-configuração

Diferente da A-Parser HTTP API, para usar a Redis API é necessário configurar e iniciar previamente uma tarefa com o scraper API::Server::RedisAPI::Server::Redis:

  • instalar e iniciar o servidor Redis (local ou remotamente)
  • criar um preset de configurações para o scraper API::Server::RedisAPI::Server::Redis, especificando:
    • Redis Host - endereço do servidor Redis, por padrão 127.0.0.1
    • Redis Port - porta do servidor Redis, por padrão 6379
    • Redis Queue Key - nome da chave para troca de dados com o A-Parser, por padrão aparser_redis_api, você pode criar filas separadas e processá-las com diferentes tarefas ou diferentes instâncias do A-Parser
    • Result Expire(TTL) - tempo de vida do resultado em segundos, serve para controle automático e exclusão de resultados não reclamados, por padrão 3600 segundos (1 hora)
  • adicionar uma tarefa com o scraper API::Server::RedisAPI::Server::Redis
    • como consultas, é necessário indicar {num:1:N}, onde N deve corresponder ao número de threads especificado na tarefa
    • você também pode ativar a opção de registro de log, permitindo assim a visualização do log para cada consulta

Exemplo de configuração de tarefa com API::Server::RedisAPI::Server::Redis

Obtendo solicitação de API

Executando o A-Parser junto com o Redis usando docker-compose

Neste método de inicialização, em vez do IP, você pode especificar o nome do serviço como endereço do servidor Redis (Redis Host), nos exemplos abaixo é redis

Se o A-Parser não foi executado anteriormente via docker-compose

  1. Baixe e descompacte a distribuição (o link de uso único deve ser obtido previamente na Área de Membros, como descrito aqui):
curl -O https://a-parser.com/members/onetime/ce42f308eaa577b5/aparser.tar.gz
tar zxf aparser.tar.gz
rm -f aparser.tar.gz
  1. Crie o arquivo docker-compose.yml e coloque nele o seguinte conteúdo:

    • Opção básica sem senha e sem abertura de porta, o Redis estará disponível apenas dentro da rede Docker
    version: '3'

    services:
    a-parser:
    image: aparser/runtime:latest
    command: ./aparser
    restart: always
    volumes:
    - ./aparser:/app
    ports:
    - 9091:9091

    redis:
    image: redis:latest
    restart: always
    • Opção com senha e abertura de porta, o Redis estará disponível externamente, por isso é altamente recomendável usar uma senha
    version: '3'

    services:
    a-parser:
    image: aparser/runtime:latest
    command: ./aparser
    restart: always
    volumes:
    - ./aparser:/app
    ports:
    - 9091:9091

    redis:
    image: redis:latest
    restart: always
    command: redis-server --requirepass SUA_SENHA_PARA_REDIS
    ports:
    - 6379:6379

    Em vez de AQUI_SENHA_PARA_REDIS, crie e especifique a senha que será usada para autenticação no Redis.

  2. Inicie os contêineres:

docker compose up -d

Se o A-Parser já foi executado anteriormente via docker-compose

  1. Edite o arquivo docker-compose.yml adicionando ao final o seguinte conteúdo:

    • Opção básica sem senha e sem abertura de porta, o Redis estará disponível apenas dentro da rede Docker
      redis:
    image: redis:latest
    restart: always
    • Opção com senha e abertura de porta, o Redis estará disponível externamente, por isso é altamente recomendável usar uma senha
      redis:
    image: redis:latest
    restart: always
    command: redis-server --requirepass SUA_SENHA_PARA_REDIS
    ports:
    - 6379:6379

    Em vez de AQUI_SENHA_PARA_REDIS, crie e especifique a senha que será usada para autenticação no Redis.

  2. Inicie os contêineres:

docker compose up -d
nota

Se o A-Parser já estiver em execução e sua configuração não tiver mudado, ele não será reiniciado, e o Docker apenas adicionará e iniciará o Redis.

Execução de consultas

O funcionamento da Redis API é baseado em Redis Lists (listas); as operações em listas permitem adicionar à fila um número ilimitado de consultas (limitado pela memória RAM), bem como obter resultados em modo de bloqueio com timeout (blpop) ou em modo assíncrono (lpop).

  • todas as configurações, exceto useproxy, proxyChecker e proxybannedcleanup, são obtidas do modelo do scraper chamado + overrideOpts
  • as configurações useproxy, proxyChecker e proxybannedcleanup são obtidas do preset API::Server::RedisAPI::Server::Redis + overrideOpts

A consulta é adicionada ao Redis com o comando lpush, cada consulta consiste em um array [queryId, parser, preset, query, overrideOpts, apiOpts] serializado com JSON:

  • parser, preset, query correspondem aos análogos para a consulta de API oneRequest
  • queryId - gerado junto com a consulta, recomendamos usar um número sequencial do seu banco de dados ou um bom valor aleatório; através deste ID será possível obter o resultado
  • overrideOpts - sobreposição de configurações para o modelo do scraper
  • apiOpts - parâmetros adicionais de processamento da API
nota

Ao realizar consultas via Redis, a etapa de formatação do resultado é ignorada, pois todo o resultado é transmitido em formato JSON para posterior processamento programático.

redis-cli

Exemplo de execução de consultas; para testes você pode usar o redis-cli:

127.0.0.1:6379> lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru"]'
(integer) 1
127.0.0.1:6379> blpop aparser_redis_api:some_unique_id 0
1) "aparser_redis_api:some_unique_id"
2) "{\"data\":\"<!DOCTYPE html><html.....

Casos de uso

Verificação assíncrona da existência de resultado

lpop aparser_redis_api:some_unique_id

Retornará o resultado se ele já tiver sido processado ou nil se a consulta ainda estiver em processamento

Obtenção de resultado com bloqueio

blpop aparser_redis_api:some_unique_id 0

Esta solicitação será bloqueada até o momento da obtenção do resultado; você também pode especificar um timeout máximo para obter o resultado, após o qual o comando retornará nil

Salvando resultados em uma fila única

Por padrão, o A-Parser salva o resultado de cada consulta sob sua própria chave única aparser_redis_api:query_id, o que permite organizar o processamento em múltiplas threads, enviando consultas e recebendo resultados separadamente para cada thread

Em alguns casos, é necessário processar os resultados em uma única thread à medida que eles chegam; nesse caso, é mais conveniente salvar os resultados em uma fila de resultados única (a chave deve ser diferente da chave usada para as consultas)

Para isso, é necessário especificar a chave output_queue para apiOpts:

lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru", {}, {"output_queue": "aparser_results"}]'

Obtendo o resultado da fila comum:

127.0.0.1:6379> blpop aparser_results 0
1) "aparser_results"
2) "{\"queryId\":\"some_unique_id\",\"results\":{\"data\":\"<!DOCTYPE html><html class=...

Exemplo de implementação (caso SpySERP)

Suponhamos que estamos criando um serviço SaaS que avalia parâmetros de domínios; para simplificar, verificaremos a data de registro do domínio

Nosso serviço consiste em 2 páginas:

  • /index.php - página de destino (landing page), onde está localizado o formulário de entrada do domínio
  • /results.php?domain=google.com - página com os resultados do funcionamento do serviço

Para melhorar a experiência do usuário, queremos que as páginas do nosso serviço carreguem instantaneamente e que o processo de espera pelos dados pareça natural e exiba um loader

Ao solicitar results.php, realizamos primeiramente uma consulta à Redis API do A-Parser, gerando um request_id único:

​lpush aparser_redis_api '["request-1", "Net::Whois", "default", "google.com", {}, {}]'

Depois disso, podemos exibir a página ao usuário e mostrar um loader na área de exibição de dados; devido à ausência de atrasos, a resposta do servidor será limitada apenas pela velocidade de conexão do Redis (geralmente dentro de 10ms)

O A-Parser começará o processamento da consulta antes mesmo de o navegador do usuário receber o primeiro conteúdo; após o navegador carregar todos os recursos e scripts necessários, podemos exibir o resultado; para isso, enviamos uma consulta AJAX para obter os dados:

/get-results.php?request_id=request-1

O script get-results.php executa uma consulta de bloqueio ao Redis com um timeout de 15 segundos:

blpop aparser_redis_api:request-1 15

E retorna a resposta assim que ela for recebida do A-Parser; se recebermos um resultado nulo por timeout, podemos exibir um erro de obtenção de dados para o usuário

Dessa forma, ao enviar a consulta ao A-Parser na primeira abertura da página (/results.php), reduzimos o tempo de espera necessário para o usuário (/get-results.php) pelo tempo que o navegador do usuário gasta esperando o conteúdo, carregando scripts e executando a consulta AJAX