No description
Find a file
2026-03-09 11:26:53 +03:00
data Add dockerized Magnit API service 2026-03-09 11:26:53 +03:00
nginx first commit 2026-03-09 11:04:49 +03:00
.dockerignore Add dockerized Magnit API service 2026-03-09 11:26:53 +03:00
.gitignore Add dockerized Magnit API service 2026-03-09 11:26:53 +03:00
docker-compose.yml Add dockerized Magnit API service 2026-03-09 11:26:53 +03:00
Dockerfile Add dockerized Magnit API service 2026-03-09 11:26:53 +03:00
magnit_api.py Add dockerized Magnit API service 2026-03-09 11:26:53 +03:00
README.md Add dockerized Magnit API service 2026-03-09 11:26:53 +03:00
requirements.txt first commit 2026-03-09 11:04:49 +03:00

Magnit price API

Локальный HTTP API и CLI для magnit.ru, который:

  • принимает store_code и query;
  • ищет товары через backend POST /webgate/v2/goods/search;
  • сам обновляет access token через POST /magnit-id/v1/auth/token/refresh;
  • хранит рабочую сессию в magnit_session.json.

Быстрый старт

Запуск API:

python3 magnit_api.py serve --host 127.0.0.1 --port 8080

Docker Compose

Сборка и запуск:

cp .env.example .env
docker compose up -d --build

По умолчанию сервис публикуется только в loopback на 127.0.0.1:18080. Docker хранит session-файл в ./data/magnit_session.json, а не в корне проекта.

Проверка:

curl "http://127.0.0.1:18080/health"
curl "http://127.0.0.1:18080/price?store_code=618224&query=Red%20Bull"

Если нужен другой внешний порт:

MAGNIT_API_PORT=18081 docker compose up -d --build

Проверка:

curl "http://127.0.0.1:18081/price?store_code=618224&query=Red%20Bull"

CLI без HTTP-сервера:

python3 magnit_api.py price --store-code 618224 --query "Red Bull"
python3 magnit_api.py search --store-code 618224 --query "Red Bull"

Endpoint'ы

GET /health

GET /session

POST /session/refresh

POST /session/bootstrap

{
  "mg_at": "%7B%22access%22%3A%22...%22%2C%22refresh%22%3A%22...%22%7D",
  "device_id": "761fa244-97f7-4b6e-b93a-8c258f357580",
  "device_tag": "8894ea27-7a01-42f0-8500-20eb63bbc7c9_1"
}

GET /search?store_code=618224&query=Red%20Bull

GET /price?store_code=618224&query=Red%20Bull

Nginx proxy_pass

Готовый пример лежит в nginx/magnit-api.location.conf.example.

Если nginx стоит на хосте и docker compose публикует API на 127.0.0.1:18080, используйте:

location /magnit-api/ {
    proxy_pass http://127.0.0.1:18080/;
    proxy_http_version 1.1;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
}

Тогда внешний запрос будет таким:

curl "https://your-domain.example/magnit-api/price?store_code=618224&query=Red%20Bull"

Если nginx контейнерный и находится в одной сети с magnit-api, замените upstream на http://magnit-api:8080/.

Что хранится в сессии

magnit_session.json содержит:

  • refresh_token
  • access_token
  • device_id (mg_udi)
  • device_tag (mg_ksid)
  • служебные заголовки браузера

Скрипт сам обновляет access_token, когда JWT подходит к истечению.

Как перебутстрапить сессию

Если refresh_token станет невалидным, откройте magnit.ru, где вы уже авторизованы, и в DevTools Console выполните:

copy(JSON.stringify({
  mg_at: decodeURIComponent(document.cookie.split('; ').find(v => v.startsWith('mg_at=')).split('=').slice(1).join('=')),
  device_id: document.cookie.split('; ').find(v => v.startsWith('mg_udi=')).split('=').slice(1).join('='),
  device_tag: document.cookie.split('; ').find(v => v.startsWith('mg_ksid=')).split('=').slice(1).join('=')
}, null, 2));

Потом отправьте это в локальный API:

curl -X POST "http://127.0.0.1:8080/session/bootstrap" \
  -H "Content-Type: application/json" \
  -d @payload.json

Если API запущен через docker compose, используйте опубликованный порт, по умолчанию 18080:

curl -X POST "http://127.0.0.1:18080/session/bootstrap" \
  -H "Content-Type: application/json" \
  -d @payload.json

При Docker session сохранится в ./data/magnit_session.json.