Методы-хуки
Данные методы работают по принципу хуков. Реализация данных методов позволяет контролировать работу парсера на разных этапах, от инициализации до уничтожения объекта
Реализация всех методов кроме parse
являются опциональной
async parse(set, results)
Метод parse
реализует основную логику обработки запроса и получения результата парсинга, в качестве аргументов передаются:
set
- объект с информацией о запросе:set.query
- текстовая строка запросаset.lvl
- уровень запроса, по умолчанию0
results
- объект с результатами, которые необходимо заполнить и вернуть из методаparse()
- парсер должен проверять наличие каждого ключа в объекте results и заполнять его только при наличии, таким образом оптимизируется скорость и парсятся только те данные, которые используются в формировании результата
results
содержит ключи необходимых flat переменных со значениемnone
, по умолчанию это означает что результат не получен, а также ключи переменных-массивов (arrays) со значением в виде пустого массива, готового для заполненияresults.success
должен устанавливаться в значение1
при успешной обработке запроса, по умолчанию значение0
, означающее что запрос обработан с ошибкой
Разберем на примере:
class JS_HTML_Tags extends BaseParser {
static defaultConf = {
results: {
flat: [
['title', 'Title'],
],
arrays: {
h2: ['H2 Headers List', [
['header', 'Header'],
]],
}
},
...
};
async parse(set, results) {
// Получаем содержимое HTML страницы, адрес которой был передан в запросе
const {success, data, headers} = await this.request('GET', set.query);
// Проверяем успешность и тип data, при корректной обработке HTML страниц мы должны получать тип 'string', в противном случае A-Parser возвращает объект типа Buffer
if (success && typeof data == 'string') {
let matches;
// Проверяем необходимость сбора title и сохраняем значение
if (results.title && matches = data.match(/<title[^>]*>(.*?)<\/title>/))
results.title = matches[1];
// Проверяем необходимость сбора h2
if (results.h2) {
let count = 0;
const re = /<h2[^>]*>(.*?)<\/h2>/g;
while(matches = re.exec(data)) {
// Сохраняем в цикле все найденные теги h2
results.h2.push(matches[1]);
}
}
// Уведомляем об успешности парсинга
results.success = 1;
}
// Возвращаем обработанные результаты
return results;
}
};
Обратите внимание что вы можете создавать собственные функции и методы для лучшей организации кода:
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)
Данный метод используется для преобразования конфига по каким либо правилам, например при использовании каптчи нам всегда необходимо использовать сессии:
async processConf(conf) {
if (conf.useCaptcha)
conf.useSessions = 1
}
async parse(set, results) {
if (conf.useSessions)
await this.login();
}
Существование данного метода обусловлено тем что A-Parser поддерживает динамические поля конфига и в рамках одного задания конфиг может иметь разные значения, такой сценарий возможен в двух случаях:
- Использование шаблонов в полях конфигурации, например
[% tools.ua.random() %]
для поля User-Agent - Использование
overrides
при вызове одного парсера из другого дляthis.parser.request
Метод processConf
вызывается однократно перед init()
. Для случаев описанных выше processConf
вызывается дополнительно перед обработкой каждого запроса
Основные правила применения processConf
:
- Используйте только если преобразования конфига имеет эффект на производительность
- Имейте ввиду что
init
выполняется один раз, аprocessConf
может выполняться для каждого запроса, в этом случае может быть нарушена логика, еслиinit
зависит от изменяющихся полей конфига (см. ниже)
async init?()
Метод init
вызывается один раз при инициализации базового объекта парсера, служит для выполнения одноразовых действия:
- Запуск браузера
- Инициализация менеджера сессий с помощью метода
this.sessionManager.init()
- Подключение к базе данных и создание таблиц в БД
- Чтение статичных данных
- И т.д.
Т.к. метод вызывается один раз, все поля конфигурации, от которых зависит init()
не могут быть исользованы совместно с шаблонами полей конфигурации или с overrides
при вызове this.parsers.request
async destroy?()
Метод destroy
вызывается один раз при завершении работы задания, необходим для корреткного уничтожение открытых ресурсов:
- Закрытие браузера
- Закрытие подключения к БД
- И т.д.
async threadInit?()
Данный метод запускается при инициализации каждого потока, каждый поток представляет из себя копия базового объекта парсера с своим уникальным this.threadId
, который начинается с 0
и заканчивается threads_count - 1
Основные варианты применения:
- создание страницы (вкладки) браузера для каждого потока
async threadDestroy?()
Выполняется при завершении потока в процессе завершения задания, служит для освобождения ресурсов, выделенных для данного потока
async afterResultsProcessor?(results)
Данный метод выполняется после обработки результатов: конструктором результатов, фильтрацией и уникализацией. Основным вариантом применения является добавление запросов в очередь c помощью метода this.query.add
после применения пользовательских фильтров, таким образом реализована фильтрация ссылок для перехода (followlinks
) для парсера HTML::LinkExtractor