Перейти к основному содержимому

Парсеры на JavaScript: Обзор возможностей

JavaScript парсеры - это возможность создавать собственные полноценные парсеры со сколько угодно сложной логикой, используя язык JavaScript. При этом в JS парсерах можно также использовать весь функционал стандартных парсеров.

Обзор

Особенности

Используя всю мощь A-Parser теперь можно написать свой парсер/регер/постер со сколько угодно сложной логикой. Для написания кода используется JavaScript с возможностями ES6 (движок v8).

Код парсеров максимально лаконичен, позволяет сосредоточится на написании логики; работу с многопоточностью, сетью, прокси, результатами, логами и т.д. A-Parser берет на себя. Код можно писать прямо в интерфейсе парсера, добавив новый парсер в Редакторе парсеров. Также для написания парсеров можно использовать сторонние редакторы, например VSCode.

Используется автоматическое версионирование при сохранении кода парсера через встроенный редактор.

примечание

Работа с JavaScript парсерами доступна для лицензий Pro и Enterprise

Доступ к Редактору JS парсеров

Если А-Парсер используется удаленно, то в целях безопасности Редактор JS парсеров по умолчанию не доступен. Чтобы открыть к нему доступ, необходимо:

  • Установить пароль на вкладке Настройки -> Общие настройки
  • Добавить в config/config.txt следующую строчку: allow_javascript_editor: 1
  • Перезапустить A-Parser

Инструкция по работе

В Редакторе парсеров создаем новый парсер и задаем имя парсера. По умолчанию будет загружен простой пример, на основе которого можно быстро приступить к созданию собственного парсера.

примечание

Если для написания кода используется сторонний редактор, то нужно открыть файл редактируемого парсера в папке /parsers/. Структура файлов установленной программы.

Когда код будет готов, сохраняем его и используем как обычный парсер: в Редакторе заданий выбираем созданный парсер, при необходимости можно задать нужные параметры, конфиг потоков, имя файла и т.п.

Созданный парсер можно в любой момент редактировать. Все изменения, касающиеся интерфейса, появятся после повторного выбора парсера в списке парсеров или перезапуска А-Парсера; изменения в логике парсера применяются при повторном запуске задания с парсером.

Для каждого созданного парсера по умолчанию отображается стандартная иконка, можно добавить свою в формате png или ico, разместив ее в папке парсера в /parsers/:

Общие принципы работы

По умолчанию создается пример простого парсера, готовый для дальнейшего редактирования.

files/parsers/v2-example/v2-example.ts

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;
}
}

Конструктор вызывается однократно для каждого задания. Необходимо обязательно задать this.defaultConf.results и this.defaultConf.results_format, остальные поля необязательны и будут принимать значения по-умолчанию.

Массив this.editableConf определяет какие настройки могут быть изменены пользователем из интерфейса A-Parser. Можно использовать следующие типы полей:

  • combobox - выпадающее меню выбора. Также можно сделать меню выбора пресета стандартного парсера, например:
['Util_AntiGate_preset', ['combobox', 'AntiGate preset']]
  • combobox с возможностью множественного выбора. Нужно дополнительно задать параметр {'multiSelect': 1}:
['proxyCheckers', ['combobox', 'Proxy Checkers', {'multiSelect': 1}, ['*', 'All']]]
  • checkbox - чекбокс, для параметров которые могут иметь только 2 значения (true/false)
  • textfield - текстовое поле
  • textarea - текстовое поле с многострочным вводом

Метод parse представляет собой асинхронную функцию, и на любую блокирующую операцию должна возвращать await (это основное и единственное отличие от обычной функции). Метод вызывается для каждого запроса поступившего в обработку. Обязательно передается set (хэш с запросом и его параметрами) и results (пустая заготовка для результатов). Также обязательно необходимо вернуть заполненый results, предварительно выставив флаг success.

Автоматическое версионирование

Версия имеет формат Major.Minor.Revision

this.defaultConf: typeof BaseParser.defaultConf = {
version: '0.1.1',
...
}

Значение Revision (последняя цифра) автоматически увеличивается при каждом сохранении. Остальные значения (Major, Minor) можно менять вручную, а также сбрасывать Revision в 0.

подсказка

Если по каким то причинам необходимо менять Revision только вручную, то версию необходимо заключить в двойные кавычки ""

Пакетная обработка запросов

В некоторых случаях может потребоваться брать сразу несколько запросов из очереди и обрабатывать их за один раз. Например, такой функционал используется в SE::Yandex::Direct::FrequencySE::Yandex::Direct::Frequency: при парсинге с аккаунтами данные собираются пачками по 10 запросов.

Чтобы реализовать такой же функционал в JS парсере, нужно в this.defaultConf задать значение bulkQueries: N, где N - необходимое количество запросов в пачке. В этом случае парсер будет брать запросы пачками по N штук и все запросы текущей итерации будут содержатся в массиве set.bulkQueries (включая все стандартные переменные: query.first, query.orig, query.prev и т.п.). Ниже пример такого массива:

[
{
"first": "test",
"prev": "",
"lvl": 0,
"num": 0,
"query": "test",
"queryUid": "6eb301",
"orig": "test"
},
{
"first": "проверка",
"prev": "",
"lvl": 0,
"num": 1,
"query": "проверка",
"queryUid": "774563",
"orig": "проверка"
},
{
"first": "third query",
"prev": "",
"lvl": 0,
"num": 2,
"query": "third query",
"queryUid": "2bc8ed",
"orig": "third query"
}
]

Результаты при пакетной обработке необходимо заполнять в массиве results.bulkResults, где каждый элемент является обьектом results. Элементы в results.bulkResults расположены в той же очередности, которая была в set.bulkQueries.