Написать скрипт с запросами

Устал копипастить код? Учим писать скрипт с запросами, который сам парсит, кликает и скачивает. Готовые сниппеты для Python и JS внутри!

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

Автоматизация взаимодействия с веб-сервисами через API (Application Programming Interface) — базовый навык современного разработчика‚ системного администратора и аналитика данных․ Написание скриптов‚ отправляющих HTTP-запросы‚ позволяет интегрировать разные системы‚ собирать данные‚ управлять ресурсами в облаке и автоматизировать рутинные бизнес-процессы․

В этой статье мы подробно разберем основные подходы‚ популярные инструменты и приведем практические примеры кода на самых востребованных языках программирования‚ основываясь на актуальных практиках и документации популярных платформ (INTRUM CRM‚ ArcGIS‚ GitHub‚ Google Apps Script)․

Фундаментальные понятия

Прежде чем писать код‚ необходимо понимать архитектуру запроса:

  • Метод HTTP: GET (чтение)‚ POST (создание)‚ PUT/PATCH (обновление)‚ DELETE (удаление)․
  • Endpoint (Конечная точка): URL-адрес конкретного ресурса API (например‚ https://api․example․com/v1/users)․
  • Заголовки (Headers): Метаданные запроса․ Критически важны для авторизации (Authorization: Bearer *)‚ указания типа контента (Content-Type: application/json) и версионирования․
  • Параметры запроса (Query Params): Передаются в URL после знака ? для фильтрации‚ пагинации‚ сортировки․
  • Тело запроса (Body): Данные‚ отправляемые серверу (обычно в формате JSON или Form Data) при методах POST/PUT․
  • Коды ответа (Status Codes): 200 OK‚ 201 Created‚ 400 Bad Request‚ 401 Unauthorized‚ 404 Not Found‚ 500 Internal Server Error․

Инструментарий: выбор языка и библиотек

Выбор инструмента зависит от задачи‚ среды выполнения и предпочтений команды․

Python — стандарт де-факто для автоматизации и Data Science

Библиотека requests — это «золотой стандарт» простоты и мощности․ Встроенный модуль json и поддержка асинхронности (через aiohttp или httpx) делают Python идеальным выбором․

PHP — классика для веб-интеграций и CMS

Расширение cURL (Client URL Library) встроено в ядро PHP․ Оно предоставляет низкоуровневый контроль над запросом‚ что часто требуется для работы с легаси-системами или специфическими CRM (как INTRUM)․

JavaScript / TypeScript (Node․js‚ Browser‚ Google Apps Script)

  • Fetch API — современный стандарт браузеров и Node․js (v18+)․
  • Axios, популярная обертка с интерцепторами и автоматической трансформацией JSON․
  • Octokit․js — официальный SDK для GitHub REST API‚ предоставляющий типизацию и удобные методы․
  • Google Apps Script (UrlFetchApp), нативный сервис для вызова API прямо из Таблиц/Документов Google․

Специализированные SDK и CLI

Для крупных платформ (AWS‚ Azure‚ Google Cloud‚ ArcGIS‚ GitHub) всегда предпочтительнее использовать официальные SDK (Boto3‚ Azure SDK‚ ArcGIS API for Python‚ Octokit)‚ а не «сырые» HTTP-запросы․ Они обрабатывают повторные попытки (retries)‚ пагинацию‚ аутентификацию и сериализацию автоматически․

Практические примеры реализации

Пример 1: Python + Requests (Универсальный подход)

Базовый шаблон для работы с JSON API с обработкой ошибок и токеном авторизации․

import requests
import json
import os
from typing import Dict‚ Any‚ Optional

BASE_URL = "https://api․example․com/v1"
API_TOKEN = os․getenv("API_TOKEN"‚ "*") # МАСКА: реальный токен скрыт

HEADERS = {
 "Authorization": f"Bearer {API_TOKEN}"‚
 "Content-Type": "application/json"‚
 "Accept": "application/json"
}

def make_request(
 method: str‚ 
 endpoint: str‚ 
 params: Optional[Dict] = None‚ 
 data: Optional[Dict] = None
) -> Optional[Dict[Any‚ Any]]:
 """
 Универсальная функция-обертка для запросов․
 """
 url = f"{BASE_URL}{endpoint}"
 
 try:
 # Используем params для GET‚ json=data для POST/PUT
 response = requests․request(
 method=method․upper‚
 url=url‚
 headers=HEADERS‚
 params=params if method․upper == "GET" else None‚
 json=data if method․upper in ["POST"‚ "PUT"‚ "PATCH"] else None‚
 timeout=30 # Обязательно ставьте таймаут!
 )
 
 # Проверка на HTTP-ошибки (4xx‚ 5xx)
 response․raise_for_status
 
 # Если ответ пустой (204 No Content)
 if response․status_code == 204:
 return {"success": True}
 
 return response․json

 except requests․exceptions․HTTPError as http_err:
 print(f"HTTP ошибка: {http_err} | Ответ сервера: {response․text}")
 except requests․exceptions․ConnectionError:
 print("Ошибка соединения: проверьте URL и сеть․")
 except requests․exceptions;Timeout:
 print("Превышено время ожидания ответа․")
 except requests․exceptions․RequestException as err:
 print(f"Общая ошибка запроса: {err}")
 except json․JSONDecodeError:
 print(f"Сервер вернул невалидный JSON: {response․text}")
 
 return None

users = make_request("GET"‚ "/users"‚ params={"q": "python"‚ "page": 1‚ "limit": 10})
if users:
 print(f"Получено пользователей: {len(users․get('data'‚ []))}")
 # Сохранение в файл
 with open("users․json"‚ "w"‚ encoding="utf-8") as f:
 json․dump(users‚ f‚ ensure_ascii=False‚ indent=4)

new_user_payload = {
 "username": "test_user_"‚ # МАСКА: чувствительные данные
 "email": "user@example․com"‚
 "role": "developer"
}
created = make_request("POST"‚ "/users"‚ data=new_user_payload)
if created:
 print(f"Создан пользователь с ID: {created․get('id')}")

Пример 2: PHP + cURL (Интеграция с CRM INTRUM)

Пример из документации INTRUM CRM для добавления комментария к заявке․ Обратите внимание на структуру массива params и необходимость http_build_query для отправки в формате application/x-www-form-urlencoded․

<?php

// Конфигурация
$domain = 'yourdomain․intrumnet․com'; // МАСКА: реальный домен
$apiKey = '4723adc21f8f06d7bd5f###-###-####1'; // МАСКА: реальный API Key
$url = "http://{$domain}:81/sharedapi/applications/addComment";

// Данные для запроса
// entity_id ⎯ ID заявки‚ author ‒ ID автора комментария
$commentData = array(
 array(
 'entity_id' => 512‚ // МАСКА: реальный ID
 'text' => 'Был звонок от клиента․ Договорились о встрече․'‚
 'author' => 2 // МАСКА: реальный ID автора
 ));

$postData = array(
 'apikey' => $apiKey‚
 'params' => $commentData
);

// Инициализация cURL
$ch = curl_init;

curl_setopt_array($ch‚ array(
 CURLOPT_URL => $url‚
 CURLOPT_FOLLOWLOCATION => 1‚
 CURLOPT_POST => 1‚
 CURLOPT_POSTFIELDS => http_build_query($postData)‚ // Ключевой момент для этого API
 CURLOPT_RETURNTRANSFER => 1‚
 CURLOPT_SSL_VERIFYPEER => false‚ // Только для тестов/внутренних сетей! В проде ‒ true + cacert
 CURLOPT_TIMEOUT => 30
));

$response = curl_exec($ch);

if (curl_errno($ch)) {
 error_log("cURL Error: " ․ curl_error($ch));
} else {
 $httpCode = curl_getinfo($ch‚ CURLINFO_HTTP_CODE);
 $result = json_decode($response‚ true);
 
 if ($httpCode >= 200 && $httpCode < 300) {
 echo "Комментарий успешно добавен․ Response: " ․ print_r($result‚ true);
 } else {
 echo "Ошибка API ({$httpCode}): " ․ print_r($result‚ true);
 }
}

curl_close($ch);
?>

Пример 3: Google Apps Script (Автоматизация Google Таблиц)

Идеально для аналитиков и менеджеров: получаем данные из API и сразу пишем в таблицу без развертывания серверов․

function fetchDataAndWriteToSheet {
 // 1․ Настройка запроса
 const apiUrl = 'https://api․example․com/v1/projects'; // МАСКА: реальный URL
 const token = PropertiesService․getScriptProperties․getProperty('API_TOKEN'); // Хранение секрета в Properties
 
 const options = {
 'method': 'get'‚
 'headers': {
 'Authorization': 'Bearer ' + token‚
 'Accept': 'application/json'
 }‚
 'muteHttpExceptions': true // Важно: не выбрасывать исключение при 4xx/5xx‚ а анализировать код
 };
 try {
 // 2․ Выполнение запроса
 const response = UrlFetchApp․fetch(apiUrl‚ options);
 const responseCode = response․getResponseCode;
 const responseBody = response․getContentText;
 
 if (responseCode !== 200) {
 throw new Error(`API Error ${responseCode}: ${responseBody}`);
 }
 const data = JSON․parse(responseBody);
 
 // 3․ Подготовка данных для таблицы (двумерный массив)
 // Предположим‚ data ‒ это массив объектов [{id‚ name‚ status}‚ ․․․]
 const header = ['ID'‚ 'Название проекта'‚ 'Статус'‚ 'Дата создания'];
 const rows = data․map(item => [
 item․id‚

 item․name‚
 item․status‚
 item․created_at ? new Date(item․created_at) : 'N/A'
 ]);
  // Добавляем  в начало
 const finalArray = [header‚ ․․․rows];

 // 4․ Запись в таблицу
 const ss = SpreadsheetApp․getActiveSpreadsheet;
 const sheet = ss․getSheetByName('PROJECTS'); // МАСКА: реальное имя листа
 
 if (!sheet) {
 throw new Error('Лист "PROJECTS" не найден');
 }
 
 // Очистка старых данных (опционально) и запись новых
 // getRange(строка‚ столбец‚ кол-во строк‚ кол-во столбцов)
 sheet․clearContents; 
 sheet․getRange(1‚ 1‚ finalArray․length‚ finalArray[0]․length)․setValues(finalArray);
 
 // Автоширина колонок для красоты
 sheet․autoResizeColumns(1‚ finalArray[0]․length);
 
 Logger․log(`Успешно записано ${rows․length} строк․`);

 } catch (e) {
 Logger․log('Ошибка выполнения скрипта: ' + e․toString);
 // Можно отправить уведомление на email через MailApp․sendEmail
 }}

Пример 4: JavaScript + Octokit (Работа с GitHub API)

Рекомендуемый GitHub способ взаимодействия через SDK․

// Node․js (ES Modules) или современный браузер
import { Octokit } from "octokit";

// Токен берем из переменных окружения
const octokit = new Octokit({ 
 auth: process․env․GITHUB_TOKEN // МАСКА: реальный токен
 // baseUrl: "https://github․*․com/api/v3"‚ // Для GitHub Enterprise
});

async function listUserRepos(username) {
 try {
 // Octokit автоматически обрабатывает пагинацию через ․paginate
 const repos = await octokit․paginate(
 "GET /users/{username}/repos"‚ 
 { username‚ per_page: 100‚ sort: "updated" }
 );

 console․log(`Найдено репозиториев: ${repos․length}`);
 
 for (const repo of repos․slice(0‚ 5)) { }
 
 return repos;
 } catch (error) {
 // Octokit выбрасывает структурированные ошибки
 if (error․status === 404) {
 console․error(`Пользователь ${username} не найден;`);
 } else if (error․status === 403) {
 console․error('Лимит запросов исчерпан или нет прав доступа․');
 } else {
 console․error('Ошибка GitHub API:'‚ error․message);
 }
 }
}

listUserRepos('octocat');

Продвинутые темы и Best Practices

Безопасность: управление секретами

  • Никогда не хардкодьте токены‚ ключи‚ пароли в коде․ Используйте переменные окружения (․env + python-dotenv)‚ секретные хранилища (HashiCorp Vault‚ AWS Secrets Manager‚ GitHub Secrets‚ Google Apps Script Properties)․
  • В примерах выше все чувствительные данные заменены на *․
  • Используйте CURLOPT_SSL_VERIFYPEER => true (PHP) и `verify=True` (Python requests) в продакшене․ Отключение проверки SSL, критическая уязвимость (MITM-атаки)․

Обработка Rate Limiting (Ограничение частоты запросов)

Почти все публичные API ограничивают количество запросов (например‚ GitHub: 5000 req/hr для авторизованных)․

  • Парсьте заголовки ответа: X-RateLimit-Remaining‚ X-RateLimit-Reset‚ Retry-After․
  • Реализуйте Exponential Backoff (экспоненциальную задержку) при получении кода 429 Too Many Requests или 5xx․
  • В Python удобно использовать библиотеку tenacity или встроенные механизмы httpx/aiohttp․

Пагинация

Не пытайтесь получить все данные одним запросом․ Реализуйте итератор по страницам:

  • Offset-based: `page=1&limit=100` -> `page=2․․․` (просто‚ но медленно на больших смещениях)․
  • Cursor-based: `after=»opaque_cursor_string»` (быстро‚ устойчиво к удалению записей)․
  • Link Header: Стандарт RFC 5988 (`Link: ; rel=»next»`)․ Библиотеки вроде Octokit или `requests-pagination` делают это автоматически․

Идемпотентность

Для операций изменения данных (POST‚ PUT‚ PATCH‚ DELETE) используйте Idempotency-Key: (поддерживается Stripe‚ GitHub‚ Яндекс․Касса и др․)․ Это гарантирует‚ что повторная отправка одного и того же запроса (при таймауте сети) не создаст дубликат сущности․

Логирование и наблюдаемость

Логируйте: URL‚ метод‚ статус-код‚ время выполнения (latency)‚ ID запроса (Request ID из заголовков ответа)․ Не логируйте тела запросов/ответов‚ если они содержат PII (персональные данные)‚ токены или номера карт․ Используйте структурированное логирование (JSON) для отправки в ELK/Grafana Loki․

Отладка и разработка

Инструменты для исследования API

  1. Postman / Insomnia / Bruno: GUI-клиенты для ручного тестирования‚ генерации сниппетов кода (включая Python requests‚ PHP cURL‚ JS fetch)‚ управления окружениями и коллекциями․
  2. Fiddler / Charles Proxy / Wireshark: Перехват трафика (Man-in-the-Middle) для реверс-инжиниринга приватных API (например‚ мобильных приложений или веб-интерфейсов ArcGIS Portal Directory)․ Позволяют увидеть полное тело запроса и ответа‚ заголовки и куки․
  3. Browser DevTools (Network tab): Самый быстрый способ увидеть‚ какие запросы отправляет фронтенд (Fetch/XHR)‚ скопировать их как cURL (Copy -> Copy as cURL) и перенести в скрипт․

ArcGIS REST API: специфика администрирования

При работе с Portal for ArcGIS / ArcGIS Server:

  • Используйте ArcGIS Portal Directory (`https:///portal/sharing/rest`) и Server Admin Directory (`https:///server/admin`) для изучения доступных эндпоинтов и параметров․
  • Аутентификация часто строится на токенах (`generateToken`)‚ которые нужно получать предварительно и передавать в параметре `token` или заголовке․
  • Для скриптов администрирования рекомендуется ArcGIS API for Python (`from arcgis․gis import GIS`)‚ который абстрагирует ручную работу с REST․

Чек-лист перед запуском в прод

Проверка Описание
Таймауты Заданы connect/read таймауты (не висеть вечно)?
Retry Logic Есть ли повторные попытки при 5xx/429/timeout с backoff?
Валидация входа Проверяются ли входные данные перед отправкой?
Обработка ответов Парсятся ли ошибки 4xx/5xx? Есть ли fallback?
Секреты Нет ли токенов в коде/логах/репозитории?
SSL/TLS Проверка сертификатов включена (verify=True)?
User-Agent Задан понятный User-Agent (имя скрипта/версия/контакт)?
Идемпотентность Передается ли Idempotency-Key для мутирующих запросов?
Мониторинг Есть ли метрики успеха/ошибок/латентности?

Написание надежных скриптов для работы с API — это не просто «отправить запрос и получить ответ»․ Это инженерная задача‚ требующая учета сетевой нестабильности‚ ограничений сторонних сервисов‚ безопасности данных и поддержки кода в долгосрочной перспективе․

Используйте высокоуровневые библиотеки (requests‚ Octokit‚ ArcGIS API for Python‚ SDK облачных провайдеров) там‚ где это возможно․ Опускайтесь на уровень «сырых» HTTP-запросов (cURL‚ Fetch‚ `urllib`) только для интеграции с легаси-системами (как INTRUM CRM в примере выше) или когда SDK не существует․

Следуйте принципу: «Сделай просто‚ сделай безопасно‚ сделай наблюдаемо»; Храните конфигурацию отдельно от кода‚ маскируйте секреты (*) в логах и репозиториях‚ и всегда тестируйте скрипты в изолированном окружении (staging/sandbox) перед запуском на продакшн-данных․