Я пытаюсь отправить GET-запросы на https://apartments.com. Однако запрос просто истекает по тайм-ауту или зависает навсегда. Страница прекрасно загружается в браузере, поэтому веб-сервер не просто отключается.
Я веб-разработчик, поэтому в прошлом я много работал с модулем requests
, а также со своими собственными веб-серверами, и я понимал, что, если сервер не работает, он всегда должен что-то возвращать. Если мне просто не хватает определенного заголовка или файла cookie, я ожидаю как минимум ошибки 403.
Другие веб-сайты работают нормально, и я сталкиваюсь с этой проблемой на разных компьютерах в разных сетях, поэтому проблема, вероятно, не в моем брандмауэре, соединении или чем-то еще. Ошибка возникает как с Python, так и с Curl. Как я могу это исправить?
Мой код Python выглядит следующим образом:
import requests
url = "https://www.apartments.com/" # Any path on this domain has this issue.
url = "https://www.apartments.com/"
escaped_time_string = datetime.datetime.now().strftime("%a+%b+%d+%Y+%H___%M___%S+GMT-0600+(Mountain+Daylight+Time)").replace("___", "%3A")
print(escaped_time_string)
headers = { # These are the headers that were sent by the browser when I visited the website. I have tried other values for User-Agent, but nothing changes.
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0",
"Host": "www.apartments.com",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Connection": "keep-alive",
"Cookie": f"cb=1; cul=en-US; ab=%7b%22e%22%3atrue%2c%22r%22%3a%5b%5d%7d; afe=%7b%22e%22%3afalse%7d; fso=%7b%22e%22%3afalse%7d; sr=%7B%22Width%22%3A2560%2C%22Height%22%3A1279%2C%22PixelRatio%22%3A1%7D; _ga=GA1.2.1587172952.1719086370; _gid=GA1.2.2141307871.1719086370; OptanonConsent=isGpcEnabled=0&datestamp = {escaped_time_string}&version=202401.2.0&browserGpcFlag=0&isIABGlobal=false&hosts=&consentId=7bc5ce4e-ac96-493a-bcbb-c4a1f2084786&interactionCount=1&landingPath=NotLandingPage&groups=C0001%3A1%2CC0003%3A1%2CC0002%3A1%2CC0004%3A1&AwaitingReconsent=false; gip=%7b%22Display%22%3a%22Orem%2c+UT%22%2c%22GeographyType%22%3a2%2c%22Address%22%3a%7b%22City%22%3a%22Orem%22%2c%22CountryCode%22%3a%22US%22%2c%22State%22%3a%22UT%22%7d%2c%22Location%22%3a%7b%22Latitude%22%3a40.3142%2c%22Longitude%22%3a-111.7099%7d%2c%22IsPmcSearchByCityState%22%3afalse%7d; akaalb_www_apartments_com_main=1719122615~op=apartments_Prd_Edge_US:www_apartments_com_LAX|~rv=77~m=www_apartments_com_LAX:0|~os=0847b47fe1c72dfaedb786f1e8b4b630~id=6fe4004a168575354c8284d8b9dcdec9; ak_bmsc=58307435F65C23FE0EBD31E15CF76945~000000000000000000000000000000~YAAQRqfLF+IFxjaQAQAApWx6Qxji3KakC+xNTdsIM+85gJPMwEo498Se+B3+ugjIZV6wiX2p63okc8LKIQYXV3UJjNcRZe05q8LM3FXGCivYqWKHk1795v1Ismu17ai6hO2NRmiHUnW7LM9WHwZsYyJFqGGeRfs9K2JX3abwcljSCXK55n2XBmdryImrz93faWCWIJqy3fCyQGGJoh8iScFiiegqL4zJg14yojxdLOBSJsVXPBnH0F2uLcs5rNpkgGZ/88uFKf66BOU340ir2Yr9QNi3CV5+90STD0hHITUhbIoG7l5Oc7991FZYZFUrj1IWT9vxnwyJOk76yYqdkN5oRuT3GO1WsPZDXp/7sh6e9gSDsAcQRdhIO3eLP4p6A5fkzc5hqogez5F01U4=; _gat=1; bm_sv=F96ACBC1FDF433C48190DCBABDE1376B~YAAQRqfLFx0GxjaQAQAAdm96QxjvIM6idZiwJvdJ3swWH5GcroUfVp9H3HRvvKzoNhUaYrtPnpUOjnfNVrLvVCN+PZNmaO/efw9Id7eOmJ9nDqVBI7g4q1+S4Y7YYd9mmE1wXAy6fgIEBW4I0aD2vfMXXs768jB4P2D26X94iUlSYjZyWSDqVP3p2oBHV+/TUUwU91FAJMXON8j+hMPXaWF74ogpw4kEWWKme2ireco1yRfqVEeRxXShohFdbhheFWgbwg==~1",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Priority": "u=1",
"TE": "trailers"
}
req = requests.get(url, timeout=10, allow_redirects=True, headers=headers)
req = None
try:
req = requests.get(url, timeout=10, allow_redirects=True)
except requests.exceptions.Timeout:
print("Timed out")
if req:
print(req.text)
Эта команда curl дает те же результаты:
curl https://apartments.com
Большинство заголовков остаются постоянными каждый раз, когда мой браузер обращается к странице, но в заголовке cookie есть части, которые каждый раз меняются. Один из них включает текущее время, что легко исправить. Но он также включает значения для bm_sv и bm_mi. У меня нет большого опыта работы с файлами cookie, но, похоже, они содержат данные о местоположении, поэтому проблема может быть в них.
Пробовали ли вы предоставить собственные заголовки запросов, например пользовательский агент? Большинство серверов обычно очень заботятся о подобных вещах.
иногда может помочь использование даже поддельного User-Agent: Mozilla/5.0
, но иногда требуется полный User-Agent
из реального веб-браузера. Конечно, страница может проверять и другие заголовки. особенно файлы cookie (идентификатор сеанса). Но сначала вам нужно проверить, может ли страница работать, когда вы отключите JavaScript в браузере. Если ему нужен JavaScript, то requests
и BS
могут быть бесполезны, потому что они не могут запускать JavaScript, и ему может потребоваться Selenium для управления реальным веб-браузером, который может запускать JavaScript.
@JohnGordon Я не увидел в robots.txt ничего, что могло бы сделать это не так. И я попробовал несколько заголовков пользовательского агента, но ничего не изменилось. Я отредактирую вопрос, чтобы сделать это более понятным.
если вы использовали какие-то заголовки, покажите их в коде, чтобы мы тоже могли их протестировать. Вы должны показать все детали, о которых идет речь, потому что мы не видим ваш компьютер и не можем читать ваши мысли.
Я пробовал разные варианты, но, поскольку это не имело никакого значения, я удалил их, чтобы сделать код менее загроможденным. Я не могу редактировать сообщение прямо сейчас (говорит просмотреть предложенное изменение, но на самом деле нет предлагаемых изменений для просмотра), но позже, если смогу, я добавлю эту информацию.
если эта проблема существует на других компьютерах, возможно, она блокирует некоторый диапазон IP-адресов или все соединения из вашей страны.
Я попытался скопировать точные заголовки, которые отправляет мой браузер, и в заголовке файла cookie есть части, которые каждый раз меняются. Один из них включает текущее время, что легко исправить. Но он также включает значения для bm_sv
и bm_mi
. У меня нет большого опыта работы с файлами cookie, но, похоже, они содержат данные о местоположении, поэтому проблема может быть в них.
Иногда порталы проверяют заголовок User-Agent
, чтобы убедиться, что это веб-браузер,
или отправлять разный контент для разных браузеров или разных устройств (компьютер, стол, телефон).
Некоторые отправляют что-то, даже если программа отправляет неправильно User-Agent
, но некоторые страницы блокируют доступ.
requests
отправляет что-то вроде python/requests ...
как User-Agent
Иногда может помочь даже фейк Mozilla/5.0
, но этой странице нужна была ценность настоящего веб-браузера. Если вы посетите страницу http://httpbin.org/get, вы увидите, что ваш браузер отправляет на сервер, и сможете это использовать.
я использовал
headers = {
#'User-Agent': 'Mozilla/5.0',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0',
}
req = requests.get(url, timeout=10, allow_redirects=True, headers=headers)
и это дает мне некоторые данные.
Но я не проверял, полезен ли это HTML, JavaScript или Captcha.
Если вы уже протестировали User-Agent
и по-прежнему не можете получить доступ к коду, возможно, сервер запомнил вас (используя другие данные), и ему может потребоваться использовать более сложную систему - например. прокси для смены IP.
ИЛИ, возможно, потребуется использовать всю информацию, которую вы найдете в реальном веб-браузере (в заголовках).
ИЛИ, возможно, потребуется использовать Selenium с настоящим веб-браузером.
Спасибо за ответ. Я попробовал заголовок пользовательского агента, как я сказал в исходном вопросе (но определенно мог бы сделать это более понятным), но это не сработало. Для меня это тоже ничего не меняет.
ну, вы сказали, что использовали разные заголовки, но не показали, какие значения вы использовали. Для меня это не работает Mozilla/5.0
, но работает Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0
- поэтому для этой страницы важна полнота. Но, как я сказал в последней строке, вы можете сделать так много неправильных подключений, что веб-страница поместит вас в черный список и не сможет подключиться, даже если вы используете правильный User-Agent. И для этого может потребоваться использовать прокси для смены IP. ИЛИ, возможно, потребуется использовать всю информацию, которую вы найдете в реальном веб-браузере (в заголовках). ИЛИ, возможно, потребуется использовать Selenium
с реальным веб-браузером.
Я использовал различные заголовки. Я только что попробовал это в сети, которую еще не использовал (поэтому новый IP-адрес), и это тоже не сработало.
У меня код работает с полным пользовательским агентом, поэтому я не могу воспроизвести вашу проблему, поэтому я не могу вам больше помочь. Кажется, у вас более серьезная проблема (которую мы не можем воспроизвести, поэтому не можем сказать, в чем может быть проблема)
единственная идея - попробовать Selenium, потому что на сервере может быть более сложная система, которая может блокировать разные соединения в разных ситуациях. Возможно, он использует некий искусственный интеллект, который решает, кого заблокировать.
Селен вроде работает. Я надеялся, что смогу разместить это и запускать автоматически раз в день, но похоже, что это не вариант. Спасибо вам за помощь!
почему? вы все равно можете запустить его автоматически с помощью Selenium — он может работать с опцией --headless
, поэтому он может работать на сервере без графического интерфейса. ИЛИ, если сервер использует Linux, он может использовать xvfb - поддельный графический интерфейс. В Python есть даже модуль xvfbwrapper
для активации этого поддельного графического интерфейса. Как мне запустить Selenium в Xvfb?
я использую вариант без головы, но для него все равно требуется установленный браузер, не так ли? я не уверен, что какой-либо удаленный провайдер предоставит такую возможность
да headless
еще нужно установить браузер. Если удаленный сервер предоставляет доступ ssh
, то обычно он позволяет устанавливать собственные программы в свою папку. Это позволяет загрузить собственный файл/программу и запустить ее без установки.
Итак, я смог воспроизвести проблему, с которой вы столкнулись. Вот несколько советов, которые вы можете попробовать, чтобы очистить сайт. Сначала вам нужно обязательно поиграть с заголовками, предыдущие ответы были на правильном пути.
У меня нет возможности доказать свою теорию, но я твердо верю, что на сайте apartment.com есть черные списки конкретных заголовков. Если вы выполняете одноразовую очистку, зайдите в заголовки и скопируйте заголовки из вашего Internet Explorer. Я предоставлю скриншоты, как это сделать.
Скопируйте и вставьте все, что получите, затем найдите значение пользовательского агента и скопируйте его в свой код.
import requests
s = requests.Session()
url = "https://www.apartments.com/" # any path on this domain has this issue
# headers = {'Accept': '*/*', 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36', 'Accept-Language': 'en-US;q=0.5,en;q=0.3', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1'}
headers = {
"Accept": "*/*",
"Host": "www.apartments.com",
# "User-Agent": "com.apple.WebKit.Networking/19618.2.12.11.6 CFNetwork/1496.0.7 Darwin/23.5.0",
'User-Agent': "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Mobile Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive"
}
req = s.get(url, headers=headers) # tried a variety of headers to pretend it's a browser, nothing changes
print(req.text)
Если вы пытаетесь автоматизировать очистку, я советую вам получить более обновленный список заголовков, которые нельзя заблокировать на сайте apartment.com, и использовать прокси. На таком популярном сайте будет целая команда разработчиков, пытающихся найти новые способы предотвращения парсинга их сайта.
Мне удалось получить от него некоторый контент, и время ожидания кода не истекло. Короче говоря, найдите более обновленные заголовки, а не общие, которые вы получаете из такой библиотеки, как fake_useragent.
Пожалуйста, убедитесь, что вы просматриваете сайт robots.txt на сайте apartment.com, чтобы выполнить парсинг в соответствии с их политикой. У них есть API, который вы можете использовать для получения контента с их сайта. Надеюсь это поможет!
Судя по всему, сайт решил, что вы робот (а вы им и являетесь), и решил не отвечать.