Skip to main content

Playwright wrapper обеспечивающий необходимый функционал для человеко-подобного парсинга сайтов

Project description

Human Requests

logo.webp

Asynchronous Playwright wrappers for browser-like HTTP scenarios, controlled render flow, and API autotest integration.

Tests Coverage Python PyPI - Package Version License BlackCode mypy Discord Telegram

Star us on GitHub | Read the Docs | Report a Bug

Features

  • Typed wrappers over Playwright primitives:
    • HumanBrowser
    • HumanContext
    • HumanPage
  • HumanPage.fetch(...): execute HTTP requests from page context and get structured FetchResponse.
  • HumanPage.goto_render(...): render already available response payloads without duplicate upstream request.
  • Storage helpers:
    • HumanContext.local_storage() for full context snapshot
    • HumanPage.local_storage() for current page origin
    • HumanPage.cookies() convenience alias
  • Fingerprint snapshot collection: HumanContext.fingerprint(...).
  • Built-in pytest autotest plugin for API clients (@autotest, hooks, params, dependencies).

Installation

Base package:

pip install human-requests
playwright install chromium

Optional autotest addon dependencies:

pip install human-requests[autotest] pytest pytest-anyio pytest-jsonschema-snapshot pytest-subtests

If you run with Camoufox, install it separately:

pip install camoufox
camoufox fetch

Quick Start

Wrap a Playwright browser

import asyncio
from playwright.async_api import async_playwright

from human_requests import HumanBrowser


async def main() -> None:
    async with async_playwright() as p:
        pw_browser = await p.chromium.launch(headless=True)
        browser = HumanBrowser.replace(pw_browser)

        ctx = await browser.new_context()
        page = await ctx.new_page()

        await page.goto("https://httpbin.org/html", wait_until="domcontentloaded")
        print(page.url)

        await browser.close()


asyncio.run(main())

Direct request in page context (fetch)

resp = await page.fetch("https://httpbin.org/json")
print(resp.status_code)
print(resp.json())

Render previously fetched response (goto_render)

challenge = await page.fetch("https://example.com/challenge")
await page.goto_render(challenge, wait_until="networkidle")

Auto Screenshot on Handler Failure

If you want a screenshot to be taken when errors like playwright.Error (including timeouts) occur, you can set page.on_error_screenshot_path = "screenshot.png" (this setting is page-specific; by default, screenshots are disabled).

State helpers

cookies = await page.cookies()
context_storage = await ctx.local_storage()
page_storage = await page.local_storage()
print(len(cookies), context_storage.keys(), page_storage.keys())

Fingerprint snapshot

fingerprint = await ctx.fingerprint(origin="https://example.com")
print(fingerprint.user_agent)
print(fingerprint.browser_name, fingerprint.browser_version)

API Tree Boilerplate Helper

To avoid repetitive _parent and __post_init__ wiring in SDK-style clients (like fixprice_api / perekrestok_api), use:

  • ApiChild[ParentType]
  • ApiParent
  • api_child_field(...)
from dataclasses import dataclass
from human_requests import ApiChild, ApiParent, api_child_field


class ClassCatalog(ApiChild["ShopApi"]):
    async def tree(self):
        ...


class ClassGeolocation(ApiChild["ShopApi"]):
    async def cities_list(self):
        ...


@dataclass
class ShopApi(ApiParent):
    Catalog: ClassCatalog = api_child_field(ClassCatalog)
    Geolocation: ClassGeolocation = api_child_field(ClassGeolocation)

ApiParent initializes all api_child_field(...) values in __post_init__ automatically, so manual assignments are no longer needed.

Nested chains are supported as well (Root -> Child -> Child):

@dataclass
class BranchApi(ApiChild["RootApi"], ApiParent):
    Catalog: ClassCatalog = api_child_field(ClassCatalog)

@dataclass
class RootApi(ApiParent):
    Branch: BranchApi = api_child_field(BranchApi)

API Autotest Addon (pytest)

human-requests ships with a pytest plugin that can auto-run API methods marked with @autotest and validate payloads via schemashot from pytest-jsonschema-snapshot. With pytest-subtests, each discovered @autotest method and @autotest_data provider is shown as a separate subtest inside test_autotest_api_methods.

Minimal pytest.ini:

[pytest]
anyio_mode = auto
autotest_start_class = your_package.StartClass
autotest_typecheck = warn

autotest_typecheck modes:

  • off (default): no runtime type checks for params provider arguments
  • warn: emit RuntimeWarning on annotation mismatch
  • strict: fail test case with TypeError on mismatch

Minimal fixtures:

import pytest
from your_package import StartClass


@pytest.fixture(scope="session")
def anyio_backend() -> str:
    return "asyncio"


@pytest.fixture(scope="session")
async def api() -> StartClass:
    async with StartClass() as client:
        yield client

Business code only marks methods:

from human_requests import autotest


class Catalog:
    @autotest
    async def tree(self):
        ...

Test layer adds hooks and params:

from human_requests import autotest_depends_on, autotest_hook, autotest_params
from human_requests.autotest import AutotestCallContext, AutotestContext


@autotest_hook(target=Catalog.tree)
def _capture_category(_resp, data, ctx: AutotestContext) -> None:
    ctx.state["category_id"] = data["items"][0]["id"]


@autotest_depends_on(Catalog.tree)
@autotest_params(target=Catalog.feed)
def _feed_params(ctx: AutotestCallContext) -> dict[str, int]:
    return {"category_id": ctx.state["category_id"]}

Parent-specific registration is supported:

@autotest_hook(target=Child.method, parent=ParentA)
def _only_for_parent_a(_resp, data, ctx):
    ...

For a complete guide, see docs/source/autotest.rst.

Development

Setup:

git clone https://github.com/Miskler/human-requests.git
cd human-requests
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e .

Commands:

pytest
make lint
make type-check
make format
make docs

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

human_requests-0.1.8.tar.gz (51.1 kB view details)

Uploaded Source

Built Distribution

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

human_requests-0.1.8-py3-none-any.whl (44.7 kB view details)

Uploaded Python 3

File details

Details for the file human_requests-0.1.8.tar.gz.

File metadata

  • Download URL: human_requests-0.1.8.tar.gz
  • Upload date:
  • Size: 51.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for human_requests-0.1.8.tar.gz
Algorithm Hash digest
SHA256 b122ade856a56e639a65376081711b1503a51c655073ae09108833792c59a301
MD5 1a2b4a0fb211d3ddc8d691483ea7f844
BLAKE2b-256 c1c25682f0edc75f8a758d90fef1f5164f86d499438432780621a85b842f84c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for human_requests-0.1.8.tar.gz:

Publisher: release.yml on Miskler/human-requests

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

File details

Details for the file human_requests-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: human_requests-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 44.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for human_requests-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 9659499531f2289e04f168f3b0f50dc87e1082c29abc2fd024da66ba9c9fd0e3
MD5 76504a04fb49eb61db8006c02f3a2016
BLAKE2b-256 71fe18d084610db13dfd55be64090bd213ec4ccd5660afe7579dda5a1ab926bf

See more details on using hashes here.

Provenance

The following attestation bundles were made for human_requests-0.1.8-py3-none-any.whl:

Publisher: release.yml on Miskler/human-requests

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