mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 18:05:03 +00:00
48 lines
3.8 KiB
Markdown
48 lines
3.8 KiB
Markdown
# Tasks: rss-crawler
|
||
|
||
## 1. Схема и конфиг
|
||
|
||
- [x] 1.1 db/schema.sql: + CREATE TABLE rss_state; sources + feed_url; db/db.py — миграция ALTER TABLE (feed_url); sources.py — синк feed_url
|
||
Проверка: `python -m db.db` (init_db) выполняется без ошибок; таблица rss_state и колонка sources.feed_url появляются
|
||
- [x] 1.2 config.py: + RSS_USER_AGENT (env, default "vesti-rss/0.1"), RSS_DEFAULT_TIMEOUT=20
|
||
Проверка: `python -c "from config import RSS_USER_AGENT; print(RSS_USER_AGENT)"` → значение из .env
|
||
- [x] 1.3 requirements.txt: + trafilatura, selectolax
|
||
Проверка: `.venv/bin/pip install -r requirements.txt` без ошибок
|
||
|
||
## 2. Модуль краулера
|
||
|
||
- [x] 2.1 crawler/rss_crawler.py: normalize_url (UTM/якоря), sha256_text
|
||
Проверка: изолированный тест normalize_url: utm-параметры удаляются, якорь удаляется, остальное сохраняется
|
||
- [x] 2.2 fetch_feed: httpx.GET с If-None-Match/If-Modified-Since/User-Agent, таймаут, ретрай 429/503; 304 → пусто
|
||
Проверка: повторный запрос к ленте с etag → 304 (сервер LWN поддерживает)
|
||
- [x] 2.3 parse_entries: feedparser, извлечение etag/modified из ответа, лимит записей (MAX_ITEMS=25)
|
||
Проверка: запись → dict {url, title, text, published_at, author}
|
||
- [x] 2.4 full_text: trafilatura для summary-only (selectolax для HTML→text)
|
||
Проверка: запись с summary → в text полный текст или summary (не падает)
|
||
- [x] 2.5 store_rss_post: дедуп по sha256; вставка в posts (source_id, url, canonical_url, content_type='text', published_at)
|
||
Проверка: две идентичные записи → одна строка в posts
|
||
- [x] 2.6 run_source: start_run/finish_run, обновление rss_state (etag/modified/status/error_count), status alive/dead при error_count>=5
|
||
Проверка: успешный прогон → rss_state.status='alive', runs=ok; имитация ошибки → error_count растёт
|
||
- [x] 2.7 CLI: --all / --direction / --source / --dry-run
|
||
Проверка: `--source lwn --dry-run` печатает записи, БД не меняется
|
||
|
||
## 3. Источники и интеграция
|
||
|
||
- [x] 3.1 sources.yaml: + lwn (crawler: rss, direction: linux, priority: P0, enabled: true); пример opennet закомментирован
|
||
Проверка: `sync_sources_to_db()` — в БД появляется источник lwn c crawler='rss'
|
||
- [x] 3.2 .env.example: + RSS_USER_AGENT, RSS_DEFAULT_TIMEOUT
|
||
- [x] 3.3 Реальный прогон `--source lwn` → посты в posts, rss_state настроена
|
||
Проверка: SQL-запросы из design.md (Verification)
|
||
|
||
## 4. Cron и доки
|
||
|
||
- [ ] 4.1 Hermes cron: vesti-rss-crawler (`*/15`, P0; no_agent, тихий, deliver=local)
|
||
Проверка: cron list показывает job; ручной запуск проходит
|
||
- [x] 4.2 STATUS.md / AGENT.MD обновлены (команды запуска, порты/доступы)
|
||
Проверка: grep rss в доках
|
||
- [x] 4.3 `openspec validate rss-crawler` → 0 ошибок
|
||
Проверка: команда выше → valid
|
||
- [ ] 4.4 TODO.md: + задача веб-скедулинга RSS (веб-админ: кнопка запуска краулера)
|
||
Проверка: задача видна в планах
|
||
|
||
Открытый вопрос: состояние таблицы rss_state ERROR (после 429 и ретрая, error_count=1) обновится при следующем удачном 200; в отсутствие ошибок не трогаем. |