← back to Paul Conrad Archive
scripts/crawl_all.py
49 lines
#!/usr/bin/env python3
"""Run every crawler (seed first), MAX_CONCURRENCY sources in parallel, then dedupe + exports + report.
python scripts/crawl_all.py # restartable: cached responses + checkpoints are reused
python scripts/crawl_all.py --fresh # rebuild data/conrad.db from scratch (HTTP cache is still reused)
python scripts/crawl_all.py --no-cache # re-fetch everything live
"""
import importlib, json, logging, subprocess, sys, pathlib
from concurrent.futures import ThreadPoolExecutor
ROOT = pathlib.Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "src"))
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(threadName)s %(message)s", stream=sys.stderr)
from conrad import config, db, dedupe, exports # noqa: E402
from conrad.crawlers import ORDER # noqa: E402
from conrad.crawlers.base import Http # noqa: E402
def run_one(name: str, use_cache: bool) -> dict:
mod = importlib.import_module(f"conrad.crawlers.{name}")
return mod.CRAWLER(conn=db.connect(), http=Http(use_cache=use_cache)).run()
def main() -> None:
use_cache = "--no-cache" not in sys.argv
if "--fresh" in sys.argv and config.DB_PATH.exists():
for suffix in ("", "-wal", "-shm"):
p = pathlib.Path(str(config.DB_PATH) + suffix)
if p.exists():
p.unlink()
conn = db.connect()
db.init_db(conn)
results = [run_one("seed_import", use_cache)]
# huntington first (live verification of the largest source), then the rest in parallel
results.append(run_one("huntington", use_cache))
rest = [n for n in ORDER if n not in ("seed_import", "huntington", "latimes", "denver_post")]
with ThreadPoolExecutor(max_workers=config.MAX_CONCURRENCY) as pool:
results += list(pool.map(lambda n: run_one(n, use_cache), rest))
results += [run_one(n, use_cache) for n in ("latimes", "denver_post")] # coverage computed after other sources
for r in results:
print(json.dumps(r))
print(json.dumps({"dedupe": dedupe.run(conn)}))
print(json.dumps({"exports": exports.export_all(conn)}))
subprocess.run([sys.executable, str(ROOT / "scripts/report.py")], check=True)
if __name__ == "__main__":
main()