Есть сайт, к которому пробую подключиться на питоне через Requests.
На сайте есть очень серьезная защита от загрузки страниц с помощью внешних программ и без длинного описания здесь не обойтись.
Если на сайт заходит человек, используя браузер, то никаких проблем не возникает. В этом случае сайт открывается без каких-либо видимых нюансов.
Но
если подключиться к этому сайту с помощью Requests, то даже "правильную" главную страницу невозможно получить.
Вместо нормальной главной страницы возвращается служебная страница, содержащая встроенные javascript'ы, прописанные таким образом, что крайне трудно понять, что именно они делают и как их обойти, а также в служебной странице сохранен RSA ключ шифрования для каких-то хитрых манипуляций.
HTML код служебной страницы выложил на Codepen. (В двух местах там IP и временную метку заменил).
https://codepen.io/atoster/pen/ExQwONd?editors=1000
Теперь детали, - как я понимаю отдельные важные моменты и что примерно происходит.
В заглавной части служебной страницы загружаются два внешних javascript.
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jsrsasign/8.0.20/jsrsasign-all-min.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.js"></script>
Первый из скриптов нужен для какого-то шифрования или дешифрирования. Второй - составляет уникальный Fingerprint браузера.
Когда пользователь открывает страницу, автоматически загружаются скрипты, которые вычисляют уникальный отпечаток (Fingerprint) браузера, задаются куки spsn (числовой, на основании какой-то unix-временной метки), "spid" и "spsc". Последние две задаются с помощью шифрования и дешифрирования какой-то информации, вероятно, отпечатка.
Дальше управление передается функции "get_location()", которая делает переадресацию, подставляя в url адрес разные рассчитанные хеши, IP итп. Переадресация идет на какой-то служебный адрес, начинающийся с "/xpvnsulc/". В результате после проверки у обычного живого пользователя сайт либо автоматически открывается, либо отображается промежуточная страница с уведомлением о большой нагрузке на сервер и просьбе ввести символы с каптчи (картинки).
После ввода символов такая же просьба может повториться еще один или несколько раз. Дальше происходит переход на сайт. Сама функция на служебной странице, которая делает все эти манипуляции, путает в алгоритме следы, называния переменных итп - все сделано для того, чтобы невозможно было понять алгоритм. ... А "/xpvnsulc/" - если набрать в поисковике, то находятся 10-20 результатов. Т.е. такая проверка каптчи и на других сайтах встречается, но не часто.
Надо заметить, что увидеть промежуточную служебную страницу в браузере тоже непросто. Джаваскипты при загрузке страницы запускаются и делают все очень быстро, - в панели веб-разработчика её не видно. В браузере в режиме веб-разработчика на вкладке Network видна уже итоговая html страница с полезной информацией, в html коде которой ничего из вышеописанного нет.
Чтобы увидеть эту "служебную страницу", я через hosts файл запретил доступ к двум внешним джаваскриптам. Если они не стартуют, то тогда служебная страница видна - кроме нее ничего не загружается.
127.0.0.1 cdnjs.cloudflare.com
127.0.0.1 cdn.jsdelivr.net
Второй способ увидеть промежуточную служебную страницу - обратиться к любой странице сайта через питон-скрипт, через Requests итп. Вместо правильного контента в ответе response выведется описанная выше служебная страница.
Отсюда возникают сложности.
Подключиться к сайту и прочитать полезный контент через Requests не получается. Я
пробовал имитировать куки-файлы, поля referer, host, origin - не помогает.
Единственное, что получилось сделать - это подключиться к сайту и получить "правильный" контент через библиотеку Selenium. Selenium открывает страницу в реальном браузере. При заходе на сайт через Selenium автоматически запускаются все скрипты. Поскольку от человека поведение не отличается (почти), защита не срабатывает и контент доступен.
Но Selenium очень медленный и не все умеет, что требуется. Мне нужно подключиться через Python Requests или что-то похожее.
В поисках решения я использовал библиотеку Requestium (
для ее работы нужна версия Selenium ниже 4.0).
Requestium при подключении позволяет создать сессию и одновременно управлять ей, как с помощью Selenium, так и с помощью аналога Requests.
С помощью Requestium я запускаю Selenium и открываю главную страницу сайта - все проверки сайта проходят и защита не блокирует доступ.
На этом этапе в драйвере Selenium (в управляемом им браузере) сформированы все куки и все, что нужно для просмотра любых страниц сайта.
Далее я использую функцию Requestium - session.transfer_driver_cookies_to_session(), которая все куки из браузера автоматически копирует в куки сессии Requests.
Дополнительно я также копирую из браузера в сессию requests название user-agent - session.copy_user_agent_from_driver().
Перед этим я заранее приготовил заголовки headers, в которых прописан referrer, host и origin.
Прежде чем делать запрос, я проверяю, что в сессию Requests действительно скопировались все нужные куки из браузера - print (session.cookies).
Дальше я пытаюсь получить страницу через ~requests (requestium):
r = session.post(url, data=payload, headers=headers)
Но сколько бы я не пробовал сымитировать браузер с помощью ~Requests, нормальный контент не отдается, а всегда возвращается хоть и с кодом 200, но служебная страница "защиты".
В примере выше указан пример с POST запросом, поскольку конечная цель обращения к сайту через POST. Но я пробовал и с GET запросами, на любые страницы, включая главную - результат одинаковый. Поэтому я думаю, что если получить доступ к главной странице, то к остальным страницам алгоритм подключения будет аналогичный.
К другим сайтам я много раз подключался через Requests и не сталкивался с нерешаемыми препятствиями. А здесь никак не получается разгадать механизм защиты.
Я уже голову сломал, что именно может блокировать доступ к сайту питоновским скриптам и на чем основана проверка. Прошу помочь с идеями.
P.S. Адрес сайта указан в коде в функции get_location(). Результат планировалось использовать локально и исключительно в благих целях, - для выгрузки данных по отдельному населенному пункту для поиска родственников и "забытых" земляков-героев.