Все чаще встречаются сайты, которые требуют индивидуального подхода в процессе парсинга. Здесь, как нельзя лучше подходят решения, созданные с помощью языка программирования JavaScript, который поддерживается в A-Parser.
Основу любого языка программирования составляют переменные, которые используются для построения логики работы программы. Невозможно начать работать с системой, не зная весь перечень и особенности использования каждой из переменных. В 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, ее нужно объявить в конструкторе:
В данном примере, мы обьявляем простую (flat) переменную, которая имеет название totalcount. Важно заметить, что обьявление простых переменных состоит из двух частей:Код:class Parser { constructor() { this.defaultConf = { version: '0.1.18', results: { flat: [ ['totalcount', 'Total results count'] ],
- имени переменной (totalcount) - значение, которое будет использоваться в самом коде парсера при обращении к переменной
- описания переменной (Total results count) - используется исключительно для визуального отображения переменной в интерфейсе парсера:
Можно обьявлять сколько угодно простых переменных, например:
Работа с типом arrays. Аналогично flat, для использования типа arrays его нужно объявить в конструкторе перед использованием:Код:flat: [ ['first', 'Первая переменная'], ['second', 'Вторая переменная'], ... ['n', 'N-я переменная'] ]
Структура для объявления arrays отличается от flat, так как используется для вывода массива значений. В структуру включены:Код: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
Массивов и элементов, которые в них размещаются, можно объявить столько, сколько требует задание, например:
В нашем примере, мы объявили один массив с названием serp, в котором планируется размещать два элемента link и name, которые будут элементами массива со значениями ссылок и имен соответственно.Код: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 записывается результат некой функции, которая в данном случае забирает значение из кода страницы с помощью регулярного выражения.Код: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 парсере отличаются от таковых в обычных пресетах. Более детально это показано на примере ниже.
Объявим в конструкторе такой массив результатов:
Согласно общему представлению переменных в А-Парсере, это будет массив, имеющий примерно такую структуру:Код: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')
Но, в JS парсерах данный массив имеет такой вид:Код: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.
Реальный пример показан в парсере, о котором упоминалось в начале статьи. В нем регулярным выражением извлекаются из кода страницы необходимые данные и в цикле записываются в массив:
Таким образом, полученные значения будут доступны в парсере, например, при таком формате результата: $serp.format('$link - $name\n'). Значения можно выводить как вместе, так и раздельно, например $serp.format('$link\n'). Более подробно о методе .format в этом разделе Документации.Код: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. Благодаря этому, есть возможность проверять, нужен ли конечному пользователю результат из данного массива, и если не нужен, то пропускать его парсинг, тем самым экономя время и ресурсы. Например:
Если массив $serp не выводится в результат, то полностью пропускается парсинг всех его элементов, а именно: не применяется регулярное выражение и не запускается цикл для перебора и записи полученных данных.Код: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.
-
Вступайте в наш Telegram чат: https://t.me/a_parser Нас уже 2600+ и мы растем!Скрыть объявление
Переменные в парсерах JavaScript
Описание типов переменных в JS парсерах и примеры работы с ними
Метки: