web2json
web2json converts web content into structured JSON using a local Ollama server. It exposes a simple command line interface.
This repository began from code by abdo-Mansour and was adapted for use at the NOAA Global Systems Laboratory.
Installation
- Clone the repository.
- Install dependencies:
pip install -r requirements.txt
- Install the package in editable mode so the
web2jsoncommand is available:pip install -e .
- Optionally set
OLLAMA_HOST(orOLLAMA_BASE_URL) andOLLAMA_MODELto point to your Ollama instance and model. The dev container defaults togemma3:12b. - Set
OPENAI_API_KEYto use the OpenAI API instead of the local Ollama server. When this variable is present, theOLLAMA_*settings are ignored. UseOPENAI_MODELto choose a model (defaultgpt-3.5-turbo). IfOPENAI_API_KEYis left undefined in the dev container, it may be set to a placeholder value like${{ secrets.OPENAI_API_KEY }}; this is ignored and the local Ollama server will be used.
Command line usage
Run the CLI module with the content to process and your schema definition. The tool can also crawl multiple pages from a starting URL:
python -m web2json.cli --schema SCHEMA [--url] [--crawl] [--max_pages N] [--output FILE] CONTENT
CONTENTcan be a URL or raw text.--urltells the tool to treatCONTENTas a URL.--schemaaccepts a JSON Schema definition directly or the path to a JSON file containing it.- When loading a schema from a file, an optional
promptstring may be included to append additional instructions for the language model. - The file may also contain a
postprocesssection withlink_patternsthat map field names to regular expressions and optionalcss_selectorsfor extracting values using CSS paths. These settings help fill in missing data based on the cleaned HTML. --crawltreats the content as a starting URL and processes each discovered page.--max_pageslimits how many pages are crawled when using--crawl(default: 10).--debugprints the preprocessed content and other intermediate information to stderr.--outputwrites the resulting JSON toFILEinstead of only printing to stdout.- When a URL is provided, relative links in the page are converted to absolute URLs so they can be extracted correctly. The page URL itself is assigned to the
urlfield if that key exists in the schema. Missing URLs can be filled using regex patterns in the post-processor when provided. - Character encoding is determined automatically when downloading pages so accented characters are preserved correctly.
- If your schema defines a
contentfield, the CLI removes common header, footer and navigation sections (including the official U.S. government banner) so that field only contains the main page body.
Example:
python -m web2json.cli https://example.com --url --schema '{"properties": {"title": {"type": "string", "description": "Page title"}}}'
You can place the schema in a file instead. For example schema.json:
{
"properties": {"title": {"type": "string"}},
"postprocess": {
"link_patterns": {"ftp_download": "(ftp://\\S+)"},
"css_selectors": {"preview": {"selector": "a.preview", "attr": "href"}}
}
}
Run the CLI using that file:
python -m web2json.cli https://example.com --url --schema schema.json
To crawl and process multiple pages under https://example.com/docs/:
python -m web2json.cli https://example.com/docs/ --crawl --schema '{"properties": {"title": {"type": "string"}}}'
The extracted JSON is printed to standard output. Unicode characters are
preserved so accent marks appear correctly. Any schema validation errors are
reported to standard error. When --debug is used, intermediate output such as the cleaned HTML is also sent to standard error.
Library usage
The pipeline components are exposed as Python classes so you can build custom workflows.
from web2json.cli import parse_schema_input
from web2json.preprocessor import BasicPreprocessor
from web2json.postprocessor import PostProcessor
from web2json.pipeline import Pipeline
from web2json.ai_extractor import OllamaLLMClient
schema_json = '{"properties": {"title": {"type": "string"}, "content": {"type": "string"}}}'
schema = parse_schema_input(schema_json)
# Exclude header, footer and navigation markup when cleaning HTML
pre = BasicPreprocessor(config={"remove_boilerplate": True})
llm = OllamaLLMClient()
post = PostProcessor()
pipe = Pipeline(pre, llm, post)
result = pipe.run("<h1>Title</h1>", False, schema)
Regex link_patterns and css_selectors can be supplied for special cases where the language model misses links or other values.
The post-processor also applies simple heuristics to recover categories, keywords, and notable features directly from the cleaned HTML. These values replace the model output when they differ from the page content.
Code overview
- Preprocessor - cleans and normalizes HTML or text input.
When
remove_boilerplateis enabled, common header, footer and navigation elements (like the U.S. government banner) are stripped before text extraction. The CLI turns this setting on automatically if your schema includes acontentfield. - AIExtractor - sends a prompt to the LLM and returns the raw JSON text.
- PostProcessor - repairs malformed JSON and adds missing URLs.
These pieces are wired together by the Pipeline class and driven by the CLI script.
Running tests
Install pytest and run the suite:
pip install -r requirements.txt
pip install pytest
pytest
Tests also run automatically through GitHub Actions on every push and pull request.
Dev container
The .devcontainer folder provides a configuration for
Dev Containers
and GitHub Codespaces. Open the project in Visual Studio Code and choose
Reopen in Container to automatically build the image and install the
dependencies listed in requirements.txt.
Environment variables like OPENAI_API_KEY, OLLAMA_BASE_URL,
and OLLAMA_MODEL are set through the remoteEnv section of
devcontainer.json. The repository is mounted inside the container at
/workspace/web2json and the site-config directory is available at
/workspace/site-config.
Additional tests
The test suite now covers the CLI utilities as well as core components.
Additional tests live under tests/ and exercise:
- The
AIExtractorprompt formatting logic. - Error handling in
PostProcessor.processwhen invalid JSON is returned. - The
_fetch_contentmethod inBasicPreprocessor. - run_pipeline success and error scenarios.
- Pipeline operation with a mocked LLM.
Metadata
Release files for web2json 0.0.13
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| web2json-0.0.13.tar.gz | 21.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| web2json-0.0.13-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 39.1 kB
Release files / web2json-0.0.13.tar.gz
| Download URL | web2json-0.0.13.tar.gz |
|---|---|
| Size | 21.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f324543b6f2d4c4abfc271f0ae0e4831c2286fa9ff94cfd8de94194f9dafbd68
|
|
BLAKE2b-256 checksum How to use checksums |
01e9d412950f00a8a2515013a7397d9cc3c9ca74e9209aa764af68b8c88fc634
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.8
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 27, 2025.
Transparency logRelease files / web2json-0.0.13-py3-none-any.whl
| Download URL | web2json-0.0.13-py3-none-any.whl |
|---|---|
| Size | 17.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8dfe4e777c34178467dc19e88062c44c53317fdf546a52326fc3229101fceca2
|
|
BLAKE2b-256 checksum How to use checksums |
c6f01f12bad9ae6b5872ae25b02d973ae40596822694c9a6865750cdd17824f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.8
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 27, 2025.
Transparency log