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 consultaset.lvl- nivel de la consulta, por defecto0
results- objeto con los resultados que deben completarse y devolverse desde el métodoparse()- 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
resultscontiene las claves de las variables flat necesarias con el valornone, 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 completadaresults.successdebe establecerse en1tras el procesamiento exitoso de la consulta, por defecto el valor es0, 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
overridesal llamar a un extractor desde otro parathis.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
initse ejecuta una vez, mientras queprocessConfpuede ejecutarse para cada consulta; en este caso, la lógica puede verse afectada siinitdepende 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.
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::LinkExtractor