Files

3.8 KiB
Raw Permalink Blame History

Tasks: rss-crawler

1. Схема и конфиг

  • 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 появляются
  • 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
  • 1.3 requirements.txt: + trafilatura, selectolax Проверка: .venv/bin/pip install -r requirements.txt без ошибок

2. Модуль краулера

  • 2.1 crawler/rss_crawler.py: normalize_url (UTM/якоря), sha256_text Проверка: изолированный тест normalize_url: utm-параметры удаляются, якорь удаляется, остальное сохраняется
  • 2.2 fetch_feed: httpx.GET с If-None-Match/If-Modified-Since/User-Agent, таймаут, ретрай 429/503; 304 → пусто Проверка: повторный запрос к ленте с etag → 304 (сервер LWN поддерживает)
  • 2.3 parse_entries: feedparser, извлечение etag/modified из ответа, лимит записей (MAX_ITEMS=25) Проверка: запись → dict {url, title, text, published_at, author}
  • 2.4 full_text: trafilatura для summary-only (selectolax для HTML→text) Проверка: запись с summary → в text полный текст или summary (не падает)
  • 2.5 store_rss_post: дедуп по sha256; вставка в posts (source_id, url, canonical_url, content_type='text', published_at) Проверка: две идентичные записи → одна строка в posts
  • 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 растёт
  • 2.7 CLI: --all / --direction / --source / --dry-run Проверка: --source lwn --dry-run печатает записи, БД не меняется

3. Источники и интеграция

  • 3.1 sources.yaml: + lwn (crawler: rss, direction: linux, priority: P0, enabled: true); пример opennet закомментирован Проверка: sync_sources_to_db() — в БД появляется источник lwn c crawler='rss'
  • 3.2 .env.example: + RSS_USER_AGENT, RSS_DEFAULT_TIMEOUT
  • 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; ручной запуск проходит
  • 4.2 STATUS.md / AGENT.MD обновлены (команды запуска, порты/доступы) Проверка: grep rss в доках
  • 4.3 openspec validate rss-crawler → 0 ошибок Проверка: команда выше → valid
  • 4.4 TODO.md: + задача веб-скедулинга RSS (веб-админ: кнопка запуска краулера) Проверка: задача видна в планах

Открытый вопрос: состояние таблицы rss_state ERROR (после 429 и ретрая, error_count=1) обновится при следующем удачном 200; в отсутствие ошибок не трогаем.