Веб-серверы — это черные ящики. Им разрешено возвращать любой правильный HTTP-ответ на основе вашего запроса, времени суток, фазы луны или любых других критериев, которые они выбирают. Если другой HTTP-клиент постоянно получает другой ответ, попытайтесь выяснить, в чем разница между запросом, который отправляет Python, и запросом, который отправляет другой клиент.
Это означает, что вам необходимо:
- Запишите все аспекты рабочего запроса
- Запишите все аспекты неудачного запроса
- Попробуйте, какие изменения вы можете внести, чтобы сделать неудачный запрос более похожим на рабочий запрос, и минимизировать эти изменения.
Обычно я направляю свои запросы на конечную точку http://httpbin.org, записываю запрос, а затем экспериментирую.
Для requests
есть несколько заголовков, которые устанавливаются автоматически, и многие из них вы обычно не ожидаете изменить:
Host
; это должно быть установлено на имя хоста, с которым вы связываетесь, чтобы он мог правильно размещать разные сайты. requests
устанавливает этот.
Content-Length
и Content-Type
для запросов POST обычно устанавливаются из аргументов, которые вы передаете requests
. Если они не совпадают, измените аргументы, которые вы передаете, на requests
(но будьте осторожны с запросами multipart/*
, которые используют сгенерированную границу, записанную в заголовке Content-Type
; оставьте ее создание requests
).
Connection
: оставить это на усмотрение клиента
Cookies
: они часто устанавливаются при первоначальном запросе GET или после первого входа на сайт. Убедитесь, что вы записываете файлы cookie с помощью объекта requests.Session()
и вошли в систему (предоставили учетные данные так же, как это сделал браузер).
Все остальное — честная игра, но если requests
установил значение по умолчанию, то чаще всего эти значения по умолчанию не являются проблемой. Тем не менее, я обычно начинаю с заголовка User-Agent и продвигаюсь оттуда.
В этом случае сайт фильтрует пользовательский агент, похоже, они заносят Python
в черный список, установка практически любого другого значения уже работает:
>>> requests.get('https://rent.591.com.tw', headers={'User-Agent': 'Custom'})
<Response [200]>
Далее вам нужно принять во внимание, что requests
— это не браузер. requests
— это всего лишь HTTP-клиент, браузер делает гораздо больше. Браузер анализирует HTML на наличие дополнительных ресурсов, таких как изображения, шрифты, стили и сценарии, загружает эти дополнительные ресурсы и выполняет сценарии. Затем сценарии могут изменять то, что отображает браузер, и загружать дополнительные ресурсы. Если ваши requests
результаты не совпадают с тем, что вы видите в браузере, но первоначальный запрос браузера совпадает, вам нужно выяснить, какие другие ресурсы загружены браузером, и сделать дополнительные запросы. с requests
по мере необходимости. Если ничего не помогает, используйте такой проект, как requests-html
, который позволяет запускать URL-адрес через настоящий безголовый браузер Chromium.
Сайт, с которым вы пытаетесь связаться, делает дополнительный запрос AJAX к https://rent.591.com.tw/home/search/rsList?is_new_list=1&type=1&kind=0&searchtype=1®ion=1
, примите это во внимание, если вы пытаетесь извлечь данные с этого сайта.
Далее, хорошо построенные сайты будут использовать передовые методы обеспечения безопасности, такие как токены CSRF, которые требуют, чтобы вы делали запросы в правильном порядке (например, запрос GET для получения формы перед POST обработчику) и обрабатывали файлы cookie или иным образом извлекали дополнительную информацию, которую сервер ожидает передать от одного запроса к другому.
И последнее, но не менее важное: если сайт блокирует скрипты от выполнения запросов, они, вероятно, либо пытаются обеспечить соблюдение условий обслуживания, запрещающих парсинг, либо потому, что у них есть API, который они предпочитают использовать вам. Проверьте любой из них и примите во внимание, что вас могут заблокировать более эффективно, если вы все равно продолжите очищать сайт.
27.11.2017