feat(tg): реальные абузы из Telegram без сессии — адаптер tg_web переписан (служебное/пустыши отсекаются, заголовок из тела, порог 12/8 для leak-каналов), 19 живых каналов из 87 проверенных, сигнал абуза в score (+до 1.8), tools/tg_discover.py, tools/fixtg.py, tools/purge_tg_junk.py, tools/rescore.py; реестр 869, база 7295 (ab_ 3135, tg_ 374); тесты 19
This commit is contained in:
78
tools/tg_discover.py
Normal file
78
tools/tg_discover.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""Разведка публичных Telegram-каналов под абузы: t.me/s без сессии и ключей.
|
||||
|
||||
python tools/tg_discover.py name1,name2,... # проверить и показать
|
||||
python tools/tg_discover.py --file data/tg_cand.txt # список из файла
|
||||
python tools/tg_discover.py ... --min 3 # печатать только годные
|
||||
|
||||
Для каждого канала: HTTP-статус, сколько постов даёт парсер (после отсева
|
||||
служебного и пустышей) и сколько из них новые для базы.
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
|
||||
from omni import feeds, sources, store # noqa: E402
|
||||
|
||||
|
||||
def candidates(argv):
|
||||
"""Позиционные аргументы = имена/списки через запятую; --file/--min пропускаем."""
|
||||
names = []
|
||||
skip_next = False
|
||||
for a in argv:
|
||||
if skip_next:
|
||||
skip_next = False
|
||||
continue
|
||||
if a in ("--file", "--min"):
|
||||
skip_next = True
|
||||
continue
|
||||
if a.startswith("--"):
|
||||
continue
|
||||
names += [x.strip() for x in a.split(",") if x.strip()]
|
||||
if "--file" in argv:
|
||||
p = Path(argv[argv.index("--file") + 1])
|
||||
names += [x.strip() for x in p.read_text(encoding="utf-8").splitlines() if x.strip()]
|
||||
seen, out = set(), []
|
||||
for n in names:
|
||||
k = n.lower().lstrip("@")
|
||||
if k and k not in seen:
|
||||
seen.add(k)
|
||||
out.append(n.lstrip("@"))
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
min_items = 1
|
||||
if "--min" in args:
|
||||
min_items = int(args[args.index("--min") + 1])
|
||||
todo = candidates(args)
|
||||
print(f"кандидатов {len(todo)}")
|
||||
good = []
|
||||
for name in todo:
|
||||
src = sources.Source("probe_" + name.lower(), "abuse", "html",
|
||||
f"https://t.me/s/{name}", "tg_web", ("abuse",), 25, "", {})
|
||||
try:
|
||||
items = feeds.fetch(src)
|
||||
except Exception as e:
|
||||
print(f" {name:24} ошибка: {type(e).__name__}")
|
||||
continue
|
||||
c = store.conn()
|
||||
urls = {r[0] for r in c.execute("SELECT url FROM items WHERE source=?", (src.name,))}
|
||||
c.close()
|
||||
fresh = sum(1 for it in items if it.url not in urls)
|
||||
mark = ""
|
||||
if fresh >= min_items and items:
|
||||
good.append((name, len(items), fresh))
|
||||
mark = " <-- ГОДЕН"
|
||||
print(f" {name:24} постов {len(items):>3} новых {fresh:>3}{mark}")
|
||||
print(f"\nгодных каналов: {len(good)}")
|
||||
for name, n, f in sorted(good, key=lambda x: -x[1]):
|
||||
print(f" {name:24} постов {n:>3} новых {f}")
|
||||
if good:
|
||||
Path("data/tg_good.txt").write_text("\n".join(g[0] for g in good), encoding="utf-8")
|
||||
print("список: data/tg_good.txt")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user