Home » Введение в Python Requests: руководство по GET-запросам
Введение в Python Requests: руководство по GET-запросам

Введение в Python Requests: руководство по GET-запросам

Если ты работаешь с серверами, то рано или поздно столкнёшься с необходимостью автоматизировать запросы к API, мониторить состояние сервисов или просто «дёргать» данные с веб-ресурсов. Python Requests — это та библиотека, которая превращает HTTP-запросы из кошмара в удовольствие. Она настолько проста и интуитивна, что даже новичок может быстро написать скрипт для проверки доступности сайта или получения данных из REST API.

В этой статье мы разберём GET-запросы — самый распространённый тип HTTP-запросов, с которым ты будешь сталкиваться постоянно. Я покажу, как установить и настроить Requests, разберём практические примеры и кейсы, которые реально пригодятся в ежедневной работе с серверами.

Что такое Python Requests и зачем он нужен

Requests — это HTTP-библиотека для Python, которая делает работу с веб-запросами максимально простой. Вместо того чтобы мучиться с встроенным модулем urllib, который требует кучу бойлерплейта, Requests позволяет делать запросы в одну строку кода.

Основные преимущества:

  • Простой и понятный API
  • Автоматическое декодирование JSON
  • Поддержка сессий и cookies
  • Встроенная поддержка SSL/TLS
  • Гибкая настройка таймаутов и retry
  • Отличная документация

Установка и первый запрос

Установка стандартная через pip:

pip install requests

Первый GET-запрос выглядит элементарно:


import requests

response = requests.get('https://httpbin.org/get')
print(response.text)

Всё! Ты уже отправил HTTP GET-запрос и получил ответ. Для работы с серверами рекомендую сразу развернуть тестовую среду на VPS — так удобнее экспериментировать с реальными запросами.

Анатомия GET-запроса

Давайте разберём, что происходит под капотом:


import requests

# Базовый GET-запрос
response = requests.get('https://api.github.com/users/octocat')

# Информация о запросе
print(f"Статус код: {response.status_code}")
print(f"Заголовки: {response.headers}")
print(f"Время выполнения: {response.elapsed}")
print(f"URL: {response.url}")

# Тело ответа
print(f"Текст: {response.text}")
print(f"JSON: {response.json()}") # Если контент в формате JSON

Requests автоматически определяет кодировку, парсит JSON и даже следует редиректам. Это экономит кучу времени по сравнению с urllib.

Параметры запроса

В реальной жизни GET-запросы часто содержат параметры. Вместо ручного форматирования URL используй параметр params:


# Плохо
url = 'https://api.example.com/search?q=python&page=1&limit=10'

# Хорошо
params = {
'q': 'python',
'page': 1,
'limit': 10
}
response = requests.get('https://api.example.com/search', params=params)
print(response.url) # Requests сам собрал URL

Это особенно полезно при работе с API мониторинга серверов, где нужно передавать множество параметров фильтрации.

Заголовки и аутентификация

Большинство API требует передачи заголовков для аутентификации:


headers = {
'User-Agent': 'MyServerMonitor/1.0',
'Authorization': 'Bearer your_token_here',
'Accept': 'application/json'
}

response = requests.get('https://api.example.com/servers', headers=headers)

Для базовой HTTP-аутентификации есть удобный параметр auth:


from requests.auth import HTTPBasicAuth

response = requests.get(
'https://api.example.com/protected',
auth=HTTPBasicAuth('username', 'password')
)

# Или ещё проще
response = requests.get('https://api.example.com/protected', auth=('username', 'password'))

Обработка ошибок

В продакшене всегда обрабатывай ошибки. Requests предоставляет несколько способов:


import requests
from requests.exceptions import RequestException, Timeout, ConnectionError

try:
response = requests.get('https://api.example.com/data', timeout=5)
response.raise_for_status() # Вызовет исключение для 4xx и 5xx
data = response.json()
except Timeout:
print("Запрос превысил таймаут")
except ConnectionError:
print("Проблемы с подключением")
except requests.exceptions.HTTPError as e:
print(f"HTTP ошибка: {e}")
except RequestException as e:
print(f"Общая ошибка: {e}")

Практические примеры для серверного администрирования

Мониторинг состояния сервисов


import requests
import time

def check_service_health(url, timeout=5):
try:
response = requests.get(url, timeout=timeout)
return {
'status': 'UP' if response.status_code == 200 else 'DOWN',
'status_code': response.status_code,
'response_time': response.elapsed.total_seconds(),
'timestamp': time.time()
}
except requests.exceptions.RequestException as e:
return {
'status': 'DOWN',
'error': str(e),
'timestamp': time.time()
}

# Проверка списка сервисов
services = [
'https://example.com/health',
'https://api.example.com/status',
'https://monitoring.example.com/ping'
]

for service in services:
health = check_service_health(service)
print(f"{service}: {health['status']}")

Работа с API мониторинга


def get_server_metrics(api_url, server_id, api_key):
headers = {'Authorization': f'Bearer {api_key}'}
params = {
'server_id': server_id,
'metrics': 'cpu,memory,disk',
'period': '1h'
}

response = requests.get(f"{api_url}/metrics", headers=headers, params=params)

if response.status_code == 200:
return response.json()
else:
print(f"Ошибка получения метрик: {response.status_code}")
return None

metrics = get_server_metrics('https://api.monitoring.com', 'server-123', 'your-api-key')

Автоматизация проверки SSL-сертификатов


import ssl
import socket
from datetime import datetime

def check_ssl_expiry(domain):
try:
# Проверяем SSL через requests
response = requests.get(f'https://{domain}', timeout=10)

# Получаем информацию о сертификате
context = ssl.create_default_context()
with socket.create_connection((domain, 443)) as sock:
with context.wrap_socket(sock, server_hostname=domain) as ssock:
cert = ssock.getpeercert()

expiry_date = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
days_left = (expiry_date - datetime.now()).days

return {
'domain': domain,
'expiry_date': expiry_date,
'days_left': days_left,
'issuer': cert['issuer'],
'status': 'OK' if days_left > 30 else 'WARNING'
}
except Exception as e:
return {'domain': domain, 'error': str(e)}

domains = ['example.com', 'api.example.com', 'monitoring.example.com']
for domain in domains:
ssl_info = check_ssl_expiry(domain)
print(f"{domain}: {ssl_info}")

Продвинутые возможности

Сессии для оптимизации

Если делаешь много запросов к одному серверу, используй сессии. Они переиспользуют TCP-соединения и сохраняют cookies:


session = requests.Session()
session.headers.update({'User-Agent': 'MyApp/1.0'})

# Все запросы будут использовать одно соединение
response1 = session.get('https://api.example.com/endpoint1')
response2 = session.get('https://api.example.com/endpoint2')
response3 = session.get('https://api.example.com/endpoint3')

session.close()

Retry и адаптеры

Для критически важных запросов настрой автоматические повторы:


from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

def create_resilient_session():
session = requests.Session()

retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
)

adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)

return session

session = create_resilient_session()
response = session.get('https://unstable-api.example.com/data')

Сравнение с альтернативами

Библиотека Простота использования Производительность Функциональность Рекомендация
urllib (встроенный) Низкая Средняя Базовая Только если нельзя устанавливать зависимости
requests Очень высокая Хорошая Отличная Для большинства задач
httpx Высокая Очень высокая Отличная + async Для высоконагруженных приложений
aiohttp Средняя Отличная Async-первая Для асинхронных приложений

Интеграция с другими инструментами

Requests + JSON для работы с API


import json

# Отправка JSON-данных
data = {'server_id': 'web-01', 'action': 'restart'}
response = requests.post('https://api.example.com/servers', json=data)

# Обработка JSON-ответа
if response.headers.get('content-type') == 'application/json':
result = response.json()
print(f"Операция выполнена: {result['status']}")

Requests + BeautifulSoup для парсинга


from bs4 import BeautifulSoup

response = requests.get('https://status.example.com')
soup = BeautifulSoup(response.text, 'html.parser')

# Извлекаем статус сервисов
services = soup.find_all('div', class_='service-status')
for service in services:
name = service.find('h3').text
status = service.find('span', class_='status').text
print(f"{name}: {status}")

Requests + Prometheus для мониторинга


import time
from prometheus_client import Counter, Histogram, start_http_server

# Метрики для мониторинга запросов
REQUEST_COUNT = Counter('http_requests_total', 'Total HTTP requests', ['method', 'endpoint', 'status'])
REQUEST_DURATION = Histogram('http_request_duration_seconds', 'HTTP request duration')

def monitored_request(url, **kwargs):
start_time = time.time()
try:
response = requests.get(url, **kwargs)
REQUEST_COUNT.labels(method='GET', endpoint=url, status=response.status_code).inc()
return response
finally:
REQUEST_DURATION.observe(time.time() - start_time)

# Запуск метрик-сервера
start_http_server(8000)

Автоматизация и скрипты

Requests отлично подходит для автоматизации рутинных задач. Вот пример скрипта для массовой проверки сайтов:


#!/usr/bin/env python3
import requests
import csv
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed

def check_website(url, timeout=10):
try:
response = requests.get(url, timeout=timeout, allow_redirects=True)
return {
'url': url,
'status_code': response.status_code,
'response_time': response.elapsed.total_seconds(),
'final_url': response.url,
'ssl_valid': url.startswith('https://'),
'error': None
}
except requests.exceptions.RequestException as e:
return {
'url': url,
'status_code': None,
'response_time': None,
'final_url': None,
'ssl_valid': False,
'error': str(e)
}

def bulk_check_websites(urls, max_workers=10):
results = []

with ThreadPoolExecutor(max_workers=max_workers) as executor:
future_to_url = {executor.submit(check_website, url): url for url in urls}

for future in as_completed(future_to_url):
result = future.result()
results.append(result)
print(f"Проверен {result['url']}: {result['status_code']}")

return results

# Использование
if __name__ == '__main__':
urls = [
'https://example.com',
'https://google.com',
'https://github.com',
'https://stackoverflow.com'
]

results = bulk_check_websites(urls)

# Сохранение результатов в CSV
with open('website_check_results.csv', 'w', newline='') as csvfile:
fieldnames = ['url', 'status_code', 'response_time', 'final_url', 'ssl_valid', 'error']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(results)

Безопасность и лучшие практики

  • Всегда используй HTTPS для передачи чувствительных данных
  • Настраивай таймауты — по умолчанию Requests может висеть вечно
  • Проверяй SSL-сертификаты — не отключай verify=True без крайней необходимости
  • Используй сессии для множественных запросов
  • Логируй запросы для отладки, но не логируй sensitive данные
  • Ограничивай rate limiting — не забивай чужие API


import logging
import time

# Настройка логирования
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def safe_api_request(url, headers=None, params=None, timeout=30):
"""Безопасный запрос к API с логированием"""
try:
logger.info(f"Отправляем запрос к {url}")

response = requests.get(
url,
headers=headers,
params=params,
timeout=timeout,
verify=True # Всегда проверяем SSL
)

logger.info(f"Получен ответ {response.status_code} за {response.elapsed.total_seconds():.2f}с")
response.raise_for_status()

return response

except requests.exceptions.Timeout:
logger.error(f"Таймаут при запросе к {url}")
raise
except requests.exceptions.SSLError:
logger.error(f"Ошибка SSL при запросе к {url}")
raise
except requests.exceptions.HTTPError as e:
logger.error(f"HTTP ошибка {e.response.status_code} при запросе к {url}")
raise

Интересные факты и нестандартные применения

Несколько интересных способов использования Requests:

Загрузка файлов с прогресс-баром


import requests
from tqdm import tqdm

def download_with_progress(url, filename):
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))

with open(filename, 'wb') as file, tqdm(
desc=filename,
total=total_size,
unit='B',
unit_scale=True,
unit_divisor=1024,
) as pbar:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
file.write(chunk)
pbar.update(len(chunk))

download_with_progress('https://example.com/bigfile.zip', 'bigfile.zip')

Создание простого load balancer checker


import requests
import statistics
from collections import defaultdict

def check_load_balancer(lb_url, num_requests=100):
"""Проверяем, как работает load balancer"""
server_responses = defaultdict(int)
response_times = []

for i in range(num_requests):
try:
response = requests.get(lb_url, timeout=5)
server_id = response.headers.get('Server-ID', 'unknown')
server_responses[server_id] += 1
response_times.append(response.elapsed.total_seconds())
except requests.RequestException as e:
print(f"Ошибка в запросе {i}: {e}")

print(f"Распределение запросов по серверам:")
for server, count in server_responses.items():
print(f" {server}: {count} запросов ({count/num_requests*100:.1f}%)")

print(f"Время ответа: среднее {statistics.mean(response_times):.3f}с, "
f"медиана {statistics.median(response_times):.3f}с")

check_load_balancer('https://api.example.com/health')

Производительность и оптимизация

Для высоконагруженных систем важно оптимизировать запросы. Вот несколько техник:

Connection pooling


from requests.adapters import HTTPAdapter

session = requests.Session()
adapter = HTTPAdapter(
pool_connections=100, # Количество connection pools
pool_maxsize=100, # Максимальное количество соединений в pool
max_retries=3
)
session.mount('http://', adapter)
session.mount('https://', adapter)

Асинхронные запросы с concurrent.futures


import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def make_request(url):
try:
response = requests.get(url, timeout=10)
return {'url': url, 'status': response.status_code, 'time': response.elapsed.total_seconds()}
except Exception as e:
return {'url': url, 'error': str(e)}

urls = [f'https://httpbin.org/delay/{i}' for i in range(1, 6)]

# Последовательные запросы
start_time = time.time()
results_sequential = [make_request(url) for url in urls]
sequential_time = time.time() - start_time

# Параллельные запросы
start_time = time.time()
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(make_request, url) for url in urls]
results_parallel = [future.result() for future in as_completed(futures)]
parallel_time = time.time() - start_time

print(f"Последовательно: {sequential_time:.2f}с")
print(f"Параллельно: {parallel_time:.2f}с")
print(f"Ускорение: {sequential_time/parallel_time:.2f}x")

Debugging и troubleshooting

Для отладки запросов используй встроенные возможности:


import requests
import logging

# Включаем подробное логирование
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("requests.packages.urllib3").setLevel(logging.DEBUG)
logging.getLogger("requests.packages.urllib3.connectionpool").setLevel(logging.DEBUG)

response = requests.get('https://httpbin.org/get')

# Или используй httpbin для тестирования
test_response = requests.get('https://httpbin.org/get', params={'test': 'value'})
print(test_response.json())

Для серьёзного тестирования и отладки рекомендую развернуть собственный тестовый сервер на выделенном сервере с полным контролем над конфигурацией.

Полезные ресурсы

Заключение и рекомендации

Python Requests — это must-have инструмент для любого, кто работает с серверами и API. Библиотека настолько проста в использовании, что даже сложные задачи решаются в несколько строк кода.

Когда использовать Requests:

  • Мониторинг состояния сервисов и API
  • Автоматизация задач через REST API
  • Интеграция с внешними сервисами
  • Парсинг веб-страниц
  • Написание скриптов для DevOps-задач

Когда стоит рассмотреть альтернативы:

  • Если нужна высокая производительность — смотри на httpx или aiohttp
  • Если нельзя устанавливать зависимости — используй urllib
  • Для WebSocket-подключений — нужны специализированные библиотеки

Начинай с простых GET-запросов, постепенно изучай продвинутые возможности вроде сессий и retry-политик. В 90% случаев Requests даст тебе всё необходимое для эффективной работы с HTTP API. Главное — не забывай про обработку ошибок и таймауты, особенно в продакшене.

И помни: хороший код — это код, который легко читать и поддерживать. Requests как раз про это.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked