#python #python-3.x #web-scraping #python-requests
#python #python-3.x #очистка веб-страниц #python-запросы
Вопрос:
Я пытаюсь войти на этот сайт с помощью модуля запросов, но я получаю 403
код состояния каждый раз, когда пытаюсь выполнить следующую попытку. Хотя я пытался имитировать способ отправки запросов с помощью инструментов мониторинга разработчиков, я не могу заставить это работать. Учетные данные (имя пользователя: simpndev@gmail.com
, пароль: agb5E2?w2pQJ3z
), которые я использовал здесь, предназначены только для тестирования, поэтому вы можете свободно ими пользоваться.
Чтобы получить форму, все, что вам нужно сделать, это нажать на login
кнопку, а затем на Fantasy
button.
Я пытался с:
import re
import requests
link = 'https://www.fanduel.com/contests'
url = 'https://api.fanduel.com/sessions'
payload = {"email":"simpndev@gmail.com","password":" agb5E2?w2pQJ3z","product":"DFS"}
def log_in(s):
r = s.get(link)
client_id = re.findall(r"clientId":"(.*?)",",r.text)[0]
s.headers['authorization'] = f'Basic {client_id}'
s.headers['Referer'] = 'https://www.fanduel.com/login'
s.headers['accept'] = 'application/json'
r = s.post(url,json=payload)
print(r.status_code)
if __name__ == '__main__':
with requests.Session() as s:
s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'
log_in(s)
Я добился успеха, используя selenium, поэтому я не хочу идти этим путем.
Как я могу войти на этот сайт с помощью запросов?
Ответ №1:
В этом запросе содержится 2 потенциальных ошибки 403. 403 из bot protection в link = 'https://www.fanduel.com/contests'
и 403 из запроса в / sessions/
403 от link
использует некоторые расширенные функции браузеров для проверки повторных попыток входа. Это будет более сложная тема, включающая сравнение строк пользовательского агента с трафиком HTTP2, преодоление капчи с помощью ML и так далее. Мой совет — не идти по этому пути.
Вместо этого уменьшите версию строки вашего пользовательского агента и убедитесь, что вы предоставляете правильные заголовки. Вы не предоставляете правильные заголовки для первоначального запроса, и поэтому вы генерируете 403s, а затем вы попадаете в черный список ботов и пытаетесь управлять этим.
У меня работает следующее, как показано на скриншоте отладчика ниже:
import re
import requests
link = 'https://www.fanduel.com/contests'
url = 'https://api.fanduel.com/sessions'
payload = {"email":"simpndev@gmail.com","password":" agb5E2?w2pQJ3z","product":"DFS"}
def log_in(s):
r = s.get(link)
client_id = re.findall(r"clientId":"(.*?)",",r.text)[0]
s.headers['Authorization'] = f'Basic {client_id}'
s.headers['Referer'] = 'https://www.fanduel.com/login?cc_success_url=/contests'
s.headers['Accept'] = 'application/json'
s.headers['Accept-Encoding'] = 'gzip, deflate, br'
s.headers['Accept-Language'] = 'en-US,en;q=0.5'
s.headers['Origin'] = "https://www.fanduel.com"
r = s.post(url,json=payload)
print(r.status_code)
if __name__ == '__main__':
with requests.Session() as s:
s.headers['User-Agent'] = 'Mozilla/5.0 (en-us) AppleWebKit/534.14 (KHTML, like Gecko; Google Wireless Transcoder) Chrome/9.0.597 Safari/534.14 wimb_monitor.py/1.0'
log_in(s)
Обратите внимание, что я изменил ваш реферер, изменил заглавные буквы в ваших заголовочных ключах и предоставил то, что может показаться лишними заголовками. При проверке r.request.headers я увидел различия между теми, которые отправляются запросами, и, например, Firefox, поэтому я просто добавил все, что отличалось.
Также обратите внимание, что ваш токен на предъявителя и учетные данные учетной записи теперь широко распространены и могут привести к дополнительным 403 секундам, если вы все еще используете их для тестирования. Вам понадобится чистая учетная запись, поскольку многие люди могут иметь эти учетные записи сейчас.
Комментарии:
1. Я использовал инструменты разработчика Chrome для сбора и использования заголовков в моем первоначальном скрипте. Я перепроверил, не использовал ли я ошибочно маленькую букву в ключах заголовка, но заметил, что я не ошибся. Ваш код работает без ошибок. У меня вопрос по этому поводу: как вы выяснили, что ключи заголовка должны использоваться печатными буквами и каким может быть точный пользовательский агент? Огромное спасибо.
2. Я выбрал user-agent случайным образом из списка старых пользовательских агентов (погуглил). Я использовал Firefox для пар ключ заголовка-> значение. Возможно, все, что было необходимо, это исправление значения Referer (обратите внимание, что я добавил фрагмент строки запроса), но я просто добавил все одновременно.
Ответ №2:
Был там, в прошлом было много проблем с использованием Selenium для очистки веб-страниц.
Одна из альтернатив, которая мне больше нравится, — это использование mitmproxy для сброса скрипта навигации в файл и воспроизведения его с помощью requests
, что-то вроде этого:
import mitmproxy.io
import requests
def main():
sess = requests.Session()
with open('flows', 'rb') as f: data = [row for row in mitmproxy.io.FlowReader(f).stream()]
for d in data:
url = d.request.url
raw_content = d.request.raw_content
headers = dict([(k, v,) for k, v in d.request.headers.items() if not k.startswith(':') and k.lower() != 'cookie'])
print(url, raw_content, headers)
if d.request.method == 'GET':
r = sess.get(url, headers=headers, data=raw_content)
if d.request.method == 'POST':
r = sess.post(url, headers=headers, data=raw_content)
print(r.status_code)
if d.request.url == 'https://api.fanduel.com/sessions':
break
if __name__ == '__main__':
main()
Приведенный выше код (с использованием моего собственного потока, выгруженного из mitmproxy) приводит к выводам ниже:
http://www.fanduel.com/ b'' {'Host': 'www.fanduel.com', 'Upgrade-Insecure-Requests': '1', 'Accept': 'text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Mobile/15E148 Safari/604.1', 'Accept-Language': 'en-gb', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive'}
200
https://www.fanduel.com/ b'' {'accept': 'text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8', 'upgrade-insecure-requests': '1', 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Mobile/15E148 Safari/604.1', 'accept-language': 'en-gb', 'accept-encoding': 'gzip, deflate'}
200
https://www.fanduel.com/JMCVuBG8/init.js b'' {'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Mobile/15E148 Safari/604.1', 'accept-language': 'en-gb', 'referer': 'https://www.fanduel.com/'}
200
https://www.fanduel.com/login?source=Header Login b'' {'accept': 'text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8', 'accept-encoding': 'gzip, deflate, br', 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Mobile/15E148 Safari/604.1', 'accept-language': 'en-gb', 'referer': 'https://www.fanduel.com/'}
200
https://api.fanduel.com/sessions b'{"email":"simpndev@gmail.com","password":" agb5E2?w2pQJ3z","product":"DFS"}' {'accept': 'application/json', 'origin': 'https://www.fanduel.com', 'content-type': 'application/json', 'authorization': 'Basic ZWFmNzdmMTI3ZWEwMDNkNGUyNzVhM2VkMDdkNmY1Mjc6', 'referer': 'https://www.fanduel.com/login', 'content-length': '75', 'accept-language': 'en-gb', 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Mobile/15E148 Safari/604.1', 'accept-encoding': 'gzip, deflate, br'}
201
Все, что вам понадобится, это устройство с установленным прокси для прохождения через вашу собственную установку mitmproxy (обычно я использую свой телефон для маршрутизации запросов с помощью моего ПК и SOCKS5). Если что-то изменится в навигации по веб-сайту, все, что вам нужно будет сделать, это создать новый поток и дамп скрипта для загрузки в программу Python.
Это не решит более сложных реализаций безопасности javascript, но должно быть достаточно для простых, таких как этот веб-сайт.