Skip to main content

A declarative HTML/XML extraction framework using lxml

Project description

pagemodel

tests publish PyPI - Version PyPI - Python Version


A declarative HTML/XML extraction framework built on lxml.

Features

  • Unified Field descriptor – handles text, attributes, JSON, fragments, and multiple values via a single class. CSS and XPath selectors are auto‑detected and pre‑compiled.
  • Type‑driven annotations – write title: str = "h1" and the library automatically picks the right converter (str, int, float, bool, dict, list, Pydantic models).
  • @fragment decorator – describe repeating blocks of HTML without leaving the page class.
  • @keyvalue decorator – turn a list of fragments into a dictionary with one line.
  • Built‑in Pydantic integration – validate JSON data and export directly to your models.
  • Streaming parser (StreamPage) for large XML files that cannot fit in memory.
  • Compact helpers Q, Sel, X for rapid field creation with pipeline support (| float, | str.strip).
  • Fast – selectors are compiled once, results are cached, and lxml does the heavy lifting in C.

Installation

pip install pagemodel
# or with extra dependencies
pip install pagemodel[all]

Python >=3.10 is required.

Quick Start

from pagemodel import BasePage, fragment

html = """<html><body>
    <h1>Catalog</h1>
    <div class="product">
        <span class="name">Pen</span>
        <span class="price" data-value="1.5"></span>
    </div>
    <div class="product">
        <span class="name">Paper</span>
        <span class="price" data-value="2.0"></span>
    </div>
</body></html>"""

class Page(BasePage):
    title: str = "h1"

    @fragment(".product", multiple=True)
    class Product:
        name: str   = ".name"
        price: float = ".price @data-value"

page = Page(html)
print(page.title)          # Catalog
for prod in page.Product:
    print(prod.name, prod.price)
print(page.export())       # full dictionary

Advanced usage

Explicit Field, JSON and Pydantic models

from pagemodel import BasePage, Field
from pydantic import BaseModel

class ProductModel(BaseModel):
    name: str
    price: float

class Page(BasePage):
    product: ProductModel = "script[type='application/json']"

page = Page('<script type="application/json">{"name":"Pen","price":1.5}</script>')
print(page.product.name)   # Pen
print(page.product.price)  # 1.5

Key‑value aggregation with @keyvalue

from pagemodel import BasePage, fragment, keyvalue

@keyvalue("Spec", key_field="label", value_field="val", export_name="specs")
class Page(BasePage):
    @fragment(".row", multiple=True)
    class Spec:
        label: str = ".key"
        val: str   = ".val"

page = Page("""<div class="row"><span class="key">Color</span><span class="val">Red</span></div>""")
print(page.export())   # {'specs': {'Color': 'Red'}}

Streaming large XML

from pagemodel import StreamPage, HtmlFragment, Field

class Item(HtmlFragment):
    name = Field("name")

xml = """<root><item><name>Alice</name></item><item><name>Bob</name></item></root>"""
stream = StreamPage(xml, tag_callback_map={"item": Item})
for entry in stream.iter_items("item"):
    print(entry)   # {'name': 'Alice'}   {'name': 'Bob'}

Documentation

Documentation

Running tests

uv run pytest

License

This project is licensed under the MIT License – see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pagemodel-0.2.0.tar.gz (29.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pagemodel-0.2.0-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

Details for the file pagemodel-0.2.0.tar.gz.

File metadata

  • Download URL: pagemodel-0.2.0.tar.gz
  • Upload date:
  • Size: 29.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pagemodel-0.2.0.tar.gz
Algorithm Hash digest
SHA256 85cc745a31141d7f7f2952efd6afe19627363c566c9d4af2e6eb4c87a3545adb
MD5 606ef9a5ceaac374c105c151ae097e01
BLAKE2b-256 040ed5210f2ab3d58600099eee8b9b773e4f5c335782d9d74ff096b035441f0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pagemodel-0.2.0.tar.gz:

Publisher: publish.yml on avalak/pagemodel

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pagemodel-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: pagemodel-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 21.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pagemodel-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8ef1e935abc5e0e8f8c2785e976473fca962e14112c4658666f661d5c1e27bc0
MD5 825cba461ebdba605ab3aca53ab16856
BLAKE2b-256 d120dd0eb52a74bbba959ffb6f3bffde7a359434a43eaf5bd2528f8b5ea5f526

See more details on using hashes here.

Provenance

The following attestation bundles were made for pagemodel-0.2.0-py3-none-any.whl:

Publisher: publish.yml on avalak/pagemodel

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page