Ir al contenido principal

Integración de A-Parser con Redis: API avanzada

Comparación con HTTP API

A-Parser Redis API fue diseñado para reemplazar los métodos oneRequest y bulkRequest para una implementación más eficiente y el soporte de escenarios de uso adicionales:

  • Redis actúa como servidor de consultas y resultados
  • posibilidad de solicitar resultados de forma asíncrona o en modo bloqueante
  • posibilidad de conectar múltiples extractores (tanto en el mismo servidor como en diferentes) para procesar consultas con un único punto de entrada
  • posibilidad de establecer el número de hilos para procesar consultas y ver los registros de trabajo
  • posibilidad de organizar tiempos de espera (timeouts) en las operaciones
  • Expire automático de resultados no reclamados

Tema de discusión en el foro

Configuración previa

A diferencia de A-Parser HTTP API, para utilizar Redis API es necesario configurar previamente e iniciar una tarea con el extractor API::Server::RedisAPI::Server::Redis:

  • instalar y ejecutar el servidor Redis (local o remotamente)
  • crear un ajuste preestablecido de configuración para el extractor API::Server::RedisAPI::Server::Redis, especificando:
    • Redis Host: dirección del servidor Redis, por defecto 127.0.0.1
    • Redis Port: puerto del servidor Redis, por defecto 6379
    • Redis Queue Key: nombre de la clave para el intercambio de datos con A-Parser, por defecto aparser_redis_api, puede crear colas separadas y procesarlas con diferentes tareas o diferentes copias de A-Parser
    • Result Expire(TTL): tiempo de vida del resultado en segundos, sirve para el control automático y la eliminación de resultados no reclamados, por defecto 3600 segundos (1 hora)
  • añadir una tarea con el extractor API::Server::RedisAPI::Server::Redis
    • como consultas es necesario indicar {num:1:N}, donde N debe corresponder al número de hilos indicado en la tarea
    • también puede activar la opción de registro (log), de esta manera estará disponible la posibilidad de ver el registro de cada consulta

Ejemplo de configuración de tarea con API::Server::RedisAPI::Server::Redis

Obtención de solicitud API

Ejecución de A-Parser junto con Redis usando docker-compose

Con este método de ejecución, en lugar de la IP, puede indicar el nombre del servicio como dirección del servidor Redis (Redis Host); en los ejemplos de abajo es redis

Si A-Parser no se ha ejecutado previamente a través de docker-compose

  1. Descargue y descomprima la distribución (debe obtener previamente un enlace de un solo uso en el Área de clientes, como se describe aquí):
curl -O https://a-parser.com/members/onetime/ce42f308eaa577b5/aparser.tar.gz
tar zxf aparser.tar.gz
rm -f aparser.tar.gz
  1. Cree un archivo docker-compose.yml y coloque en él el siguiente contenido:

    • Variante básica sin contraseña y sin apertura de puerto, Redis estará disponible solo dentro de la red 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
    • Variante con contraseña y apertura de puerto, Redis estará disponible desde el exterior, por lo que se recomienda encarecidamente usar una contraseña
    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 AQUÍ_CONTRASEÑA_PARA_REDIS
    ports:
    - 6379:6379

    En lugar de TUT_PAROL_DLYA_REDIS, invente e indique la contraseña que se utilizará para la autorización en Redis.

  2. Inicie los contenedores:

docker compose up -d

Si A-Parser ya se ha ejecutado previamente a través de docker-compose

  1. Edite el archivo docker-compose.yml agregando al final el siguiente contenido:

    • Variante básica sin contraseña y sin apertura de puerto, Redis estará disponible solo dentro de la red Docker
      redis:
    image: redis:latest
    restart: always
    • Variante con contraseña y apertura de puerto, Redis estará disponible desde el exterior, por lo que se recomienda encarecidamente usar una contraseña
      redis:
    image: redis:latest
    restart: always
    command: redis-server --requirepass AQUÍ_CONTRASEÑA_PARA_REDIS
    ports:
    - 6379:6379

    En lugar de TUT_PAROL_DLYA_REDIS, invente e indique la contraseña que se utilizará para la autorización en Redis.

  2. Inicie los contenedores:

docker compose up -d
nota

Si A-Parser ya estaba en ejecución y su configuración no ha cambiado, no se reiniciará, y Docker simplemente agregará e iniciará Redis.

Ejecución de consultas

El funcionamiento de Redis API se basa en Redis Lists (listas); las operaciones sobre listas permiten agregar a la cola un número ilimitado de consultas (limitado por la memoria RAM), así como obtener resultados en modo bloqueante con tiempo de espera (blpop) o en modo asíncrono (lpop).

  • todas las configuraciones, excepto useproxy, proxyChecker y proxybannedcleanup, se toman del ajuste preestablecido del extractor llamado + overrideOpts
  • los ajustes useproxy, proxyChecker y proxybannedcleanup se toman del ajuste preestablecido de API::Server::RedisAPI::Server::Redis + overrideOpts

La consulta se agrega a Redis con el comando lpush, cada consulta consiste en un array [queryId, parser, preset, query, overrideOpts, apiOpts] serializado mediante JSON:

  • parser, preset, query corresponden a los análogos para la consulta API oneRequest
  • queryId: se genera junto con la consulta, recomendamos usar un número secuencial de su base de datos o un buen valor aleatorio; con este ID se podrá obtener el resultado
  • overrideOpts: anulación de configuraciones para el ajuste preestablecido del extractor
  • apiOpts: parámetros adicionales de procesamiento de la API
nota

En las consultas a través de Redis, se omite la etapa de formateo del resultado, ya que todo el resultado se transmite en formato JSON para su posterior procesamiento programático.

redis-cli

Ejemplo de ejecución de consultas, para pruebas se puede usar 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

Verificación asíncrona de la disponibilidad del resultado

lpop aparser_redis_api:some_unique_id

Devolverá el resultado si ya ha sido procesado o nil si la consulta aún está en proceso de extracción de datos

Obtención de resultados con bloqueo

blpop aparser_redis_api:some_unique_id 0

Esta consulta se bloqueará hasta el momento de recibir el resultado; también puede indicar un tiempo de espera máximo para recibir el resultado, tras lo cual el comando devolverá nil

Guardado de resultados en una cola única

Por defecto, A-Parser guarda el resultado de cada consulta bajo su propia clave única aparser_redis_api:query_id, lo que permite organizar el procesamiento multihilo, enviando consultas y recibiendo resultados por separado para cada hilo

En algunos casos es necesario procesar los resultados en un solo hilo a medida que llegan; en este caso es más conveniente guardar los resultados en una cola de resultados única (la clave debe ser diferente de la clave para las consultas)

Para ello, es necesario indicar la clave output_queue para apiOpts:

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

Obtención del resultado de la cola común:

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

Ejemplo de implementación (caso SpySERP)

Supongamos que estamos creando un servicio SaaS que realiza una evaluación de parámetros de dominios; para simplificar, comprobaremos la fecha de registro del dominio

Nuestro servicio consta de 2 páginas:

  • /index.php: página de aterrizaje donde se encuentra el formulario de entrada del dominio
  • /results.php?domain=google.com: página con los resultados del trabajo del servicio

Para mejorar la experiencia del usuario, queremos que las páginas de nuestro servicio se carguen instantáneamente, y que el proceso de espera de datos parezca natural y muestre un cargador (loader)

Al realizar una solicitud a results.php, primero ejecutamos una consulta en A-Parser Redis API, generando un request_id único:

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

Después de esto, podemos mostrar la página al usuario y un cargador en el área de visualización de datos; debido a la ausencia de retrasos, la respuesta del servidor estará limitada solo por la velocidad de conexión de Redis (normalmente dentro de los 10 ms)

A-Parser comenzará el procesamiento de la consulta incluso antes de que el navegador del usuario reciba el primer contenido; una vez que el navegador haya cargado todos los recursos y scripts necesarios, podemos mostrar el resultado, para lo cual enviamos una consulta AJAX para obtener los datos:

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

El script get-results.php realiza una consulta bloqueante a Redis con un tiempo de espera de 15 segundos:

blpop aparser_redis_api:request-1 15

Y devuelve la respuesta tan pronto como se reciba de A-Parser; si obtenemos un resultado nulo por tiempo de espera, podemos mostrar un error de obtención de datos al usuario

De esta manera, al enviar la consulta a A-Parser en la primera apertura de la página (/results.php), reducimos el tiempo de espera de datos necesario para el usuario (/get-results.php) por el tiempo que el navegador del usuario gasta esperando el contenido, cargando scripts y ejecutando la consulta AJAX