feat: многопоточный парсинг + forum survey

- Throttle: Thread-safe координация задержек
- BanDetector: автоопределение бана
- fetch: thread-local сессии вместо глобальной
- run: ThreadPoolExecutor + диапазоны страниц + мерж
- output/state: поддержка worker-папок и merge_states()
- __main__: --workers, --no-delay, --no-ban-test
- VWTS/forums-survey.md: обзор 20+ автофорумов
This commit is contained in:
2026-06-04 10:48:57 +03:00
parent 22ca83adf8
commit c3211f0602
8 changed files with 361 additions and 93 deletions
+10 -3
View File
@@ -2,14 +2,21 @@
import json, logging
from datetime import datetime
from pathlib import Path
from .config import TOPICS_PER_FILE, OUTPUT_DIR
log = logging.getLogger(__name__)
def save_topic(section_slug: str, section_name: str, topic: dict,
posts: list, tags: list, state: dict):
"""Записать тему в part_XXXX.jsonl. Ротирует файл каждые N тем."""
posts: list, tags: list, state: dict,
worker_dir: Path = None):
"""Записать тему в part_XXXX.jsonl. Ротирует файл каждые N тем.
Args:
worker_dir: если задано — писать в эту папку (для многопоточности),
иначе в OUTPUT_DIR / section_slug
"""
st = state
# ротация
@@ -27,7 +34,7 @@ def save_topic(section_slug: str, section_name: str, topic: dict,
"scraped_at": datetime.now().isoformat(),
}
d = OUTPUT_DIR / section_slug
d = worker_dir if worker_dir else (OUTPUT_DIR / section_slug)
d.mkdir(parents=True, exist_ok=True)
fpath = d / f"part_{st['file_index']:04d}.jsonl"