Skip to main content
Use scraper_manage to read existing scraper code or save new and updated scraper code. It is the primary tool for authoring and versioning the Python scraper classes that Soria uses to discover and download files from data sources.

Parameters

string
required
Unique name for the scraper (e.g., kaufman_hall). Used to identify the scraper across all tools.
boolean
When true, returns the existing scraper code and metadata for scraper_name.
object
A dict with the scraper code and target URL to save. Required keys:
  • code — the Python source code implementing the scraper class
  • url — the target URL the scraper will run against
string
The workspace to associate the scraper with. Required whenever save includes code.

Scraper interface

Every scraper is a Python class that extends SimpleScraper and implements a single method: discover_files(). The base class handles all downloading — your job is to return a list of file metadata dicts.
The class name must follow the pattern {ScraperName}Scraper — for example, a scraper named kaufman_hall should define a class called KaufmanHallScraper.

discover_files() return format

Each dict in the returned list must include all four keys: Date format: Dates must be normalized to ISO format. Non-ISO dates are rejected at discovery time.

Capability tiers

Choose the simplest approach that works for your data source. More powerful tiers are slower and more expensive.

Tier 1 — Direct HTTP (get_html() / get_json())

The default and preferred approach. Fast, cheap, and reliable. Works for any site that serves static HTML or a JSON API.

Tier 2 — AI-driven browser automation (browser_task())

Use when the site is dynamic or JS-heavy and you do not want to write selectors by hand. browser_task() sends a natural-language instruction to an AI browser agent and returns structured data. It does not require needs_browser=True.

Tier 3 — Playwright (self.page)

Use when you need precise, deterministic browser interactions — clicking tabs, filling forms, waiting for specific DOM states. Requires needs_browser = True. The page starts on self.url with bot protection already cleared.
You can also set render_as_pdf = True to render HTML pages as PDFs via headless browser instead of downloading files directly. Use this for data sources that only publish HTML tables with no downloadable file.

Available in scraper namespace

These are available without any import inside a scraper class: Additional libraries available for import:
  • polars (use polars for DataFrames — pandas is not installed)
  • requests, lxml, beautifulsoup4, pdfplumber, html5lib, xmltodict, tenacity
  • curl_cffi, openpyxl, xlrd, chardet, python-dateutil
  • All standard library modules: csv, io, collections, itertools, hashlib, time, urllib, math, etc.

1

Create the workspace and scraper

This creates the scraper record and its associated workspace.
2

Fetch the target URL

Retrieve the source page to understand its structure before writing code.
3

Write the scraper code

Implement discover_files() using the appropriate capability tier. Start with Tier 1 (direct HTTP) and move up only if needed.
4

Test the scraper

Test mode runs discover_files() and returns the files found without downloading anything.
5

Save the scraper code

6

Run the scraper

Downloads all discovered files and triggers the processing pipeline.

Examples

Reading existing scraper code

The response includes the scraper’s URL, ID, and full Python source code.

Saving new scraper code