Не всегда выходит получить код страницы простым запросом. Иногда на сайте присутствуют некоторые ограничения, не позволяющие это сделать. Часть из них можно обойти, подставив User-Agent, другие решаются подстановкой необходимых куки и заголовков. Разберем на примере auto.ru, как работать с такими сайтами.
Первый способ (быстрый)
Для начала попробуем сделать обычный запрос, допустим, через парсерNet::HTTP, и посмотрим, что придет нам в ответ. Для этих целей будет использовать Тестовый парсинг в режиме дебага. Так будет удобно видеть все, что происходит от запроса к ответу, в том числе заголовки и куки. Отправим запрос на http://auto.ru.
Ответ пришел с кодом 200 ОК. Видим, что вес ответа составляет 5553 байта. Раскрываем код страницы через See full data или листаем чуть ниже и смотрим, что нам пришло.
Видим, что нужного нам контента нет. Чтобы продолжить работу, нужно согласиться с правилами сайта. Об этом нам подсказывает текст, выделенный красным. Смотрим дальше. Разработчики оставили нам подсказку, она выделена синим. Понимаем, что необходимо вместе с запросом передавать какие-то куки, но где их взять? Снова обратимся к дебагу и посмотрим данные об ответе, который пришел.
Находим заголовки и видим, что среди них есть set-cookie. Это то, что нам нужно. Теперь надо создать простейший JavaScript-парсер, который первым запросом будет получать эти куки и подставлять их во все последующие запросы.
Для удобства, создадим отдельный метод *getCookie(), в котором будет происходить вся работа с их получением. Делаем запрос на http://auto.ru без каких-либо дополнительных заголовков. Если запрос удачный, возвращаем response.headers[‘set-cookie’], который мы видели в Тестовом парсинге. Далее, в методе *parse() обращаемся к методу getCookie() и помещаем наши куки в константу cookie. Пробуем отправить второй запрос, указав в headers наши cookie и смотрим в дебаге, какой теперь будет ответ.
Видим, что ответ не изменился. Значит чего-то не хватает. Смотрим дальше код страницы, пытаемся понять, что мы могли упустить.
Обнаруживаем вот такую строчку, которую мы пропустили в первый раз. Попробуем подставить в наши куки «;autoru_gdpr=1;path=/;max-age=31536000;secure;domain=auto.ru».
Вот так. Снова делаем запрос и смотрим, что получилось.
Размер ответа стал значительно больше. Если раскрыть код, станет ясно, что все прошло успешно. Таким образом, требовалось лишь понять, каких заголовков не хватает запросу, чтобы auto.ru его пропустил и отдал нам нужные данные. Теперь мы можем передавать cookie в объект set и использовать их между запросами, единожды получив. Если в какой-то момент заголовки (куки) устареют, можно попытаться идентифицировать это по характерному ответу и получить заново, т.к. для этого будет достаточно обратиться к методу getCookie(), который мы вынесли отдельно.
Второй способ (простой, но ресурсоемкий)
Также существует альтернативный и в какой-то мере более простой вариант получения заголовков и куки через модуль puppeteer. Он может быть уместен в случаях, когда заголовков слишком много и невозможно понять, откуда они приходят. Такое довольно часто происходит с CSRF-токеном, когда он скрыт в скриптах, подгружаемых страницей динамически. Рассмотрим этот способ на примере.
Перед началом необходимо установить puppeteer в директории /aparser/files/ командой npm I puppeteer. Также необходимо создать файл config.txt с содержимым «allow_dangerous_node_modules: 1» в директории /aparser/config/, чтобы puppeteer корректно работал.
Теперь подключим puppeteer внутри нашего парсера. И сразу объявим переменную browser.
Переменную browser мы объявили вне класса парсера для того, чтобы можно было «аварийно» завершить его работу в методе destroy() в случае, когда по какой-то причине она не была завершена в ходе работы парсера, иначе процессы chrome.exe (chromium) будут висеть в памяти даже после окончания парсинга и нагружать компьютер.
Сразу напишем метод destroy().
Не забываем, что puppeteer – асинхронный модуль, значит перед его методами следует ставить await, а перед функцией\методом, в котором происходит работа с ним, нужно писать async.
Данный метод вызывается при завершении работы парсера и в случае, если переменная browser не пуста, он завершает работу (закрывает) браузер, который в ней объявлен.
Объявим внутри класса новую асинхронную функцию – getCookieByPuppeteer().
На вход подаем set, чтобы вытащить из него наш запрос (http://auto.ru).
Теперь по порядку. Сначала запускаем браузер с помощью метода puppeteer.launch() и помещаем его в browser. Передаем в качестве аргумента объект с параметром headless равным false. Этот параметр указывает на то, чтобы браузер запустился вместе с интерфейсом. Удобно использовать при отладке. Значение true соответственно скроет интерфейс.
Далее создаем новую страницу (browser.newPage()) и помещаем ее в константу page. Метод page.goto(url) позволяет перейти по заданной ссылке. Передаем туда set.query. Т.к. необходимо дождаться загрузки страницы, используем page.waitForSelector(selector). Где selector – указываем класс кнопки, на которую нужно нажать, чтобы согласиться с правилами. Следующим действием нажимает на эту кнопку по тому же селектору методом page.click(selector). Затем дожидаемся полной загрузки страницы (page.waitForNavigation()). После того, как страница была загружена, вытаскиваем куки методом page.cookies() и помещаем их в переменную cookie. Закрываем браузер и возвращаем cookie.
Далее немного изменим метод *parse(). Во-первых, добавим async перед названием метода. Во-вторых, объявим переменную cookie, как и прежде, но вместо yield* перед this.getCookieByPuppeteer() пишем await, т. к. это уже не генератор, а асинхронная функция. Больше ничего менять не нужно. Пробуем запустить тестовый парсинг.
Можем наблюдать, как puppeteer запускает браузер, нажимает на кнопку и переходит на главную страницу. Затем браузер закрывается и куки передаются в парсер.
Смотрим, прошел ли запрос успешно.
Видим, что все отлично.
Мы разобрали два способа работы с куки и заголовками: простой и чуть сложнее. Оба имеют право на жизнь, но рекомендуется все же использовать просто запросы, т. к. они быстрее и менее подвержены ошибкам.
-
Вступайте в наш Telegram чат: https://t.me/a_parser Нас уже 2600+ и мы растем!Скрыть объявление
Работа с куками и заголовками на примере соглашения с правилами сайта auto.ru
Рассмотрим два варианта: быстрый (this.request) и простой, но ресурсоемкий (puppeteer).


![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.03.36.png&hash=f1501379d610cebb61e150197082e40f)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.05.12.png&hash=75f7273c0d7bce8310db08c3fe64d20c)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.06.34.png&hash=15c850b2c08ce1c706710db4baac7b12)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.07.40.png&hash=5a115d3b420bf9e9e953ed498c5b8f2a)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.09.35.png&hash=3c184adadcaa35c14aec11f3abb77c31)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.10.56.png&hash=355aa6f7c6b551d4b3754a78f8e13f6e)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.11.55.png&hash=9346432691ddaa253090711add514a52)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.12.48.png&hash=ba9f7164f9d43ff6a64d20f822e20e18)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FAutoRu-Example.js_%25E2%2580%2594_C__Users_Admin_Desktop_aparser_files_%25E2%2580%2594_Atom_2020-08-25_12.18.59.png&hash=b6342d33542652de78dda80db380af22)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FAutoRu-Example.js_%25E2%2580%2594_C__Users_Admin_Desktop_aparser_files_%25E2%2580%2594_Atom_2020-08-25_12.20.22.png&hash=0788fbdfb21481804bcbfce3e381e0c4)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FAutoRu-Example.js_%25E2%2580%2594_C__Users_Admin_Desktop_aparser_files_%25E2%2580%2594_Atom_2020-08-25_12.21.24.png&hash=fbe9e11f965b2aba861d8a370bfd9a3d)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FAutoRu-Example.js_%25E2%2580%2594_C__Users_Admin_Desktop_aparser_files_%25E2%2580%2594_Atom_2020-08-25_12.24.20.png&hash=5bada8b4400398a32f6864766efb4fa4)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FFotografii_2020-08-25_12.25.34.png&hash=e1b740aee065dafd0f87b2ff0c92fc49)
![[IMG]](proxy.php?image=https%3A%2F%2Ffiles.a-parser.com%2Fimg%2FRabota_s_kukami_i_zagolovkami_na_primere_soglasheniya_s_pravilami_saita.odt_-_LibreOffice_Writer_2020-08-25_12.27.04.png&hash=62d6e613f2a8f58af86888b5f989aaca)