The Problem

Extracting structured data from arbitrary web pages usually means writing per-site selectors that break when the target changes. CyberScraper-2077 replaces that with an LLM that reads the page and returns the fields you asked for, in the format you specify.

What This Does

A Streamlit app (app/streamlit_web_scraper_chat.py) that takes a URL and a prompt, scrapes the page via Playwright or Tor, and sends the content to OpenAI, Gemini, or a local Ollama model for extraction. Results export as JSON, CSV, HTML, SQL, or Excel, and can upload to Google Sheets via src/utils/google_sheets_utils.py.

The scraper layer lives in src/scrapers/: base_scraper.py defines the abstract contract, playwright_scraper.py handles browser automation with stealth settings, and tor/ provides onion routing via tor_manager.py and tor_scraper.py. Extraction logic sits in src/web_extractor.py, which handles URL normalization, content fetching, and token counting.

How It Is Wired

Execution starts at main in main.py:415, which reaches 81 functions. The UI layer calls process_message, which routes through process_with_progress → process_query → _chat_without_content, ending in a model inference call (self.model.generate). The Ollama path is main → list_ollama_models → list_models, which makes a network call via session.get.

The hub is src/web_extractor.py (Ca 2, Ce 8, instability 0.8) — 25 functions that everything routes through. src/utils/error_handler.py is the stable core (Ca 7, Ce 0, instability 0): seven modules import it, it imports nothing. _extract_json_from_markdown is called from 6 places, so changing its signature breaks the most code. src/scrapers/playwright_scraper.py carries the heaviest load: 27 functions, 694 lines, and it launches an external browser process.

No import cycles detected, which keeps refactoring tractable. The main risk is playwright_scraper.py — oversized, deeply nested (indentation depth 8), and called from 3 other files.

How To Use It

git clone https://github.com/moses-y/CyberScraper-2077.git
cd CyberScraper-2077
virtualenv venv && source venv/bin/activate
pip install -r requirements.txt
playwright install
export OPENAI_API_KEY="your-api-key-here"
export GOOGLE_API_KEY="your-api-key-here"
python main.py

Requires Python 3.10+. For Ollama, install Ollama locally and select a model in the UI. A Dockerfile exists for containerized runs, but the README notes the captcha-bypass feature doesn't work under Docker.

Real-World Use

A data analyst scraping a product page: paste the URL, ask for "price, name, and availability," and get a CSV back. The Tor path (src/scrapers/tor/) handles .onion sites with automatic circuit setup, so the same workflow extends to sources that block datacenter IPs. The caching layer (LRU + custom dict) reduces redundant LLM calls for repeated queries.

Code Health & Issues

Static analysis (measured, not opinion) found 11 issues: 2 high, 9 medium. High: deep nesting (depth 8) in src/ollama_models.py, src/scrapers/playwright_scraper.py, and src/web_extractor.py. Medium: oversized playwright_scraper.py (694 lines), broad exception handling in src/scrapers/tor/utils.py and main.py, duplicated blocks across base_scraper.py and playwright_scraper.py, and high branching density in src/web_extractor.py (112 branch points over 393 lines).

SDLC gaps: no test files, no CI, no lockfile (requirements.txt unpinned), Dockerfile uses a mutable python:3.12-slim-bookworm tag and runs as root, and no Dependabot. Any change ships with zero regression signal.

The Bottom Line

Functionally interesting — LLM-driven extraction beats brittle selectors, and the Tor support is a differentiator. But it's a fork with no tests, no CI, and a 694-line core module that needs splitting before it's safe to extend. Use it for prototyping scraping workflows, not for production data pipelines.