Tegia News Get

HTTP API чтения архива новостей после Extractor. Сервис возвращает ссылки за период по дате и времени публикации на сайте, а по каждой ссылке — JSON для Tegia News Matching POST /v1/news. Отправку новостей и управление темпом эмуляции выполняет потребитель.

Авторизация

Все маршруты, кроме GET /health и GET /docs, требуют заголовок:

Authorization: Bearer <NEWS_GET_API_TOKEN>

Для скачивания JSON по ссылке нужен тот же заголовок. Токен этого сервиса отличается от токена Matching. Примеры используют переменную BASE_URL с доступным потребителю адресом сервиса и NEWS_GET_API_TOKEN с выданным токеном.

BASE_URL='http://127.0.0.1:8093'

GET /v1/news — список новостей

Возвращает страницу ссылок. Границы периода: from <= published_at < to.

Параметры строки запроса
ПараметрТребованиеОписание
fromОбязательныйНачало периода, ISO 8601 с часовым поясом, например 2026-09-03T00:00:00Z.
toОбязательныйКонец периода, исключающий границу; позже from.
limit1–100, по умолчанию 100Максимальное число результатов на странице.
cursorНеобязательныйЗначение next_cursor предыдущего ответа. Передаётся с тем же периодом.
curl --get "$BASE_URL/v1/news" \
  -H "Authorization: Bearer $NEWS_GET_API_TOKEN" \
  --data-urlencode 'from=2026-09-03T00:00:00Z' \
  --data-urlencode 'to=2026-09-04T00:00:00Z' \
  --data-urlencode 'limit=100'

Пример ответа 200 OK (адрес и идентификатор статьи условные):

{
  "items": [
    {
      "url": "https://example.org/news/123",
      "json_url": "https://archive.example/v1/news/<sha256>/content?etag=%22version%22",
      "published_at": "2026-09-03T09:52:21.590305Z"
    }
  ],
  "next_cursor": null,
  "scanned": 1,
  "scanned_keys": 1,
  "skipped": 0,
  "skipped_missing_publication_time": 0,
  "date_basis": "published_at",
  "consistency": "live",
  "page_stop_reason": "end"
}

Обход завершён только при next_cursor: null. Пустой массив items с курсором требует следующего запроса. Курсор подписан, привязан к источнику и периоду; срок действия по умолчанию — 24 часа. Смена токена API делает старые курсоры недействительными.

GET /v1/news/{article_id}/content — содержимое новости

Используйте json_url из списка целиком. article_id — идентификатор архивного JSON из 64 шестнадцатеричных символов нижнего регистра. Необязательный параметр etag фиксирует ожидаемую версию объекта; без него возвращается текущая версия.

curl "$JSON_URL" \
  -H "Authorization: Bearer $NEWS_GET_API_TOKEN"

Задайте JSON_URL равным ссылке из ответа. Результат 200 OK — тело запроса Matching без дополнительной обёртки:

{
  "source": "crawler",
  "external_id": "https://example.org/news/123",
  "url": "https://example.org/news/123",
  "title": "Заголовок",
  "content": "Первый абзац.\n\nВторой абзац.",
  "published_at": "2026-09-03T09:52:21.590305Z"
}

Текст уже извлечён Extractor, границы абзацев сохраняются. HTML не включается в ответ; исходный сайт не скачивается. Повторная передача того же source и external_id подпадает под дедупликацию Matching.

Даты, порядок и ограничения обхода

Точное время с часовым поясом берётся из article.publishedAt. Если точного времени нет, сервис проверяет article:published_time в head архивного HTML и datePublished JSON-LD основной статьи. Противоречащие даты не выбираются по порядку HTML. Время скачивания, изменения объекта и dateModified не используются. Точные даты возвращаются в UTC.

Статьи с известным только днём или неизвестным временем исключаются из списка. При прямом запросе содержимого их published_at может быть YYYY-MM-DD или null.

Порядок выдачи определяется ключом архива, а не датой публикации. consistency=live означает отсутствие снимка: изменения архива влияют на обход, новые ключи перед курсором могут появиться только при новом обходе. Для повторяемого эксперимента сохраните полученные документы и отсортируйте их у потребителя.

По умолчанию запрос списка ограничен 100 ключами, 50 JSON-кандидатами, 32 MiB прочитанных документов и 20 секундами. Максимальный документ — 10 MiB, одновременно выполняются до 4 операций. Значения на сервере могут быть изменены. Исчерпание бюджета после продвижения возвращает частичную страницу с курсором; незавершённый документ повторяется на следующей странице.

Служебные маршруты

Все маршруты используют метод GET
ПутьТокенРезультат
/docsНе нуженЭта HTML-справка. Доступна без обращения к архиву.
/healthНе нужен{"status":"ok"} — HTTP-процесс работает.
/readyНужен{"status":"ready","checks":["list","get","article"]} — доступны листинг, чтение и корректная контрольная статья.
/metricsНуженJSON с totals, statuses, inflight и max_inflight.

totals содержит requests, errors, duration_seconds, s3_list, s3_get, s3_bytes, scanned, skipped и skipped_missing_publication_time. statuses — числа ответов по HTTP-статусам. Счётчики накопительные, относятся к одному процессу и сбрасываются при его перезапуске.

Ошибки и повторные запросы

Ошибки приложения возвращаются как {"error":{"code":"unauthorized"}}. Ошибки валидации параметров FastAPI имеют статус 422 и поле detail.

HTTP-статусы ошибок
СтатусПричина и действие
400Некорректные даты, период или курсор. Исправьте параметры.
401Отсутствует или неверен bearer token.
404Статья отсутствует или идентификатор некорректен.
409article_changed: версия объекта изменилась. Запросите список заново.
410Курсор истёк. Начните новый обход без курсора.
422Некорректные параметры либо непригодный или слишком большой JSON.
429Заняты рабочие слоты. Повторите запрос позже.
499Клиент отключился, работа отменена. Код прежде всего используется в журнале.
503Архив недоступен, проверка готовности не прошла либо нет прогресса по бюджету байтов.
504Истекло время запроса без результата.

На ошибки приложения 429, 503 и 504 добавляется Retry-After: 1. Повторяйте запрос с ограничением попыток и увеличением задержки. Заголовок X-Request-ID помогает найти запрос в журнале сервиса.