Files
omni-parse/README.md

231 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### Telegram-бот: кнопки, канал, формат
```bash
set OMNI_BOT_TOKEN=<токен BotFather> # .bot_token, в git не попадает
set OMNI_BOT_OWNERS=<твой numeric id> # кому отвечает, можно несколько через запятую
python -m omni.bot
```
Экран бота — инлайн-кнопки: `Лента`, `Абузы`, `Источники`, `Цифры`, теги `Промо / Триалы / Сливы`, `Подписка: вкл/выкл`, `Формат: кратко/полно`, `Пост в канал`.
Команды: `/new [N]`, `/abuse [тег]`, `/find <слово>`, `/src <слово>`, `/run <категория>`, `/add <url>`, `/auto [N]`, `/stats`, `/sub [@канал]`, `/unsub [@канал]`, `/subs`, `/post [@канал]`.
**Постинг в канал.** Добавь бота админом канала с правом публикации и отправь `/sub @твойканал` — бот каждые 5 минут проверяет новые абузы и публикует только те, что появились после подписки. `/post @твойканал` — опубликовать подборку сразу, `/unsub @твойканал` — остановить. Дальше можно подключить свой бот: код один, токен свой, база общая.
**Формат текста.** `кратко` — заголовок, источник, тег. `полно` — плюс ссылка на запись. Переключается кнопкой и хранится на чат/канал: канал можно держать в одном формате, личку — в другом.
**Про ключи не публикуем.** Тег `keys` отфильтрован на уровне бота (`HIDE_TAGS` в `omni/bot.py`): записи, у которых после фильтра не осталось тегов, не попадают ни в `/abuse`, ни в автопостинг.
# omni-parse
Один парсер под любую тему: Reddit, форумы, поисковики, X/Twitter, карточки товаров и платные search-API — в одну SQLite-базу с FTS5, дедупом и рейтингом.
Ставится без ключей. Платные провайдеры включаются сами, если в окружении есть ключ.
## Состояние на сейчас
- **источников: 589** в 11 категориях, **записей в базе: 3411**
- вкладки панели: `Лента` · `Источники` · `Прогоны` · `Абузы`
- health-аудит: живой/мёртвый/непроверенный по каждому источнику, причина в примечании
- Telegram-бот на той же базе: `/new`, `/abuse`, `/find`, `/src`, `/run`, `/add`, `/auto`, `/stats`
| категория | источников |
|---|---|
| `community` | 123 |
| `company` | 119 |
| `security` | 72 |
| `papers` | 68 |
| `forum` | 50 |
| `models` | 35 |
| `company_cn` | 34 |
| `abuse` | 31 |
| `release` | 30 |
| `benchmark` | 16 |
| `company_kr` | 11 |
## Панель
```bash
python -m omni serve --port 8077
# http://127.0.0.1:8077/?view=abuse
```
`?view=feed|src|runs|abuse`, горячие клавиши `1..4`, палитра `Ctrl K`, категории в URL (`?cat=`), кнопка «авто-добавление» ищет новые фиды на уже подключённых хостах и сохраняет только те, что реально отдали записи.
## Что умеет
| Провайдер | Что тянет | Ключ |
|---|---|---|
| `reddit` | поиск по постам и комментариям через api.pullpush.io (архив Reddit) + публичный json как запас | нет |
| `forums` | Discourse (9 инстансов), Hacker News (Algolia), Lobsters, XenForo, веб-версии Telegram-каналов | нет |
| `ddg` | html-выдача DuckDuckGo | нет |
| `bing` | html-выдача Bing, ссылки раскодируются из `ck/a?...u=a1<base64url>` | нет |
| `mojeek` | html Mojeek (свой индекс, без капчи) | нет |
| `x` | без платного API: oembed по URL твита, syndication-таймлайн профиля, поиск твитов через ddg/bing/mojeek | нет |
| `tavily` | Tavily search | `TAVILY_API_KEY` |
| `exa` | Exa search + текст страниц | `EXA_API_KEY` |
| `you` | You.com search | `YOU_API_KEY` |
| `firecrawl` | Firecrawl search | `FIRECRAWL_API_KEY` |
| `cards` | карточки товаров: JSON-LD Product/Offer, OpenGraph, microdata, цена/валюта/наличие | нет |
| `treg` | treg-поиск | `TREG_TOKEN` |
| `feed` | обход реестра из 450 лент/API без запроса (см. ниже) | нет |
`python -m omni providers` печатает, что реально поднялось в этом окружении.
## Установка
```bash
pip install -r requirements.txt
cp .env.example .env # ключи по желанию, ни один не обязателен
```
## Быстрый старт
```bash
# что доступно
python -m omni providers
# поиск по одной теме в четырёх бесплатных источниках
python -m omni search "scraping twitter without api" --providers reddit,forums,ddg,bing --limit 12 --show 10
# реестр источников: сколько и каких
python -m omni sources
python -m omni sources --category papers,security --list
# обход реестра БЕЗ запроса: 589 источников -> база
python -m omni feed --category community --limit 8
python -m omni feed --limit 15 # всё подряд
python -m omni feed --only arxiv_cs_ai,hn_top,reddit_localllama
# прогон по списку тем из themes.txt (по теме на строку)
python -m omni fanout --providers reddit,forums,ddg,bing --limit 10
# топ базы, статистика, поиск по своей базе
python -m omni top --limit 20
python -m omni stats
python -m omni find "proxy"
# карточки товаров по URL
python -m omni cards https://example.com/product
# выгрузка
python -m omni export --format jsonl --out data/dump.jsonl
```
## Реестр источников
`omni/sources.py` + `omni/sources_ext.py` — **589 источников в 9 категориях**, у каждого свой адаптер и флаг вкл/выкл:
- **papers 49** — arxiv по 25+ разделам (cs.AI/LG/CL/CV/RO/IR/CR/SE/NE/MA/DC/DB/HC/SD/CY, stat.ML, eess.AS/SP/IV, math.OC, q-bio.NC, cs.GR, cs.AR, cs.PF), HF daily papers, OpenAlex, Semantic Scholar, Papers with Code, Connected Papers
- **company 95** — ленты OpenAI, Google AI/Research/DeepMind, Microsoft Research, NVIDIA, Apple ML, Amazon Science, HF, Meta AI, Mistral, Cohere, Together, Perplexity, Groq, Cerebras, Stability, Databricks, Anyscale, Modal, W&B, LangChain, LlamaIndex, vLLM, Replicate, Fireworks, SambaNova, Scale, xAI, Salesforce, AWS ML, Azure AI, Anthropic, AI2, EleutherAI, LAION, Runway, ElevenLabs, Deepgram, AssemblyAI, Pinecone, Weaviate, Qdrant, Chroma, Unsloth, Axolotl
- **company_cn 31** — Qwen, DeepSeek changelog, Moonshot, Zhipu, Baichuan, MiniMax, StepFun, 01.AI, InternLM, ChatGLM + GitHub-орги Tencent-Hunyuan, PaddlePaddle, bytedance, mindspore-ai, QwenLM, deepseek-ai, MoonshotAI, THUDM, OpenBMB, Shanghai-AI-Lab
- **company_kr 10** — Kakao tech, Naver Cloud/D2, Samsung Research, LG AI Research, Upstage, Rebellions, Twelve Labs, FriendliAI
- **community 49** — HN top/new/ask/show, Lobsters (4 тега), GeekNews, Reddit: LocalLLaMA, OpenAI, singularity, MachineLearning, deeplearning, netsec, programming, rust, golang, Python, webdev, selfhosted, devops, datascience, androiddev, javascript, linux, experienced_devs
- **security 45** — THN, BleepingComputer, Krebs, SANS ISC, Packet Storm, CISA advisories + CISA KEV (JSON), NVD CVE (JSON), Exploit-DB, Project Zero, PortSwigger, GitHub Security, Rapid7, Qualys, Tenable, CrowdStrike, SentinelOne, Unit42, Talos, Securelist, WeLiveSecurity, Malwarebytes, Schneier, Graham Cluley, HackerOne hacktivity, Bugcrowd, Intigriti, YesWeHack, CTFtime, OWASP, SANS diaries, Risky Business, tl;dr sec, Detection Engineering
- **forum 31** — 10 Discourse-инстансов (discuss.python, community.openai, forum.cursor, discuss.huggingface, forum.obsidian, community.cloudflare, discuss.elastic, forum.gitlab, community.home-assistant, discuss.grafana), XenForo BHW, веб-версии Telegram-каналов (durov, telegram, AI-каналы), Stack Overflow tags, Reddit-миграции
- **models 18** — HF trending/new (модели, спейсы, датасеты), HF по 6 пайплайн-тегам, Ollama library + search, LM Studio catalog, OpenRouter models + pricing (JSON), Civitai, Replicate explore
- **benchmark 10** — Open LLM Leaderboard, LMArena, Artificial Analysis, Epoch AI, SWE-bench, LiveBench, HELM, MTEB, BigCodeBench, Chatbot Arena
Адаптеры: `rss`, `generic_json`, `or_models`, `cisa_kev`, `nvd`, `json` (HF, HN, OpenAlex, S2, Discourse), `html` (список + детальная), `github_org`. Медленные хосты (reddit, github, HF, arxiv, openrouter) обходятся последовательно с паузой, остальные — в 8 потоков. Для arxiv RSS, который часто отдаёт пустое, есть fallback на официальный API (`export.arxiv.org/api/query`).
## Панель и команды
```
python -m omni serve --port 8077 # веб-панель + JSON API (без сборки, без npm)
python -m omni feed --limit 10 # обход всего реестра
python -m omni doctor --fix # проверить источники и подобрать рабочие фиды
python -m omni digest --out data/digest.md
```
Панель — две вкладки:
1. **лента** — счётчики (записей, с ценой, прогонов, источников, включённых), поиск по базе, фильтр по категориям, кнопка «собрать ленту» с прогрессом и разбивкой fetched/new/dup/empty.
2. **источники** — менеджер реестра:
- таблица всех 589 источников: переключатель вкл/выкл, категория, тип, url, статус (жив / мёртв / не проверен), число записей;
- фильтр по имени/url и по категории;
- **подключить источник** — форма (имя, url, категория): тип и адаптер определяются по url автоматически (`/rss` → rss, `.json`/`/api/` → generic_json, `github.com/org` → github_org, `t.me/s/` → tg_web), запись живёт в SQLite и сразу участвует в обходах;
- **проверить всё / проверить категорию** — фоновой джоб: реальный фетч каждого источника, запись `status/items/note/checked`, прогресс `done/total, живых/мёртвых`;
- **вкл все / выкл все** — массово по текущему фильтру;
- удаление своих источников (реестровые только выключаются).
Выключенный источник не дёргается ни панелью, ни `omni feed`, ни `omni doctor` — фильтр применяется в `sources.pick()`.
API: `GET /api/stats`, `GET /api/items?category=&q=&limit=&offset=`, `GET /api/sources?category=&q=`,
`POST /api/sources/toggle {name,enabled}`, `POST /api/sources/add {name,category,url}`,
`POST /api/sources/remove {name}`, `POST /api/sources/check {name|names|category|all}`,
`POST /api/feed {category,limit}`, `GET /api/job/<id>`.
Состояние источников — таблицы `source_flags` и `source_custom` в той же SQLite (`data/omni.sqlite3`).
## Как устроено
- `omni/net.py` — лестница транспорта: httpx → curl_cffi (подмена TLS-фингерпринта) → прокси из env. Троттлинг по хосту, лимит байт, пометка блокировок.
- `omni/model.py` — единая схема записи: провайдер, тип, url, заголовок, текст, автор, дата, теги, цена, счёт, simhash.
- `omni/filter.py` — релевантность: запрос должен быть покрыт текстом (≥60% терминов) и хотя бы один термин — в заголовке. Для русского сравнивает по 5-символьному префиксу, иначе морфология убивает совпадения.
- `omni/store.py` — SQLite WAL + FTS5, таблицы `items`, `bands`, `runs`. Дедуп: simhash по шинглам, сравнение по Хэммингу ≤3 по бакетам.
- `omni/rank.py` — вес провайдера, свежесть, наличие цены, вовлечение.
- `omni/providers/` — по файлу на семейство источников, реестр в `__init__.py`.
## Реальные прогоны
```
python -m omni search "scraping twitter without api" --providers reddit,forums,ddg,bing
bing 10 ok | ddg 10 ok | forums 10 ok | reddit 8 ok
собрано 38, новых 31, дублей 7
python -m omni fanout # 8 тем из themes.txt
итого новых 200, дублей 5
python -m omni stats
записей 266 | прогонов 56 (ok 37)
ddg=93 bing=85 forums=56 reddit=32
```
## Ограничения
- Reddit напрямую с серверных IP отдаёт 403 — используется архив pullpush; свежие посты (последние часы) в архиве могут отсутствовать.
- X/Twitter без токена: доступны только публичные встраивания и таймлайн профиля, полноценного полнотекстового поиска нет.
- mojeek отдаёт пустую страницу при агрессивном троттлинге — провайдер помечается, остальные работают.
- `cards` не обходит защиту от парсинга: если страница рендерится JS, разметки в html не будет.
## Лицензия
MIT.
## Абузы, авто-добавление и Telegram-бот
- **абузы**: категория `abuse` — 31 живая площадка (XenForo/Discourse/Telegram/RSS), включая свои каналы, классификатор `omni/abuse.py` раскладывает записи по тегам `ключи / промо / триалы / сливы / софт / продажа / новости`. В панели — отдельная вкладка (`?view=abuse`), в боте — `/abuse [тег]`.
- **авто-добавление**: `omni/discover.py` ищет фиды на уже подключённых хостах и каталогах, проверяет их теми же адаптерами и сохраняет только те, что реально отдали записи. В панели — кнопка «авто-добавление», в API — `POST /api/discover?hosts=40&add=25`.
- **новости**: любые RSS/Atom/JSON-ленты (редакции, релизы, сообщества) подключаются как обычный источник или через `/add <url>` в боте — отдельной схемы не требуется.
### Telegram-бот
```bash
set OMNI_BOT_TOKEN=<токен BotFather>
set OMNI_BOT_ALLOW=<твой numeric id>
python -m omni.bot
```
Команды: `/new [N]`, `/abuse [тег]`, `/find <слово>`, `/src <слово>`, `/run <категория>`, `/add <url>`, `/stats`. Бот работает на той же базе и том же реестре, что панель; отвечает только id из `OMNI_BOT_ALLOW`.
## Что нужно подключить
1. **Python 3.11+** и зависимости: `pip install -r requirements.txt` (httpx, curl_cffi, bs4, lxml). Больше ничего не обязательно — база создаётся сама в `data/omni.sqlite3`.
2. **Ни одного ключа не нужно.** Reddit (архив), форумы (Discourse/XenForo/веб-Telegram), HN, arXiv, GitHub, HF, поисковики работают без регистрации. Платные search-API (`TAVILY_API_KEY`, `EXA_API_KEY`, `YOU_API_KEY`, `FIRECRAWL_API_KEY`) подхватываются из env, если они есть: с ними больше покрытие, без них проект полностью рабочий.
3. **Свои источники**: кнопка «авто-добавление» в панели, `POST /api/discover`, `/auto` в боте или `python -m omni add <url>` — адрес проверяется реальным запросом и сохраняется только если отдал записи.
4. **Свой бот**: токен BotFather в `OMNI_BOT_TOKEN`, свой numeric id в `OMNI_BOT_OWNERS`, бота админом канала и `/sub @канал`.
## Проект обновляется
Проект живой: реестр источников, адаптеры и классификатор абузов правятся по мере того, как площадки ломают разметку. Обновление:
```bash
git pull
pip install -r requirements.txt
python -m omni serve --port 8077 # панель
python -m omni.bot # бот, если нужен
```
База в `data/` не перезаписывается — источники, здоровье и подписки остаются на месте. Ближайшие шаги: отдельная новостная лента с группировкой по сюжетам, скоринг абузов по свежести и частоте площадки, экспорт подборки в канал по расписанию.