Extractores en JavaScript: Resumen de capacidades
Los extractores JavaScript son una oportunidad para crear sus propios extractores completos con una lógica de cualquier complejidad, utilizando el lenguaje JavaScript. Al mismo tiempo, en los extractores JS también se puede utilizar toda la funcionalidad de los extractores estándar.

Características
Utilizando todo el poder de A-Parser, ahora es posible escribir su propio extractor/registrador/poster con una lógica de cualquier complejidad. Para escribir el código se utiliza JavaScript con capacidades de ES6 (motor v8).
El código de los extractores es lo más conciso posible, permitiendo enfocarse en la escritura de la lógica; el trabajo con el multihilo, la red, los proxies, los resultados, los registros, etc., A-Parser lo asume por sí mismo. El código se puede escribir directamente en la interfaz del extractor, añadiendo un nuevo extractor en el Editor de extractores. También se pueden utilizar editores externos para escribir extractores, como VSCode.
Se utiliza el versionado automático al guardar el código del extractor a través del editor integrado.
El trabajo con extractores JavaScript está disponible para las licencias Pro y Enterprise
Acceso al Editor de extractores JS
Si A-Parser se utiliza de forma remota, por razones de seguridad el Editor de extractores JS no está disponible por defecto. Para habilitar el acceso, es necesario:
- Establecer una contraseña en la pestaña Settings (Configuración) -> Global Settings (Configuración general)
- Añadir en config/config.txt la siguiente línea:
allow_javascript_editor: 1 - Reiniciar A-Parser
Instrucciones de trabajo
En el Editor de extractores creamos un nuevo extractor y definimos el nombre del extractor. Por defecto se cargará un ejemplo sencillo, sobre el cual se puede comenzar rápidamente a crear su propio extractor.
Si se utiliza un editor externo para escribir el código, se debe abrir el archivo del extractor que se está editando en la carpeta /parsers/. Estructura de archivos del programa instalado.
Cuando el código esté listo, lo guardamos y lo usamos como un extractor normal: en el Editor de tareas seleccionamos el extractor creado, si es necesario se pueden definir los parámetros requeridos, la configuración de hilos, el nombre del archivo, etc.
El extractor creado se puede editar en cualquier momento. Todos los cambios relacionados con la interfaz aparecerán después de volver a seleccionar el extractor en la lista de extractores o reiniciar A-Parser; los cambios en la lógica del extractor se aplican al volver a ejecutar la tarea con el extractor.
Para cada extractor creado se muestra por defecto un icono estándar, se puede añadir uno propio en formato png o ico, colocándolo en la carpeta del extractor en /parsers/:
Principios generales de funcionamiento
Por defecto se crea un ejemplo de un extractor sencillo, listo para su posterior edición.
- TypeScript
- JavaScript
import { BaseParser } from 'a-parser-types';
export class JS_v2_example extends BaseParser {
static defaultConf: typeof BaseParser.defaultConf = {
version: '0.0.1',
results: {
flat: [
['title', 'HTML title'],
]
},
max_size: 2 * 1024 * 1024,
parsecodes: {
200: 1,
},
results_format: '$query: $title\\n',
};
static editableConf: typeof BaseParser.editableConf = [];
async parse(set, results) {
this.logger.put("Start scraping query: " + set.query);
let response = await this.request('GET', set.query, {}, {
check_content: ['<\/html>'],
decode: 'auto-html',
});
if (response.success) {
let matches = response.data.match(/<title>(.*?)<\/title>/i);
if (matches)
results.title = matches[1];
}
results.success = response.success;
return results;
}
}
const { BaseParser } = require("a-parser-types");
class JS_v2_example_js extends BaseParser {
static defaultConf = {
version: '0.0.1',
results: {
flat: [
['title', 'HTML title'],
]
},
max_size: 2 * 1024 * 1024,
parsecodes: {
200: 1,
},
results_format: '$query: $title\\n',
};
static editableConf = [];
async parse(set, results) {
this.logger.put("Start scraping query: " + set.query);
let response = await this.request('GET', set.query, {}, {
check_content: ['<\/html>'],
decode: 'auto-html',
});
if (response.success) {
let matches = response.data.match(/<title>(.*?)<\/title>/i);
if (matches)
results.title = matches[1];
}
results.success = response.success;
return results;
}
}
El constructor se llama una sola vez para cada tarea. Es obligatorio definir this.defaultConf.results y this.defaultConf.results_format, los demás campos son opcionales y tomarán valores por defecto.
El array this.editableConf determina qué configuraciones pueden ser modificadas por el usuario desde la interfaz de A-Parser. Se pueden utilizar los siguientes tipos de campos:
combobox- menú desplegable de selección. También se puede crear un menú de selección de ajuste preestablecido de un extractor estándar, por ejemplo:
['Util_AntiGate_preset', ['combobox', 'AntiGate preset']]
comboboxcon posibilidad de selección múltiple. Se debe definir adicionalmente el parámetro{'multiSelect': 1}:
['proxyCheckers', ['combobox', 'Proxy Checkers', {'multiSelect': 1}, ['*', 'All']]]
checkbox- casilla de verificación, para parámetros que solo pueden tener 2 valores (true/false)textfield- campo de textotextarea- campo de texto con entrada multilínea
El método parse es una función asíncrona y debe devolver await para cualquier operación de bloqueo (esta es la principal y única diferencia con una función normal). El método se llama para cada consulta que entra en procesamiento. Se pasan obligatoriamente set (hash con la consulta y sus parámetros) y results (una plantilla vacía para los resultados). También es obligatorio devolver el results completado, habiendo establecido previamente la bandera success.
Versionado automático
La versión tiene el formato Major.Minor.Revision
- TypeScript
- JavaScript
this.defaultConf: typeof BaseParser.defaultConf = {
version: '0.1.1',
...
}
this.defaultConf = {
version: '0.1.1',
...
}
El valor de Revision (el último dígito) aumenta automáticamente con cada guardado. Los demás valores (Major, Minor) se pueden cambiar manualmente, así como restablecer Revision a 0.
Si por alguna razón es necesario cambiar Revision solo manualmente, entonces la versión debe encerrarse entre comillas dobles ""
Procesamiento por lotes de consultas
En algunos casos puede ser necesario tomar varias consultas de la cola a la vez y procesarlas de un solo golpe. Este modo se utiliza en los extractores integrados cuando se necesitan solicitar datos para varias claves a la vez (en lote) en una sola pasada.
Para implementar la misma funcionalidad en un extractor JS, se debe definir en this.defaultConf el valor bulkQueries: N, donde N es la cantidad necesaria de consultas en el lote. En este caso, el extractor tomará las consultas en lotes de N unidades y todas las consultas de la iteración actual estarán contenidas en el array set.bulkQueries (incluyendo todas las variables estándar: query.first, query.orig, query.prev, etc.). A continuación, un ejemplo de dicho array:
[
{
"first": "test",
"prev": "",
"lvl": 0,
"num": 0,
"query": "test",
"queryUid": "6eb301",
"orig": "test"
},
{
"first": "comprobación",
"prev": "",
"lvl": 0,
"num": 1,
"query": "comprobación",
"queryUid": "774563",
"orig": "comprobación"
},
{
"first": "third query",
"prev": "",
"lvl": 0,
"num": 2,
"query": "third query",
"queryUid": "2bc8ed",
"orig": "third query"
}
]
Los resultados en el procesamiento por lotes deben completarse en el array results.bulkResults, donde cada elemento es un objeto results. Los elementos en results.bulkResults están ubicados en el mismo orden en que estaban en set.bulkQueries.
Enlaces útiles
📄️ Ejemplo de bulkQueries
Ejemplo de uso de bulkQueries con una llamada a un extractor integrado
🔗 Ejemplos y discusión
Tema en el foro con ejemplos y discusión sobre la funcionalidad de los extractores JS
🔗 Catálogo de extractores JS
Sección en el catálogo de recursos dedicada a los extractores JS
🔗 Resumen de las capacidades básicas de ES6
Artículo en habrahabr dedicado a un resumen de las capacidades básicas de ES6