Ir al contenido principal

Métodos hook

Estos métodos funcionan según el principio de ganchos (hooks). La implementación de estos métodos permite controlar el funcionamiento del extractor en diferentes etapas, desde la inicialización hasta la destrucción del objeto.

La implementación de todos los métodos, excepto parse, es opcional.

async parse(set, results)

El método parse implementa la lógica principal de procesamiento de la consulta y obtención del resultado de la extracción de datos; como argumentos se pasan:

  • set - objeto con información sobre la consulta:
    • set.query - cadena de texto de la consulta
    • set.lvl - nivel de la consulta, por defecto 0
  • results - objeto con los resultados que deben completarse y devolverse desde el método parse()
    • el extractor debe verificar la presencia de cada clave en el objeto results y completarla solo si existe, optimizando así la velocidad y extrayendo solo los datos que se utilizan en la formación del resultado
    • results contiene las claves de las variables flat necesarias con el valor none, por defecto esto significa que el resultado no se ha obtenido, así como las claves de las variables de matriz (arrays) con un valor en forma de matriz vacía, lista para ser completada
    • results.success debe establecerse en 1 tras el procesamiento exitoso de la consulta, por defecto el valor es 0, lo que significa que la consulta se procesó con error

Veamos un ejemplo:

class JS_HTML_Tags extends BaseParser {
static defaultConf = {
results: {
flat: [
['title', 'Title'],
],
arrays: {
h2: ['H2 Headers List', [
['header', 'Header'],
]],
}
},
...
};

async parse(set, results) {
// Obtenemos el contenido de la página HTML cuya dirección se pasó en la consulta
const {success, data, headers} = await this.request('GET', set.query);

// Verificamos el éxito y el tipo de data; al procesar correctamente páginas HTML debemos recibir el tipo 'string', de lo contrario A-Parser devuelve un objeto de tipo Buffer
if (success && typeof data == 'string') {
let matches;

// Verificamos la necesidad de recopilar el title y guardamos el valor
if (results.title && matches = data.match(/<title[^>]*>(.*?)<\/title>/))
results.title = matches[1];

// Verificamos la necesidad de recopilar h2
if (results.h2) {
let count = 0;
const re = /<h2[^>]*>(.*?)<\/h2>/g;
while(matches = re.exec(data)) {
// Guardamos en un bucle todas las etiquetas h2 encontradas
results.h2.push(matches[1]);
}
}

// Notificamos el éxito de la extracción de datos
results.success = 1;
}

// Devolvemos los resultados procesados
return results;
}
};

Tenga en cuenta que puede crear sus propias funciones y métodos para una mejor organización del código:

function Answer() {
return 42;
}

class JS_HTML_Tags extends BaseParser {
...

async parse(set, results) {
results = await this.doWork(set, results);
return results;
}

async doWork(set, results) {
results.answer = Answer();
return results;
}
};

async processConf?(conf)

Este método se utiliza para transformar la configuración según ciertas reglas, por ejemplo, al usar captcha siempre es necesario usar sesiones:

async processConf(conf) {
if (conf.useCaptcha)
conf.useSessions = 1
}

async parse(set, results) {
if (conf.useSessions)
await this.login();
}

La existencia de este método se debe a que A-Parser admite campos de configuración dinámicos y, dentro de una misma tarea, la configuración puede tener diferentes valores; este escenario es posible en dos casos:

  • Uso de plantillas en los campos de configuración, por ejemplo [% tools.ua.random() %] para el campo User-Agent
  • Uso de overrides al llamar a un extractor desde otro para this.parser.request

El método processConf se llama una sola vez antes de init(). Para los casos descritos anteriormente, processConf se llama adicionalmente antes del procesamiento de cada consulta

Reglas principales para aplicar processConf:

  • Úselo solo si las transformaciones de la configuración tienen un efecto en el rendimiento
  • Tenga en cuenta que init se ejecuta una vez, mientras que processConf puede ejecutarse para cada consulta; en este caso, la lógica puede verse afectada si init depende de campos de configuración cambiantes (ver más abajo)

async init?()

El método init se llama una vez durante la inicialización del objeto base del extractor y sirve para realizar acciones únicas:

  • Iniciar el navegador
  • Inicialización del administrador de sesiones mediante el método this.sessionManager.init()
  • Conexión a la base de datos y creación de tablas en la BD
  • Lectura de datos estáticos
  • Etc.
advertencia

Dado que el método se llama una vez, todos los campos de configuración de los que depende init() no pueden utilizarse junto con plantillas de campos de configuración o con overrides al llamar a this.parsers.request

async destroy?()

El método destroy se llama una vez al finalizar la tarea y es necesario para la destrucción correcta de los recursos abiertos:

  • Cierre del navegador
  • Cierre de la conexión a la BD
  • Etc.

async threadInit?()

Este método se ejecuta al inicializar cada hilo; cada hilo es una copia del objeto base del extractor con su propio this.threadId único, que comienza en 0 y termina en threads_count - 1

Principales casos de uso:

  • creación de una página (pestaña) del navegador para cada hilo

async threadDestroy?()

Se ejecuta al finalizar el hilo durante el proceso de finalización de la tarea y sirve para liberar los recursos asignados a dicho hilo

async afterResultsProcessor?(results)

Este método se ejecuta después de procesar los resultados: mediante el constructor de resultados, el filtrado y la eliminación de duplicados. El caso de uso principal es añadir consultas a la cola utilizando el método this.query.add después de aplicar los filtros de usuario; de esta manera se implementa el filtrado de enlaces para seguir (followlinks) para el extractor HTML::LinkExtractorHTML::LinkExtractor