Все чаще встречаются сайты, которые требуют индивидуального подхода в процессе парсинга. Здесь, как нельзя лучше подходят решения, созданные с помощью языка программирования JavaScript, который поддерживается в A-Parser.
Основу любого языка программирования составляют переменные, которые используются для построения логики работы программы. Невозможно начать работать с системой, не зная весь перечень и особенности использования каждой из переменных. В A-Parser существует два типа переменных, которые можно использовать в проектах, созданных с помощью встроенного языка JavaScript. Рассмотрим каждый и попробуем дать исчерпывающую характеристику по их использованию.
Для наглядности и лучшего понимания материала, напишем простой JS парсер для страницы https://habrahabr.ru/all, который, например, будет собирать название, ссылку на статью и количество новых статей:
Типы переменных. При создании JavaScript парсеров в A-Parser доступны два типа переменных: flat и arrays.
Тип flat используется для определения простых переменных, в которые планируется помещать единичные значения. Соответственно, тип arrays используется для массивов данных. Оба типа могут использоваться как вместе, так и раздельно, в зависимости от исполняемой задачи и получаемых результатов.
Для более полного понимания того, как устроены переменные в А-Парсере, рекомендуем ознакомиться с этой статьей.
Работа с типом flat. Для того чтобы начать использовать переменную типа flat, ее нужно объявить в конструкторе:
В данном примере, мы обьявляем простую (flat) переменную, которая имеет название totalcount. Важно заметить, что обьявление простых переменных состоит из двух частей:
Можно обьявлять сколько угодно простых переменных, например:
Работа с типом arrays. Аналогично flat, для использования типа arrays его нужно объявить в конструкторе перед использованием:
Структура для объявления arrays отличается от flat, так как используется для вывода массива значений. В структуру включены:
Массивов и элементов, которые в них размещаются, можно объявить столько, сколько требует задание, например:
В нашем примере, мы объявили один массив с названием serp, в котором планируется размещать два элемента link и name, которые будут элементами массива со значениями ссылок и имен соответственно.
Сохранение в flat. После декларирования (объявления) переменной типа flat, она становится доступной для записи и вывода в результаты. Согласно базовым принципам создания JS парсеров, все результирующие переменные хранятся в объекте results, поэтому все переменные доступны для записи и чтения, через обращение к этому обьекту. В нашем примере мы используем конструкцию:
Т.е. в results.totalcount записывается результат некой функции, которая в данном случае забирает значение из кода страницы с помощью регулярного выражения.
Таким образом, мы получаем в переменной totalcount значение +39, которое будет доступным для вывода в результаты при использовании в формате результата переменной $totalcount.
Сохранение в arrays. По аналогии с flat, после декларирования становится доступным использование массивов arrays. Важно понимать, что массивы результатов в JS парсере отличаются от таковых в обычных пресетах. Более детально это показано на примере ниже.
Таким образом, в JS парсерах для записи значений в массив нужно использовать обычные методы для работы с массивами. Чаще всего это .push.
Реальный пример показан в парсере, о котором упоминалось в начале статьи. В нем регулярным выражением извлекаются из кода страницы необходимые данные и в цикле записываются в массив:
Таким образом, полученные значения будут доступны в парсере, например, при таком формате результата: $serp.format('$link - $name\n'). Значения можно выводить как вместе, так и раздельно, например $serp.format('$link\n'). Более подробно о методе .format в этом разделе Документации.
Оптимизация. Для оптимизации потребления ресурсов, а также увеличения скорости работы создаваемых парсеров, реализован следующий механизм. Если в формате результата не используется какой-то из объявленных массивов, то он имеет значение undefined. Благодаря этому, есть возможность проверять, нужен ли конечному пользователю результат из данного массива, и если не нужен, то пропускать его парсинг, тем самым экономя время и ресурсы. Например:
Если массив $serp не выводится в результат, то полностью пропускается парсинг всех его элементов, а именно: не применяется регулярное выражение и не запускается цикл для перебора и записи полученных данных.
При записи результатов в массив, рекомендуется использовать данную проверку. При ее отсутствии, если пользователь не будет выводить массив в результат, то парсер все равно попытается записать результат в массив, и будет получена ошибка, т.к. массив по сути будет не объявлен.
В этой статье были рассмотрены типы переменных, которые используются при создании JavaScript парсеров. Подробно описан процесс объявления переменных, их заполнение и вывод в результаты. Также продемонстрированы примеры использования каждого типа переменных. Этот материал будет полезен в первую очередь тем, кто планирует начать создавать собственные парсеры на JavaScript.
Основу любого языка программирования составляют переменные, которые используются для построения логики работы программы. Невозможно начать работать с системой, не зная весь перечень и особенности использования каждой из переменных. В A-Parser существует два типа переменных, которые можно использовать в проектах, созданных с помощью встроенного языка JavaScript. Рассмотрим каждый и попробуем дать исчерпывающую характеристику по их использованию.
Для наглядности и лучшего понимания материала, напишем простой JS парсер для страницы https://habrahabr.ru/all, который, например, будет собирать название, ссылку на статью и количество новых статей:
Код:
class Parser {
constructor() {
this.defaultConf = {
version: '0.1.18',
results: {
flat: [
['totalcount', 'Total results count']
],
arrays: {
serp: ['List', [['link', 'Link'], ['name', 'Name']]]
}
},
results_format: "$totalcount\n$serp.format('$link - $name\\n')",
parsecodes: {
200: 1,
},
page_count: '1'
};
this.editableConf = [
['page_count', ['combobox', 'PageCount', ['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'], ['9', '9'], ['10', '10']]]
];
}
*parse(set, results) {
let success = 1;
for(let i = 1; i<=this.conf.page_count; i++){
let link = set.query + 'page' + i;
let response = yield this.request('GET', link, {}, {
decode: 'utf8',
});
if(this.conf.page_count == 1) {
try {
results.totalcount = parseInt(response.data.match(/<span class="tabs-menu__item-counter tabs-menu__item-counter_new">(.+?)<\/span>/)[1]);
} catch(e) {
this.logger.put('Results count not found');
}
}
if(!response.success) {
this.logger.put('Error open page');
success = 0;
break;
}
if(results.serp !== undefined) {
let regexp = /<h2 class="post__title">\n\s+<a href="(.+?)"\sclass="post__title_link">(.+?)<\/a>/g;
let res;
while (res = regexp.exec(response.data)) {
results.serp.push(res[1], res[2]);
}
}
}
results.success = success;
return results;
}
}
Код:
eJyNVm1v2zgM/iuaEMDJNXWSbl07p+mhV7SHDcXaW3v3JQ4CxVYSr47kSXJfEPi/
Hym/JY4POH1oKVKkHpKP6GypYfpZPyiuudHUm25pYmXq0X+YunmjfZowpblC45R+
e/S8F6Yitoi5BlvIlyyNDZ3N+hT8QNS3Um0Y+neSkVsEq4yP7IU/STAuo5jX6lvY
fWcbjl4hMxyt7tIG6vZc84YRWBhGJpKCxfkNCKi+9W8R/UrRX0g4C6KKuL5VcgMq
w20AVL6X6Ka0Y/cUQqTW96/ch3pLFmvepxqg3jIAEjYtkeGKGanuE8QD+i2V4iqO
7/gLj+tjNv4faRSHUL2rJTh9LRzbj9wfxMiq9HaveuHqVQGG+lAo7+SqzP2Z86Sq
xnfUbKTiVYDi5iIuND7hIoSTdTOuklq1B3Cv4PvKQIpltLoHaCoKeXkyFU/Arntx
LTdJzBGxSOMYCq75j7rxV7ooMG5qgE3na3sFwCo516dGylh/e8yhJioCYp1WzQft
2phEe4PBmi0Uwz+uSgcsjgdwPACarSQQAKBms4rl1UvYNrjubTOo9E/9kJ9DrK2n
aLVxfyKGIGZak9yLbH1BYEG1tFFpAFTo9kolLrOOtFvkh/mSya4VF1RYQyM94gzd
kTs6c/r79qI7XtMP1zJmxiPTQwOuqWOkYXEgU2GcPnGecFeGI7l6dug66x/qmFLs
vR0CLihEAjCcu0jjTdOpE0fiGe+8w/8zUDkChgFqcCg4s1nLxdm+KuvvbFpLMs/n
iUd82qlT9X3RQUDltHE6CIYckw5C8GEJp+fTRpaWLIEEprdmeTIcemTUbyJsxljx
ucUAzRw5tTEb+6JBCQ6jDzlVcKLRwqlTx8KCOoHcLORCvmEFH8B0XVlGqBrlNT5B
+SSXP6L8MZc/ofwpl09RPs3lzyh/zuUzlM9y+Rzl81z+gvKXXB4N7WXD/f7Nxrmc
lUn+ZovZhVfXL1u19ybg7ROdBgGHZzQho3FtgZZ10RpZPYkuJrZYOIvcuiJgODrq
bXdrWoa1rZ4AIY1rBx05IraUDgjRuM0DACbweDl4vUc8DvP2KA7uGsjz580T5Ixh
+2QLlGzhRmh5Ay1PzfK8+Xqz3nhfsb+Llt22DMkE8u81LzOQT0Plm6LAbv0AIBPb
gK/CdMvsXPgGMxeeQ7DuDi50wgSxY2ziw8+FhT7ecJHO5/AJ2hzbGDDZ/kM/F/zV
p5dd9+j33oXvDzDW5aA3Hc2amWYksPfxg0RsMph2LFcrrtwkhUr/2B1MREgDbEhF
6BwU0DQHRbOtUNQPVeIF0f4fhhulpCISvpb2MR/cjatm7rDFulCcPTcLcQCvbBrO
KfIBmg2Jwk8kwcNWnDlPV/wtgVsHF+uTqnmJ1GY+N5GJOTQFRpvv66MLRtaKL8Fs
u+RTULY4zJHVu61kl4NVS0rFK2mxvK7hm0kwG8CVA3T5Gw/2addrzQnXbhmgAXqN
jsAkOzamJweMainmznZHrAJXvSqk8e4ZkypRHq1nWEbxZ0HxVabeKPsXpUhX3g==
Типы переменных. При создании JavaScript парсеров в A-Parser доступны два типа переменных: flat и arrays.
Тип flat используется для определения простых переменных, в которые планируется помещать единичные значения. Соответственно, тип arrays используется для массивов данных. Оба типа могут использоваться как вместе, так и раздельно, в зависимости от исполняемой задачи и получаемых результатов.
Для более полного понимания того, как устроены переменные в А-Парсере, рекомендуем ознакомиться с этой статьей.
Работа с типом flat. Для того чтобы начать использовать переменную типа flat, ее нужно объявить в конструкторе:
Код:
class Parser {
constructor() {
this.defaultConf = {
version: '0.1.18',
results: {
flat: [
['totalcount', 'Total results count']
],
- имени переменной (totalcount) - значение, которое будет использоваться в самом коде парсера при обращении к переменной
- описания переменной (Total results count) - используется исключительно для визуального отображения переменной в интерфейсе парсера:
Можно обьявлять сколько угодно простых переменных, например:
Код:
flat: [
['first', 'Первая переменная'],
['second', 'Вторая переменная'],
...
['n', 'N-я переменная']
]
Работа с типом arrays. Аналогично flat, для использования типа arrays его нужно объявить в конструкторе перед использованием:
Код:
class Parser {
constructor() {
this.defaultConf = {
version: '0.1.18',
results: {
flat: [
['totalcount', 'Total results count']
],
arrays: {
serp: ['List', [['link', 'Link'], ['name', 'Name']]]
}
- имя массива (serp) – для использования в коде
- заголовок массива (List) - используется для визуального отображения в интерфейсе парсера
- объявление каждого элемента массива (['link', 'Link']) - имя и название аналогично типу flat
Массивов и элементов, которые в них размещаются, можно объявить столько, сколько требует задание, например:
Код:
arrays: {
arr1: ['Array 1', [['el1', 'First element'], ['el2', 'Second element']]],
arr2: ['Array 2', [['el', 'Single element']]],
...
arrN: ['Array 3', [['el1', 'First element'], ['el2', 'Second element'], ..., ['elN', 'N-th element']]]
}
Сохранение в flat. После декларирования (объявления) переменной типа flat, она становится доступной для записи и вывода в результаты. Согласно базовым принципам создания JS парсеров, все результирующие переменные хранятся в объекте results, поэтому все переменные доступны для записи и чтения, через обращение к этому обьекту. В нашем примере мы используем конструкцию:
Код:
results.totalcount = parseInt(response.data.match(/<span class="tabs-menu__item-counter tabs-menu__item-counter_new">(.+?)<\/span>/)[1]);
Таким образом, мы получаем в переменной totalcount значение +39, которое будет доступным для вывода в результаты при использовании в формате результата переменной $totalcount.
Сохранение в arrays. По аналогии с flat, после декларирования становится доступным использование массивов arrays. Важно понимать, что массивы результатов в JS парсере отличаются от таковых в обычных пресетах. Более детально это показано на примере ниже.
Объявим в конструкторе такой массив результатов:
Согласно общему представлению переменных в А-Парсере, это будет массив, имеющий примерно такую структуру:
Т.е. массив хэшей. Если в формате результата задать такой шаблон:
то мы получим результат такого вида:
Но, в JS парсерах данный массив имеет такой вид:
Т.е. именно массив, в классическом его виде. А-Парсер автоматически преобразовывает данный "обычный" массив в массив хэшей согласно объявленной в конструкторе структуре.
Код:
arrays: {
arr1: ['Array 1', [['el1', 'First element'], ['el2', 'Second element']]]
}
Код:
{
"arr1": [
{
"el1": "1-1",
"el2": "1-2"
},
{
"el1": "2-1",
"el2": "2-2"
},
{
"el1": "3-1",
"el2": "3-2"
}
]
}
Код:
$arr1.format('$el1, $el2\n')
Код:
1-1, 1-2
2-1, 2-2
3-1, 3-2
Код:
{
"arr1": [
"1-1",
"1-2",
"2-1",
"2-2",
"3-1",
"3-2"
]
}
Таким образом, в JS парсерах для записи значений в массив нужно использовать обычные методы для работы с массивами. Чаще всего это .push.
Реальный пример показан в парсере, о котором упоминалось в начале статьи. В нем регулярным выражением извлекаются из кода страницы необходимые данные и в цикле записываются в массив:
Код:
let regexp = /<h2 class="post__title">\n\s+<a href="(.+?)"\sclass="post__title_link">(.+?)<\/a>/g;
let res;
while (res = regexp.exec(response.data)) {
results.serp.push(res[1], res[2]);
};
Оптимизация. Для оптимизации потребления ресурсов, а также увеличения скорости работы создаваемых парсеров, реализован следующий механизм. Если в формате результата не используется какой-то из объявленных массивов, то он имеет значение undefined. Благодаря этому, есть возможность проверять, нужен ли конечному пользователю результат из данного массива, и если не нужен, то пропускать его парсинг, тем самым экономя время и ресурсы. Например:
Код:
if(results.serp !== undefined) {
let regexp = /<h2 class="post__title">\n\s+<a href="(.+?)"\sclass="post__title_link">(.+?)<\/a>/g;
let res;
while (res = regexp.exec(response.data)) {
results.serp.push(res[1], res[2]);
}
}
При записи результатов в массив, рекомендуется использовать данную проверку. При ее отсутствии, если пользователь не будет выводить массив в результат, то парсер все равно попытается записать результат в массив, и будет получена ошибка, т.к. массив по сути будет не объявлен.
В этой статье были рассмотрены типы переменных, которые используются при создании JavaScript парсеров. Подробно описан процесс объявления переменных, их заполнение и вывод в результаты. Также продемонстрированы примеры использования каждого типа переменных. Этот материал будет полезен в первую очередь тем, кто планирует начать создавать собственные парсеры на JavaScript.