Объект Session в библиотеке requests: поддержка куки и заголовков
Библиотека requests предоставляет класс Session, который позволяет сохранять определённые параметры между несколькими запросами. Это избавляет от необходимости передавать куки, заголовки или параметры аутентификации в каждом запросе вручную.
Создание сессии и сохранение куки с заголовками
Типичная задача - поддерживать авторизацию на сайте, которая передаётся через cookie. Сессия автоматически запоминает все куки, полученные от сервера, и отправляет их в последующих запросах. Также заголовки можно установить один раз через атрибут session.headers.
import requests
# Создание объекта сессии
session = requests.Session()
# Установка общего заголовка (например, User-Agent)
session.headers.update({
'User-Agent': 'Mozilla/5.0 (compatible; MyApp/1.0)'
})
# Первый запрос - обычно вход на сайт
login_data = {'username': 'user', 'password': 'pass'}
login_response = session.post('https://httpbin.org/post', data=login_data)
# Куки, установленные сервером, сохранятся в session.cookies
# Второй запрос - сессия автоматически подставит куки
profile_response = session.get('https://httpbin.org/cookies')
print(profile_response.text)Python requests get (get-запрос через requests в python)
Код не требует явного манипулирования куками - всё происходит автоматически. В ответе на второй запрос будут видны сохранённые куки.
Типичная ошибка:
Забыть обновлять заголовки при смене окружения. Например, если сессия создаётся один раз в модуле, а потом её случайно перезаписывают новым объектом Session - заголовки теряются. Решение: проверять, что используется один и тот же объект, или применять фабрику сессий.
Как передать куки вручную, не создавая сессию?
Иногда требуется отправить один запрос с определёнными куками без сохранения состояния. В requests это делается через параметр cookies.
import requests
# Словарь с куками
custom_cookies = {'session_id': 'abc123'}
response = requests.get('https://httpbin.org/cookies', cookies=custom_cookies)
print(response.text) # сервер увидит session_idGet html python (получение html-содержимого через http в python)
Параметр cookies принимает словарь или объект RequestsCookieJar. Этот способ не подходит, если нужно выполнить несколько последовательных запросов - куки не сохраняются автоматически.
Проблема:
Если сервер устанавливает новые куки в ответе, они не запоминаются для следующего запроса. Для многошаговых сценариев лучше использовать Session.
Как задать заголовки для одного запроса без влияния на сессию?
Сессия позволяет установить базовые заголовки, но иногда нужно переопределить их для конкретного запроса. Для этого используется параметр headers в вызове метода.
import requests
session = requests.Session()
session.headers.update({'Accept-Language': 'en-US'})
# Переопределяем Accept-Language только для этого запроса
response = session.get('https://httpbin.org/headers', headers={'Accept-Language': 'fr-FR'})
print(response.json()['headers']['Accept-Language']) # 'fr-FR'
Url запрос python (работа с url в python)
Обратите внимание: заголовки из параметра headers сливаются с заголовками сессии. Но если в параметре указан тот же ключ, что и в сессии, параметр имеет приоритет.
Типичная ошибка:
Полная замена всех заголовков из-за неправильного понимания - на самом деле выполняется объединение, а не замена. Если нужно полностью исключить заголовки сессии, следует создать временный объект сессии без заголовков.
Как сохранить куки между перезапусками программы?
Объект Session хранит куки только во время выполнения. Чтобы сохранить их между разными запусками, нужно сериализовать session.cookies в файл.
import requests
import pickle
# Сохранение
session = requests.Session()
session.get('https://httpbin.org/cookies/set?name=value') # получаем куки
with open('cookies.pkl', 'wb') as f:
pickle.dump(session.cookies, f)
# Загрузка
with open('cookies.pkl', 'rb') as f:
loaded_cookies = pickle.load(f)
new_session = requests.Session()
new_session.cookies.update(loaded_cookies)
response = new_session.get('https://httpbin.org/cookies')
print(response.text) # куки восстановленыPython urllib request (отправка запросов с помощью urllib.request в python)
Это полезно для долгоживущих сессий (например, парсинг с авторизацией), чтобы не логиниться при каждом запуске. Однако срок действия кук может истечь, поэтому нужна обработка ошибок.
Проблема:
Куки могут быть невалидными (истекли или заблокированы). Лучше дополнительно проверять статус ответа после загрузки и при необходимости повторно аутентифицироваться.
Как настроить базовую HTTP-аутентификацию через сессию?
Сессия может хранить объект аутентификации и передавать его во все запросы.
import requests
from requests.auth import HTTPBasicAuth
session = requests.Session()
session.auth = HTTPBasicAuth('user', 'pass')
# Запрос автоматически получит заголовок Authorization
response = session.get('https://httpbin.org/basic-auth/user/pass')
print(response.status_code) # 200
# Можно также установить auth как кортеж
session.auth = ('user2', 'pass2')Files upload python (загрузка файлов на сервер с помощью python (requests, flask))
Это удобно для REST API, где требуется аутентификация для каждого вызова.
Ошибка:
Если для разных хостов требуется разная аутентификация, одна сессия не подойдёт - нужно создавать отдельные сессии или временно переопределять auth в параметрах запроса.
Как управлять редиректами в сессии?
По умолчанию requests автоматически следует редиректам (код 3xx). Сессия сохраняет куки, которые могут меняться при перенаправлениях. Иногда требуется отключить редиректы или получить их историю.
import requests
session = requests.Session()
# Отключить автоматическое следование
response = session.get('https://httpbin.org/redirect/3', allow_redirects=False)
print(response.status_code) # 302
print(response.headers['Location']) # путь для ручного перехода
# Получить историю редиректов
response2 = session.get('https://httpbin.org/redirect/3', allow_redirects=True)
print(len(response2.history)) # 3Python requests method (методы http-запросов в python (get, post, put, delete) с requests)
При отключении редиректов куки с промежуточных ответов не сохраняются. Для полного контроля лучше включить редиректы, а потом анализировать response.history.
Проблема:
Бесконечные редиректы могут привести к зависанию. Следует установить таймаут или лимит на количество редиректов (параметр max_redirects в адаптере транспорта).
Как обрабатывать CSRF-токены при работе с формами?
Многие сайты требуют CSRF-токен, который передаётся в куки и в теле POST-запроса. Сессия упрощает этот сценарий: сначала GET-запрос для получения куки с токеном, затем извлечение токена из HTML, и POST с этим токеном.
import requests
from bs4 import BeautifulSoup
session = requests.Session()
# Получаем страницу с формой
login_page = session.get('https://example.com/login')
soup = BeautifulSoup(login_page.text, 'html.parser')
csrf_token = soup.find('input', {'name': 'csrf_token'}).get('value')
# Отправляем POST с токеном
login_data = {
'username': 'user',
'password': 'pass',
'csrf_token': csrf_token
}
response = session.post('https://example.com/login', data=login_data)
# Куки обновились, сессия готова к дальнейшим запросам
Сессия автоматически отправит куки, в которых обычно содержится вторая часть CSRF-защиты (например, csrftoken в куки).
Типичная ошибка:
Несоответствие между куки-токеном и телом запроса. Многие фреймворки ожидают, что куки с CSRF-токеном будут отправлены вместе с POST. Сессия делает это автоматически, но если токен извлекается неправильно (например, из другого поля), сервер вернёт ошибку 403. Рекомендуется проверять содержимое ответа на наличие сообщения об ошибке.
Сессия - гибкий инструмент, который можно комбинировать с адаптерами, пулом соединений, повторными попытками и таймаутами. Подробные примеры с расширенными возможностями приведены в следующем разделе.