Как стать автором
Обновить

Как получить контент веб-страницы, если по ссылке с именем хоста не получилось

Время на прочтение6 мин
Количество просмотров11K

Простым языком об использовании PHP с cURL на одном примере сайта с JavaScript-защитой.

1. Парсер для получения контента по ссылкам

Задача парсера тривиальная - агрегатор новостей: сбор контента с новостных сайтов.
На входе: файл с URL-ссылками на статьи для сбора.

Веб-интерфейс для администратора: php-страница с кнопкой для запуска скрипта парсера.
Скрипт: использование cURL - с минимальным набором опций.

function cURL_get_content($url){
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

	$urlContent = curl_exec($ch);
	curl_close($ch);
	return $urlContent;
}

Кейс:

1) Пользователь:

  • заходит на страницу запуска скрипта,

  • нажимает кнопку запуска.

    2) Скрипт:

  • обходит (в цикле) массив ссылок на сайты,

  • собирает контент статей,

  • формирует веб-страницы по заданному шаблону.

Проблема: наткнувшись на интересную статью с сайта о недвижимости (Домофонд), попытался добавить ее в файл ссылок для сбора контента.

Контент со страницы не собрался: 403 Forbidden.

Ссылка: https://www.domofond.ru/statya/kolichestvo_dolgostroev_uvelichilos_v_vosemnadtsati_regionah_rf_za_2021_god/102082

Спойлер: если сразу интересно найденное решение, то можно переходить к заключению, пропустив бесплодные попытки поиска.

2. Попытка решения в лоб за счет "имитации" браузера доп. заголовками в запросе

В поисках сначала натолкнулся на статьи о том, что некоторые сайты ставят защиту от ботов (чем и является парсер для сбора контента). Например, при использовании cURL надо "оживлять" запрос заголовками, что я и делал, но безуспешно - проиллюстрирую одной из попыток.

function cURL_get_content($url){
$url_1 = "https://www.domofond.ru/";
$url_2 = $url;

$headers = array(
	'GET ' . $url_2 . ' HTTP/1.1',
	"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 
    "Accept-Encoding: gzip, deflate", 
    "Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7", 
    "Host: domofond.ru", 
	"Referer: domofond.ru", 
    "Upgrade-Insecure-Requests: 1", 
	'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
	'Cookie: dfuid=5e0dd723-40e6-46cf-a2f1-1db784e320e1; _ga=GA1.2.140590976.1641893876; rrpvid=42725831313485; rcuid=6166ad1a101fb8000139a8a9; _ym_uid=1641893879540019262; _ym_d=1641893879; __gads=ID=00752b7382f51452:T=1641893879:S=ALNI_ManEsFfeviPUR29VUUnBx_DcgsAxQ; _gid=GA1.2.589118605.1642400326; _ym_visorc=w; _ym_isad=2; cto_bundle=ellcGV9VT0c4Q0Vrd2E3dEhtVmhJNk1Ic20xaHNnNXhuSiUyRiUyQiUyRnZYMlFEV0tnNExTWmhQUjJJVzdUOHdkNmlKdnh1aEZtUWMzQ0dxV25Nb3hrYktOeUpEMjZLZ0xLTFElMkZDekxiSkh6elEyOFM0UHVZZ2xHTklpQ2RJOTRkb1Q3QUNTODRlR0hnU0Z1MEFkeDBtNTc1MVozdjVndyUzRCUzRA'
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
...
}

Пример запроса с заголовками:
GET /statya/kolichestvo_dolgostroev_uvelichilos_v_vosemnadtsati_regionah_rf_za_2021_god/102082 HTTP/1.1 Host: www.domofond.ru User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Accept: ... +куки +смотрел/добавлял заголовки, отправленные в браузере

2.1. Заголовок с Host

Хотя при добавлении хост-заголовка все же возникла одна из мыслей.

Если значение заголовка менялось с "Host: www.domofond.ru" на "Host: domofond.ru" (без www.), то появлялась ошибка: 421 Misdirected Request.

Поэтому в браузере я вручную открывал страницу с/без www - естественно, визуально для меня ничего не менялось.

Перенаправление срабатывало нормально, но потом я еще решил изменить и протокол, чтобы проверить, какой будет редирект.

Сменив в браузере ссылку с https:// на http:// (с/без www) получал нормальный редирект на главное зеркало (https://www.) с нормальным отображением статьи.

Заменив ссылку на https://146.158.48.9/statya/kolichestvo_dolgostroev_uvelichilos_v_vosemnadtsati_regionah_rf_za_2021_god/102082 - с IP-адресом хоста, получил, что подключение к сайту не защищено (несмотря на протокол).

При этом вместо статьи отобразилась та же ошибка: 421 Misdirected Request.

3. Изучение веб-страницы, "проблемной" для парсера

Продолжив поиски по теме защиты на сайтах от ботов, столкнулся с выполнением JavaScript-кода на страницах для этой цели.

Сразу скажу, что в браузере отключил выполнение JavaScript-сценариев, но страница продолжила отображаться нормально.

Хотя при изучении кода проблемной страницы смутил следующий скрипт, включающий в виде JSON-блока контент статьи.

<script>window.__INITIAL_DATA__ = {...,"body":"<h2>В восемнадцати регионах России с начала 2021 года увеличилось число проблемных объектов, жилье в которых ждут обманутые дольщики. Об этом сообщает ТАСС со ссылкой на Фонд защиты прав граждан — участников долевого строительства.</h2><figure class=\"image\"><img src=\"https://st04.domofond.ru/image/1/1.8e4sara2-QaYKU3NkRHj4GaUXwecy78XUsJf.n2qDfSv5Xan97G3s9xyoTicCp2winXLLHxcVGotZqQg\" srcset=\"https://st29.domofond.ru/image/1/1.UJZ1xba2WH7Bxv-hwvxU-1U7_n_FZF58H2f-.mAwXzCu3zagIajLE0KwxA4pTSi_Rcg215CdmhiCxQdo 80w, https://st04.domofond.ru/image/1/1.8e4sara2-QaYKU3NkRHj4GaUXwecy78XUsJf.n2qDfSv5Xan97G3s9xyoTicCp2winXLLHxcVGotZqQg 1200w\" sizes=\"100vw\" width=\"1200\"><figcaption>markus thoenen/Fotolia</figcaption></figure><p>&nbsp;</p><p>В частности, новые долгострои находятся в Ленинградской области — 33 объекта, Ивановской области&nbsp;— 9 объектов, Красноярском крае — 9 объектов, Ульяновской области — 8 объектов. По данным фонда, общее число новых проблемных домов составило 90 объектов.</p><p>Однако за тот же период в 39 субъектах РФ количество долгостроев сократилось на 368 домов. В число данных регионов вошли Московская, Ростовская, Липецкая области, Башкирия, Краснодарский край и другие.</p><p>Добавим, что в настоящее время в стране зафиксировано 2,6 тыс. проблемных объектов, которые находятся в 72 регионах России.</p><p><strong>Не пропустите:</strong></p><p><a href=\"https://www.domofond.ru/statya/fond_dolschikov_zaymetsya_tolko_vyplatoy_denezhnyh_kompensatsiy/101990\" target=\"_blank\"><strong>Фонд дольщиков займется только выплатой денежных компенсаций</strong></a></p><p><a href=\"https://www.domofond.ru/statya/pri_perenose_sdachi_doma_dengi_s_eskrou_schetov_ne_budut_vozvraschatsya_dolschikam/102037\" target=\"_blank\"><strong>При переносе сдачи дома деньги с эскроу-счетов не будут возвращаться дольщикам</strong></a></p><p><a href=\"https://www.domofond.ru/statya/mozhno_li_vzyskat_neustoyku_s_zastroyschika_za_zaderzhku_sdachi_kvartiry/100823\" target=\"_blank\"><strong>Можно ли взыскать неустойку с застройщика за задержку сдачи квартиры?</strong></a></p><p><a href=\"https://www.domofond.ru/statya/kak_vzyskat_kompensatsiyu_s_zastroyschika_zaderzhavshego_sdachu_doma/6766\" target=\"_blank\"><strong>Как взыскать компенсацию с застройщика, задержавшего сдачу дома?</strong></a></p>","author":{"id":144,"name":"Анна Филонова","profile":"<p><strong>Редактор Domofond.ru</strong></p>"},...}
</script>

4. ПО для сбора контента с веб-сайтов

В ходе исследований попадались статьи на "безголовые" браузеры, среды наподобие селениума и т.п.

Предлагалась имитация действий пользователя, установка тайм-аутов при обращении к сайту для снижения нагрузки и т.д.

Но для решения задач по парсингу одной-двух ссылок, а не многопоточного скачивания всего сайта это не подходило.

Глубоко в этом направлении не разбирался и не копал.

5. Возврат к мысли про ссылку с IP-адресом сервера

Пришлось вернуться к начальному вопросу: как получить контент веб-страницы, если по ссылке с именем хоста не получилось.

Решил, в качестве эксперимента, скормить парсеру ссылку https://146.158.48.9/statya/kolichestvo_dolgostroev_uvelichilos_v_vosemnadtsati_regionah_rf_za_2021_god/102082 - с IP-адресом хоста.

В ответ получил содержимое страницы.

6. Выводы и решение

В чем проблема - до конца непонятно. Закроет ли собственник сайта (Домофонд) эту дыру и сможет ли это вообще сделать - неясно.

Но в статье приведено достаточно простое решение и оно работает, а на просторах интернета с такой легкой подсказкой я не сталкивался.

В решении дополнил скрипт методом gethostbyname, чтобы получать IPv4-адрес, соответствующий переданному имени хоста.

Парсер для получения контента по ссылке на входе имеет тот же набор URL-ссылок, но теперь обращается по IP-адресам серверов, что не мешает его работе в сборе данных.

Теги:
Хабы:
-19
Комментарии32

Публикации

Изменить настройки темы

Истории

Работа

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн