Оба массовых источника исчерпаны — wikipedia_ru и pmc_bulk отдают ноль,
сторож честно пишет «источник исчерпан, пропускаем», и корпус стоит.
Брать новые статьи неоткуда, а главная дыра прежняя: полный текст есть у
11% корпуса, по-русски — почти нигде (CyberLeninka отдаёт только HTML
страницы, тела статьи там нет вовсе).
CORE кладёт готовый текст прямо в выдачу поиска: его не надо ни качать
отдельно, ни извлекать из PDF. Парсер массовый, как Википедия и PMC —
отдаёт статьи генератором, пишется пачками через COPY, помнит позицию.
Что выяснено живьём и учтено в коде:
- у /v3/search/works обязателен слэш на конце, иначе 301, а на редиректе
теряется заголовок Authorization и запрос уходит анонимным;
- offset упирается в 100 000 (под капотом Azure Search), поэтому выборка
режется по годам, а позиция продолжения — строка «год:смещение»;
- fullText не фильтруемое поле, _exists_:fullText отвечает 500 — статьи с
текстом приходится отбирать на своей стороне;
- CORE отдаёт одну статью под разными id из разных репозиториев, а корпус
дедуплицируется только по ext_id: такие пары легли бы отдельными
документами и ловились бы как заимствование друг у друга. Отсеиваем по
хешу начала текста в пределах прогона.
Позиция указывает на страницу, из которой пришла статья, а не на
следующую: пачка может прерваться на середине страницы, и тогда прогон
перечитает её целиком. Лишний запрос дешевле потерянных статей, дубли
отсекает ON CONFLICT.
Замер на живом API: страница в 100 записей приходит за ~7с. В общем
потоке CORE кириллицы нет вовсе (0 из 48 полных текстов за 2019), язык
размечен негодно — сплошь None и «zz». Зато работает отбор по архиву:
запрос по 41 вузовскому репозиторию России и Беларуси даёт 79 полных
текстов из 100 записей, 78 из них кириллические. Список архивов живёт в
поле query источника, а не в коде — правится из админки без пересборки.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>