Создание JS парсеров. Парсинг сайта с проходом по страницах

Рассмотрен пример парсинга сайта по запросу с переходом по страницах

  1. Support Юра
    В данной статье рассмотрим возможность получение результатов в парсере, созданному с помощью языка программирования JavaScript, без использования готовых парсеров. В парсере предусмотрим проход по страницам и отбор нужных данных. Для решения такой задачи, в A-Parser предусмотрена функция this.request работу которой попробуем раскрыть дальше на примере создания парсера для сайта https://habrahabr.ru/all/.

    Разработку парсера начнем с определения конструктора результатов, в котором укажем необходимые сущности:
    • version — версия парсера;
    • results: {arrays: {serp: ['List', [['link', 'Link'], ['name', 'Name']]]}} — структура массива с результатами, в который будем помещать полученные результаты
    • results_format: "$serp.format('$link - $name\\n')" — определим вывод результатов по умолчанию
    • page_count: '5' — зададим по умолчанию значение переменной. Это значение можно будет менять через пользовательский интерфейс
    • 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']]]] — значение, которое можно устанавливать через пользовательский интерфейс. Имеет вид выпадающего списка со значениями (в данном случаи количество страниц которое нужно пользователю)
    Полный код конструктора будет выглядеть так:
    Код:
    constructor() {
            this.defaultConf = {
                version: '0.1.3',
                results: {
                    arrays: {
                        serp: ['List', [['link', 'Link'], ['name', 'Name']]]
                    }
                },
                results_format: "$serp.format('$link - $name\\n')",
                parsecodes: {
                    200: 1,
                },
                page_count: '5'
            };
    
            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. Согласно документации, для получение HTTP ответа по запросу нужно использовать функцию yield this.request. В качестве аргументов нужно указать:
    • method
    • url
    • хэш с query параметрами
    • хэш с опциями запроса
    В нашем случаи, нужно ещё предусмотреть проход по страницам. Поэтому создаем следующие переменные:
    • i — рабочая переменная в которой будет хранится значение текущей страницы;
    • link — переменная в которой будет хранится ссылка (url);
    • set.query — переменная с запросом (по умолчанию у нас запрос на сайт «https://habrahabr.ru/all/»);
    • response — переменная в которую будет помещен результат с ответом от сервера
    После определения переменных, строим логику работы:
    • for(let i = 1; i<=this.conf.page_count; i++) - используем цикл для прохода по страницам;
    • let link = set.query + 'page' + i; - формируем url;
    • let response = yield this.request('GET', link, {}, {decode: 'utf8',}) - получаем ответ по запросу в переменную "response". Здесь упущены дополнительные параметры для запроса, но указана опция "decode" - которая определяет кодировку в которой приходит страница. Опций можно указывать больше чем одну, разделяя их запятыми.
    Проверяем успешность ответа от сервера:
    Код:
    if(!response.success) {
                    this.logger.put('Error open page');
                    success = 0;
                    break;
                }
    В случаи неудачи, выводим сообщение в лог «Error open page». Если ответ успешный, продолжаем работу.

    Проверяем полученный массив результатов:
    Код:
    «if(results.serp !== undefined)»
    Если массива не существует, выбираем с помощью регулярных выражений интересующие нас данные с переменной «response.data» и заполняем наш массив:
    Код:
    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]);
               }
    На этом создание парсера завершено. В результат мы получаем массив «serp» - в котором собраны данные в виде "ссылка — название статьи", значения "$link - $name" которые мы указали в конструкторе.
    [​IMG]
    Полный код парсера можно посмотреть в каталоге.

    В данном обзоре была рассмотрена очередная возможность, которая доступна средствами JavaScript в A-Parser. Используя конструкцию "yield this.request", можно получать HTTP ответ по запросу.