Skip to main content

gdzapi

Universal asynchronous and synchronous Python client for 7 GDZ providers with declarative engine and Pydantic v2 validation.

PyPI version Python Versions License: MIT Tests

Quick Start · 7 Providers · Features · Usage Guide · Architecture · License


Why gdzapi

Most school scraping tools are fragmented across dozens of fragile files, lack asynchronous capability, crash on repeated awaits, or fail to handle modern SPA/lazy-loading structures.

gdzapi unifies 7 major school solution portals under a single, declarative architecture. Instead of maintaining separate scrapers for each website, all providers are driven by a single engine with non-blocking initialization, strict timeouts, protocol normalization, and Pydantic v2 models.


Supported Providers

Provider Alias Sync Method Async Method Content Type Status
GDZ.ru "gdz" Client.gdz() AsyncClient.gdz() Images Stable
Euroki.org "euroki" Client.euroki() AsyncClient.euroki() Images (lazy) Stable
MegaResheba.ru "megaresheba" Client.megaresheba() AsyncClient.megaresheba() Images Stable
GDZ-Raketa.ru "raketa" Client.raketa() AsyncClient.raketa() Text, MathJax & Images Stable
Reshak.ru "reshak" Client.reshak() AsyncClient.reshak() Images Stable
Pomogalka.me "pomogalka" Client.pomogalka() AsyncClient.pomogalka() Images Stable
Resh.Skysmart.ru "skysmart" Client.skysmart() AsyncClient.skysmart() Steps & Images Stable (SSR)

Features

  • Single Unified Engine: Zero code duplication. Switch providers with a string: Client("reshak") or Client.reshak().
  • Dual Mode (Sync & Async): Native asynchronous aiohttp engine alongside a robust synchronous requests client.
  • Rich Solution Models: Solution models support image_src, text, and html for sites with formulaic or written step-by-step explanations.
  • Safe Lazy Navigation: Await properties (subject.books, book.pages, page.solutions) as many times as you like without cannot reuse already awaited coroutine crashes.
  • Pydantic v2 Models: Data transfer objects (Class, Subject, Book, Page, Solution) with strict typing.
  • Fast Search: Server-side instant search on supported providers (e.g. Euroki) and concurrent catalog scanning on others.
  • Resilient Networking: Explicit 15s default timeouts, modern User-Agent handling (including SSR emulation for SPAs), and protocol-relative URL normalization (//...https://...).

Installation

pip install gdzapi --upgrade

From source for development:

git clone https://github.com/maybewewill/gdzAPI.git
cd gdzAPI
pip install -e ".[dev]"

Quick Start

Asynchronous (Recommended)

import asyncio
from gdzapi import AsyncClient, Provider

async def main():
    # Connect to any provider: "gdz", "reshak", "raketa", "euroki", etc.
    async with AsyncClient(Provider.RESHAK, timeout=15) as client:
        subjects = await client.get_subjects()
        math = next(s for s in subjects if "математика" in s.name.lower())

        books = await math.books
        print(f"Book: {books[0].name}")

        pages = await books[0].pages
        if pages:
            solutions = await pages[0].solutions
            print(f"Solution image: {solutions[0].image_src}")

if __name__ == "__main__":
    asyncio.run(main())

Synchronous

from gdzapi import Client

# Using provider factory method
with Client.pomogalka(timeout=15) as client:
    for cls in client.classes:
        if cls.id == 5:
            print(f"Grade: {cls.name}")
            for subj in cls.subjects:
                books = subj.books
                if books:
                    print(f"Book: {books[0].name}")
                    pages = books[0].pages
                    if pages:
                        print(f"Page 1 solution: {pages[0].solutions[0].image_src}")
                break
            break

Usage Guide

1. GDZ-Raketa (Text & Math Solutions)

gdz-raketa.ru provides full text answers with formulas in addition to images:

from gdzapi import Client

client = Client.raketa()
classes = client.classes
book = classes[4].subjects[0].books[0]  # 5th grade, 1st subject, 1st book

page = book.pages[0]
solution = page.solutions[0]

print("Text explanation:", solution.text)
if solution.image_src:
    print("Illustration:", solution.image_src)

2. Reshak.ru

from gdzapi import Client

client = Client.reshak()
subjects = client.subjects

for subj in subjects:
    if "математика" in subj.name.lower():
        for book in subj.books:
            print(f"{book.name} -> {book.url}")
            pages = book.pages
            if pages:
                print(f"First exercise solution: {pages[0].solutions[0].image_src}")
            break
        break

3. Euroki (Fast Search)

from gdzapi import Client

client = Client.euroki()
books = client.search_books("Геометрия 8 класс")

for book in books:
    print(f"Found: {book.name}")
    pages = book.pages
    if pages:
        solutions = pages[0].solutions
        print(f"Image: {solutions[0].image_src}")
    break

4. Resh.Skysmart.ru

from gdzapi import Client

client = Client.skysmart()
classes = client.classes
print(f"Loaded {len(classes)} grades from Skysmart")

5. Error Handling

from gdzapi import Client, NetworkError, ParsingError

client = Client.gdz(timeout=10)

try:
    books = client.get_books("/non-existent-subject")
except NetworkError as e:
    print(f"Connection or HTTP status error for {e.url}: {e}")
except ParsingError as e:
    print(f"Parsing error: {e}")

Architecture

gdzapi/
├── __init__.py      # Unified public API and provider factory shortcuts
├── client.py        # Single Sync & Async execution engine (Client, AsyncClient)
├── providers.py     # Declarative registry defining all 7 providers
├── models.py        # Pydantic v2 models (Class, Subject, Book, Page, Solution, AwaitableList)
├── exceptions.py    # GDZError, NetworkError, ParsingError, NotFoundError
└── utils.py         # URL normalization, DOM parsers, HTTP headers

Adding a New Provider in 20 Lines

Because gdzapi uses a declarative provider engine, you do not need to create new files or rewrite sync/async boilerplate to add an 8th provider. Simply define a ProviderSpec in gdzapi/providers.py:

MY_SPEC = ProviderSpec(
    name="myprovider",
    base_url="https://example.com",
    display_name="My Provider",
    extract_subjects=_my_subjects,
    extract_books=_my_books,
    extract_pages=_my_pages,
    extract_solutions=_my_solutions,
)

The unified Client and AsyncClient automatically provide sync, async, caching, and lazy navigation support out of the box.


Testing

The test suite includes 21 isolated offline unit tests and 8 live integration tests across all 7 providers:

# Run unit tests (offline, instantaneous)
pytest -v -m "not live"

# Run all tests including live network requests
pytest -v

License

gdzapi is distributed under the terms of the MIT license.

Download files

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

Source Distribution

gdzapi-1.0.0.tar.gz (22.3 kB view details)

Uploaded Source

Built Distribution

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

gdzapi-1.0.0-py3-none-any.whl (15.8 kB view details)

Uploaded Python 3

File details

Details for the file gdzapi-1.0.0.tar.gz.

File metadata

  • Download URL: gdzapi-1.0.0.tar.gz
  • Upload date:
  • Size: 22.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for gdzapi-1.0.0.tar.gz
Algorithm Hash digest
SHA256 6ab597d5c7110b0e4a9de3a248f56a229a5631ff8af1f04128e6696598be0179
MD5 5c6e21c8c0fb7d507c1c8477ee4fd2ba
BLAKE2b-256 9ad545c3bcb4752c661da81d98b26a5e11c523b882069cac3fc91465219c5177

See more details on using hashes here.

File details

Details for the file gdzapi-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: gdzapi-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 15.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for gdzapi-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 32e91d4e8a14d80dd8511683f4af82d82e388accd099855f01e0b8a1f94d70f2
MD5 2096eb9e62ee685c6dbcc29c23acd486
BLAKE2b-256 90f9a65df34cec3689dbbfa220e0d2a045426ba0540811b07528e468095519af

See more details on using hashes here.

Release history Release notifications | RSS feed

1.1.0

2 files

This release

1.0.0 This release

2 files

0.2.0

1 file

0.1.14

1 file

0.1.13

1 file

0.1.11

1 file

0.1.9

1 file

0.1.8

1 file

0.1.7

1 file

0.1.6

1 file

0.1.5

1 file

0.1.4

1 file

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page