### Run Web-Poet Example Script (Python)
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/tutorial.rst
This Python script demonstrates how to use the `web_poet.example.get_item` function to retrieve data using a defined page object. It requires installing the `requests` library and calls `consume_modules` to register page objects before fetching an item.
```python
from web_poet.rules import consume_modules
from web_poet.example import get_item
# Assuming Book and BookPage are defined in a module named 'my_pages'
consume_modules("my_pages")
item = await get_item("http://books.toscrape.com/", Book)
print(item)
```
--------------------------------
### Example Framework
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Functionality for the example framework.
```APIDOC
## Example Framework
### Description
Functionality related to the example framework.
### Functions
- `get_item()`
```
--------------------------------
### Install web-poet using pip
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/install.rst
This command installs the web-poet library from the Python Package Index (PyPI). Ensure you have pip installed and accessible in your environment.
```bash
pip install web-poet
```
--------------------------------
### Example Framework API
Source: https://web-poet.readthedocs.io/en/stable/_sources/api-reference.rst
Information about the example framework, intended for educational purposes and not for production use.
```APIDOC
## Example Framework API
### Description
The `web_poet.example` module provides a simplified, incomplete example of a web-poet framework. It is intended as support material for the tutorial and should not be used in production environments.
### Module
- `web_poet.example`: Contains example framework code.
```
--------------------------------
### Framework integration example (Python)
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/from-ground-up.rst
A conceptual example showing how a web-poet page object class (BookPage) would be used with an external framework to fetch and parse web content. The framework handles the downloading, and the page object handles the parsing.
```python
item = some_framework.get(url, BookPage)
```
--------------------------------
### Example Framework API
Source: https://web-poet.readthedocs.io/en/stable/api-reference
An example framework function for retrieving items from a URL using a page object.
```APIDOC
## POST /example/get_item
### Description
Returns an item built from the specified URL using a page object class from the default registry. This function is an example of a minimal, incomplete web-poet framework implementation, intended for use in the web-poet tutorial.
### Method
POST
### Endpoint
/example/get_item
### Parameters
#### Request Body
- **_url** (str) - Required - The URL to fetch the item from.
- **_item_cls** (type) - Required - The page object class to use for building the item.
- **_page_params** (dict[Any, Any] | None) - Optional - Additional parameters for the page object.
### Response
#### Success Response (200)
- **item** (Any) - The built item.
#### Response Example
```json
{
"item": { "title": "Example Page", "content": "This is an example."}
}
```
```
--------------------------------
### Example Framework Item Retrieval (Python)
Source: https://web-poet.readthedocs.io/en/stable/api-reference
A function from a simplified, incomplete example framework for web-poet, intended for tutorial support. It retrieves an item from a URL using a page object class from a default registry. This is not for production use.
```python
from typing import Any, Dict
def get_item(_url : str, _item_cls : type, *_ , _page_params : Dict[Any, Any] | None = None) -> Any:
"""Returns an item built from the specified URL using a page object class."""
# Implementation details would go here
pass
```
--------------------------------
### HTTP Response Handling in web_poet.example
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/example
This snippet demonstrates how to fetch an HTTP response and convert it into a web_poet HttpResponse object. It uses the requests library for making the HTTP GET request and extracts relevant information like URL, status code, content, and headers. This is a core part of fetching web page data within the example framework.
```python
from __future__ import annotations
from asyncio import run
from typing import Any
from warnings import warn
import andi
import requests
from . import default_registry
from .page_inputs import HttpClient, HttpResponse, PageParams
from .pages import ItemPage, is_injectable
from .utils import ensure_awaitable
warn(
(
"You should only be importing web_poet.example to follow the web-poet "
"tutorial, never as part of production code."
),
UserWarning,
stacklevel=2,
)
class _HttpClient:
async def get(self, url: str) -> HttpResponse:
return _get_http_response(url)
def _get_http_response(url: str) -> HttpResponse:
response = requests.get(url)
return HttpResponse(
response.url,
status=response.status_code,
body=response.content,
headers=response.headers,
)
```
--------------------------------
### Making HTTP Requests with HttpClient
Source: https://web-poet.readthedocs.io/en/stable/_sources/page-objects/additional-requests.rst
This snippet shows various ways to make HTTP requests using the HttpClient. It includes examples for GET, POST, and generic request methods, demonstrating how to pass URLs, bodies, and custom headers. It also mentions that methods can raise HttpError or return HttpResponse.
```python
http = HtpClient()
response = await http.get(url)
response = await http.post(url, body=b"...")
response = await http.request(url, method="...")
response = await http.execute(HttpRequest(url, method="..."))
```
```python
http.post(
url,
headers={"Content-Type": "application/json;charset=UTF-8"},
body=json.dumps({"foo": "bar"}).encode("utf-8"),
)
```
--------------------------------
### HttpClient Initialization and Request Execution in Python
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/page_inputs/client
Demonstrates the initialization of the HttpClient class, which can optionally take a custom request downloader. It also shows how to execute a request using the `request` method, which creates an HttpRequest object and handles the response, including status code validation. The `get` method is a convenience shortcut for making GET requests.
```python
from web_poet.page_inputs.client import HttpClient
# Initialize HttpClient with a custom downloader (optional)
client = HttpClient(request_downloader=my_downloader_function)
# Or use the default downloader
client = HttpClient()
# Make a GET request
response = await client.get("https://example.com")
# Make a request with custom method, headers, and body
response = await client.request(
url="https://example.com/submit",
method="POST",
headers={"Content-Type": "application/json"},
body=b'{"key": "value"}'
)
# Allow specific status codes
response = await client.request(
url="https://example.com/optional",
allow_status="404"
)
# Allow any status code
response = await client.request(
url="https://example.com/any_status",
allow_status="*"
)
```
--------------------------------
### Simulate Button Click and Fetch Product Images with HttpClient
Source: https://web-poet.readthedocs.io/en/stable/_sources/page-objects/additional-requests.rst
This example demonstrates how to use HttpClient within a web-poet page object to simulate a button click, which triggers a background request to fetch product images. It includes error handling for HTTP requests and returns a list of Image items.
```python
import attrs
from web_poet import HttpClient, HttpError, field
from zyte_common_items import Image, ProductPage
@attrs.define
class MyProductPage(ProductPage):
http: HttpClient
@field
def productId(self):
return self.css("::attr(product-id)").get()
@field
async def images(self):
url = f"https://api.example.com/v2/images?id={self.productId}"
try:
response = await self.http.get(url)
except HttpError:
return []
else:
urls = response.css(".product-images img::attr(src)").getall()
return [Image(url=url) for url in urls]
```
--------------------------------
### Get Item from URL using web_poet.example
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/example
This function serves as the main entry point for retrieving an item from a given URL. It finds the appropriate page object class from the default registry, instantiates it using `_get_page`, and then calls the `to_item` method to extract and return the desired item. It handles potential errors if no page class is found for the URL.
```python
[docs]
def get_item(
url: str,
item_cls: type,
*,
page_params: dict[Any, Any] | None = None,
) -> Any:
"""Returns an item built from the specified URL using a page object class
from the default registry.
This function is an example of a minimal, incomplete web-poet framework
implementation, intended for use in the web-poet tutorial.
"""
page_cls = default_registry.page_cls_for_item(url, item_cls)
if page_cls is None:
raise ValueError(f"No page object class found for URL: {url}")
page = _get_page(url, page_cls, page_params=page_params)
return run(ensure_awaitable(page.to_item()))
```
--------------------------------
### Get All Rules
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Retrieves a list of all `ApplyRule` objects declared using the `@handle_urls` decorator. It's recommended to call `consume_modules()` beforehand to ensure all relevant rules are loaded.
```APIDOC
## GET /rules
### Description
Retrieves all `ApplyRule` objects registered in the system.
### Method
GET
### Endpoint
/rules
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **rules** (list[ApplyRule]) - A list of all registered ApplyRule objects.
#### Response Example
```json
[
{
"priority": 100,
"use": "com.example.pages.HomePage",
"include": [
"https://example.com"
],
"exclude": [],
"override": null
}
]
```
```
--------------------------------
### Get All Rules
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/rules
Retrieves a list of all declared ApplyRule objects managed by the registry. It's recommended to call `consume_modules` beforehand to ensure all submodules with `@handle_urls` decorators are imported.
```APIDOC
## GET /rules
### Description
Return all the :class:`~.ApplyRule` that were declared using the ``@handle_urls`` decorator.
### Method
GET
### Endpoint
/rules
### Parameters
#### Query Parameters
- **consume_modules** (boolean) - Optional - Whether to recursively import submodules containing ``@handle_urls`` decorators.
### Response
#### Success Response (200)
- **rules** (list[ApplyRule]) - A list of ApplyRule objects.
#### Response Example
```json
[
{
"use": "ProductPO",
"instead_of": null,
"meta": {},
"priority": 0
}
]
```
```
--------------------------------
### Define Rule Manually with ApplyRule - Python
Source: https://web-poet.readthedocs.io/en/stable/_sources/page-objects/rules.rst
This example shows how to manually create and register an ApplyRule object. It explicitly defines URL patterns, the page object class to use (MyPage), and the return type (MyItem). This provides more granular control over rule creation and registration with the default registry.
```python
from url_matcher import Patterns
from web_poet import ApplyRule, ItemPage, default_registry
from my_items import MyItem
class MyPage(ItemPage[MyItem]): ...
rule = ApplyRule(
for_patterns=Patterns(include=["example.com"]),
use=MyPage,
to_return=MyItem,
)
default_registry.add_rule(rule)
```
--------------------------------
### Manually Build Page Object Instance
Source: https://web-poet.readthedocs.io/en/stable/page-objects/index
Provides an example of manually creating an instance of a page object class (`FooPage`). This involves directly instantiating the class and passing the required input parameters, such as an `HttpResponse` object, to its constructor. This method is less robust against changes in the page object's signature.
```python
from web_poet import HttpResponse
foo_page = FooPage(
response=HttpResponse(
"https://example.com",
b"\n
Foo",
),
)
```
--------------------------------
### Get Fully Qualified Class Name
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/utils
Retrieves the fully qualified name of a given type (class). This includes the module path and the class name, useful for uniquely identifying types. Example usage with web_poet.Injectable and decimal.Decimal is provided.
```python
from __future__ import annotations
from web_poet import Injectable
from decimal import Decimal
def get_fq_class_name(cls: type) -> str:
"""Return the fully qualified name for a type.
>>> from web_poet import Injectable
>>> get_fq_class_name(Injectable)
'web_poet.pages.Injectable'
>>> from decimal import Decimal
>>> get_fq_class_name(Decimal)
'decimal.Decimal'
"""
return f"{cls.__module__}.{cls.__qualname__}"
```
--------------------------------
### Perform GET Request using HttpClient
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/page_inputs/client
The `get` method is a convenience wrapper around the `request` method to perform an HTTP GET request. It takes a URL and optional headers, and returns an HttpResponse. It simplifies making GET requests by pre-setting the method to 'GET'.
```python
async def get(self,
url: str | _Url,
*,
headers: _Headers | None = None,
allow_status: _StatusList | None = None,
) -> HttpResponse:
"""Similar to :meth:`~.HttpClient.request` but peforming a ``GET``
request.
"""
return await self.request(
url=url,
method="GET",
headers=headers,
allow_status=allow_status,
)
```
--------------------------------
### Execute Web-Poet Tutorial Script (Bash)
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/tutorial.rst
This command executes the Python script `run.py` located in the `tutorial-project` directory. This script is part of the web-poet tutorial and demonstrates the usage of page objects and the `get_item` function.
```bash
python tutorial-project/run.py
```
--------------------------------
### Page Object Instantiation in web_poet.example
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/example
This function illustrates how to instantiate a page object using dependency injection with the 'andi' library. It plans the dependencies required by the page class (HttpClient, HttpResponse, PageParams) and provides them by calling helper functions or creating instances. This is crucial for setting up the page object with the necessary data before extracting items.
```python
def _get_page(
url: str,
page_cls: type[ItemPage],
*,
page_params: dict[Any, Any] | None = None,
) -> ItemPage:
plan = andi.plan(
page_cls,
is_injectable=is_injectable,
externally_provided={
HttpClient,
HttpResponse,
PageParams,
},
)
instances: dict[Any, Any] = {}
for fn_or_cls, kwargs_spec in plan:
if fn_or_cls is HttpResponse:
instances[fn_or_cls] = _get_http_response(url)
elif fn_or_cls is HttpClient:
instances[fn_or_cls] = _HttpClient()
elif fn_or_cls is PageParams:
instances[fn_or_cls] = PageParams(page_params or {})
else:
instances[fn_or_cls] = fn_or_cls(**kwargs_spec.kwargs(instances))
return instances[page_cls]
```
--------------------------------
### HttpClient GET Method
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/page_inputs/client
A convenience method for making GET requests.
```APIDOC
## GET /get
### Description
A convenience method for making GET requests. It's a shortcut for calling `request` with the method set to 'GET'.
### Method
`get`
### Parameters
- **url** (str | _Url) - Required - The URL for the GET request.
- **headers** (_Headers | None) - Optional - Headers to include in the request.
### Response
#### Success Response (HttpResponse)
- **response** (HttpResponse) - The HttpResponse object for successful GET requests.
#### Error Response (HttpError or HttpResponseError)
- **exception** (HttpError | HttpResponseError) - Raised for connection errors, timeouts, or disallowed HTTP status codes.
```
--------------------------------
### HttpRequestHeaders Initialization
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Shows how to instantiate HttpRequestHeaders using either an iterable of tuples or a dictionary of key-value pairs. It also highlights the case-insensitive lookup functionality inherited from multidict.CIMultiDict.
```python
from web_poet.page_inputs.http import HttpRequestHeaders
# Initialization with an iterable of tuples
pairs_tuple = [("Content-Encoding", "gzip"), ("content-length", "648")]
headers_from_tuple = HttpRequestHeaders(pairs_tuple)
print(headers_from_tuple)
# Initialization with a mapping of key-value pairs
pairs_dict = {"Content-Encoding": "gzip", "content-length": "648"}
headers_from_dict = HttpRequestHeaders(pairs_dict)
print(headers_from_dict)
# Case-insensitive lookup
print(headers_from_dict.get("content-encoding"))
print(headers_from_dict.get("Content-Length"))
```
--------------------------------
### GET Request
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/page_inputs/client
Performs an HTTP GET request to the specified URL. This is a convenience method that wraps the more general `request` method.
```APIDOC
## GET /url
### Description
Performs an HTTP GET request to the specified URL.
### Method
GET
### Endpoint
/url
### Parameters
#### Query Parameters
- **url** (str | _Url) - Required - The URL to send the GET request to.
- **headers** (_Headers | None) - Optional - A dictionary of headers to include in the request.
- **allow_status** (_StatusList | None) - Optional - A list of status codes to allow without raising an exception.
### Request Example
```json
{
"url": "https://example.com",
"headers": {
"User-Agent": "MyClient/1.0"
}
}
```
### Response
#### Success Response (200)
- **HttpResponse** - The HTTP response object.
#### Response Example
```json
{
"status_code": 200,
"body": "..."
}
```
```
--------------------------------
### Registering Rules with RulesRegistry in Python
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Demonstrates how to use the RulesRegistry to store and retrieve ApplyRule instances. It shows how to access the default registry and use the `handle_urls` decorator to define rules for Page Objects.
```python
from web_poet import handle_urls, default_registry, WebPage
from my_items import Product
@handle_urls("example.com")
class ExampleComProductPage(WebPage[Product]): ...
rules = default_registry.get_rules()
```
--------------------------------
### Get Saved Responses
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Retrieves previously saved requests and responses.
```APIDOC
## GET /get_saved_responses
### Description
Retrieves a collection of saved requests and responses.
### Method
GET
### Endpoint
/get_saved_responses
### Parameters
#### Path Parameters
None
#### Query Parameters
None
### Request Body
None
### Response
#### Success Response (200)
- **Iterable[_SavedResponseData]** - An iterable containing data for saved requests and responses.
#### Response Example
```json
[
{
"request": {
"method": "GET",
"url": "http://example.com",
"headers": {},
"body": null
},
"response": {
"status_code": 200,
"headers": {"Content-Type": "text/html"},
"body": "Hello"
}
}
]
```
```
--------------------------------
### Separate download and parse functions
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/from-ground-up.rst
Refactors the scraping code into two distinct functions: 'download' for fetching the web page and 'parse' for extracting data. This separation improves modularity and allows for easier replacement of the download mechanism.
```python
import requests
from parsel import Selector
def parse(response: requests.Response) -> dict:
selector = Selector(response.text)
return {
"url": response.url,
"title": selector.css("h1").get(),
}
def download(url: str) -> requests.Response:
return requests.get(url)
url = "http://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"
response = download(url)
item = parse(response)
```
--------------------------------
### Simplify Page Object Access with WebPage
Source: https://web-poet.readthedocs.io/en/stable/intro/from-ground-up
Further simplifies the page object by leveraging WebPage's shortcuts for accessing response attributes and methods directly.
```python
from web_poet import WebPage
class BookPage(WebPage):
def to_item(self) -> dict:
return {
"url": self.url,
"title": self.css("h1").get(),
}
```
--------------------------------
### Get Saved Responses from Web-Poet
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/page_inputs/client
Retrieves all saved requests and responses from the internal storage. This method returns an iterable of _SavedResponseData objects.
```python
def get_saved_responses(self) -> Iterable[_SavedResponseData]:
"""Return saved requests and responses."""
return self._saved_responses.values()
```
--------------------------------
### RequestDownloaderVarError Exception (Python)
Source: https://web-poet.readthedocs.io/en/stable/api-reference
The `RequestDownloaderVarError` is raised when the `web_poet.request_downloader_var` context variable is accessed before any value has been set. This typically occurs when request downloading is attempted without proper context setup.
```python
from web_poet.exceptions import RequestDownloaderVarError
# Example of catching the exception:
# try:
# # code that uses request_downloader_var without it being set
# except RequestDownloaderVarError as e:
# print(f"Context error: {e}")
```
--------------------------------
### Create a Web-Poet Page Object Class
Source: https://web-poet.readthedocs.io/en/stable/intro/from-ground-up
Demonstrates how to create a basic page object class using web-poet's Injectable base class. It takes an HttpResponse object and provides a to_item method to extract data.
```python
import requests
from web_poet import Injectable, HttpResponse
class BookPage(Injectable):
def __init__(self, response: HttpResponse):
self.response = response
def to_item(self) -> dict:
return {
"url": self.response.url,
"title": self.response.css("h1").get(),
}
def download(url: str) -> Response:
response = requests.get(url)
return HttpResponse(
url=response.url,
body=response.content,
headers=response.headers,
)
url = "http://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"
response = download(url)
book_page = BookPage(response=response)
item = book_page.to_item()
```
--------------------------------
### HttpResponseHeaders Initialization
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Shows how to instantiate HttpResponseHeaders using an iterable of tuples, similar to HttpRequestHeaders. This class is designed to hold HTTP response headers.
```python
from web_poet.page_inputs.http import HttpResponseHeaders
pairs = [("Content-Encoding", "gzip"), ("content-length", "648")]
response_headers = HttpResponseHeaders(pairs)
print(response_headers)
```
--------------------------------
### Ensure Object is Awaitable (Python)
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Returns the value of an object, awaiting it if it is an awaitable (e.g., a coroutine or a future). This function simplifies handling of asynchronous operations by providing a uniform way to get results.
```python
from typing import Any
async def ensure_awaitable(_obj_: Any) -> Any:
"""Return the value of obj, awaiting it if needed."""
# Implementation details would go here
pass
```
--------------------------------
### Define BookPage with fields using web-poet (Python)
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/from-ground-up.rst
Illustrates how to use web_poet's @field decorator to define individual parsing logic for fields like 'url' and 'title'. This approach eliminates the need for a manual to_item method and allows for lazy field evaluation.
```python
from web_poet import WebPage, field
class BookPage(WebPage):
@field
def url(self):
return self.url
@field
def title(self):
return self.css("h1").get()
```
--------------------------------
### Get Fully Qualified Class Name (Python)
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Retrieves the fully qualified name of a given type. This is useful for introspection and serialization purposes. It handles built-in types and custom classes alike.
```python
from web_poet import Injectable
def get_fq_class_name(_cls : type_) -> str:
"""Return the fully qualified name for a type."""
# Implementation details would go here
pass
print(get_fq_class_name(Injectable))
from decimal import Decimal
print(get_fq_class_name(Decimal))
```
--------------------------------
### Get All Rules Declared with @handle_urls
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/rules
Retrieves a list of all ApplyRule objects that have been registered using the `@handle_urls` decorator. This function is useful for inspecting all available rules in the registry.
```python
def get_rules(self) -> list[ApplyRule]:
"""Return all the :class:`~.ApplyRule` that were declared using
the ``@handle_urls`` decorator.
.. note::
Remember to consider calling :func:`~.web_poet.rules.consume_modules`
beforehand to recursively import all submodules which contains the
``@handle_urls`` decorators from external Page Objects.
"""
return list(self._rules.values())
```
--------------------------------
### Create HttpResponseHeaders from Bytes Dictionary (Python)
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Shows how to instantiate HttpResponseHeaders from a dictionary where keys and values are in bytes format. It supports lists or tuples of bytes for multi-value headers and allows specifying the decoding encoding.
```python
>>> raw_values = {
... b"Content-Encoding": [b"gzip", b"br"],
... b"Content-Type": [b"text/html"],
... b"content-length": b"648",
... }
>>> headers = _HttpHeaders.from_bytes_dict(raw_values)
>>> headers
<_HttpHeaders('Content-Encoding': 'gzip', 'Content-Encoding': 'br', 'Content-Type': 'text/html', 'content-length': '648')>
```
--------------------------------
### Get Generic Type Parameter (Python)
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Recursively searches base classes breadth-first to find a generic class and return its parameter. It returns the parameter of the first found class that is a subclass of the expected type.
```python
from typing import TypeVar, Union, Tuple
TypeVarT = TypeVar('TypeVarT')
def get_generic_param(_cls : type, _expected : Union[type, Tuple[type, ...]]) -> Union[type, None]:
"""Search the base classes recursively breadth-first for a generic class and return its param."""
# Implementation details would go here
pass
```
--------------------------------
### Create HttpResponseHeaders from Key-Value Pairs (Python)
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Demonstrates creating an HttpResponseHeaders object by passing a dictionary of key-value pairs. This constructor supports case-insensitive lookups for header keys.
```python
>>> pairs = {"Content-Encoding": "gzip", "content-length": "648"}
>>> headers = HttpResponseHeaders(pairs)
>>> headers
>>> headers.get("content-encoding")
'gzip'
>>> headers.get("Content-Length")
'648'
```
--------------------------------
### Defining URL Patterns with ApplyRule in Python
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Illustrates the use of the ApplyRule class to associate URL patterns with specific Page Objects. It explains the parameters like `for_patterns`, `use`, `instead_of`, and `to_return` for configuring rule behavior.
```python
from web_poet.rules import ApplyRule
from web_poet import ItemPage
# Example of creating an ApplyRule instance
rule = ApplyRule(
for_patterns="example.com/products/*",
use=ProductPage,
instead_of=AnotherProductPage,
to_return=Product,
meta={"version": 1}
)
```
--------------------------------
### Refactor Page Object with WebPage Base Class
Source: https://web-poet.readthedocs.io/en/stable/intro/from-ground-up
Shows how to simplify a web-poet page object by inheriting from the WebPage base class, which provides a default __init__ method for the response object.
```python
from web_poet import WebPage
class BookPage(WebPage):
def to_item(self) -> dict:
return {
"url": self.response.url,
"title": self.response.css("h1").get(),
}
```
--------------------------------
### Define RequestDownloaderVarError Exception for web-poet
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/exceptions/core
Defines the RequestDownloaderVarError exception, raised when the web_poet.request_downloader_var is accessed without a value set during request execution. Refer to the contextvars setup documentation for more details.
```python
class RequestDownloaderVarError(Exception):
"""The ``web_poet.request_downloader_var`` had its contents accessed but there
wasn't any value set during the time requests are executed.
See the documentation section about :ref:`setting up the contextvars `
to learn more about this.
"""
pass
```
--------------------------------
### Get Fields Dictionary in Python
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/fields
This Python function retrieves a dictionary containing information about fields defined for a given class or instance. The keys are field names, and the values are FieldInfo instances.
```python
def get_fields_dict(cls_or_instance) -> dict[str, FieldInfo]:
"""Return a dictionary with information about the fields defined
for the class: keys are field names, and values are
:class:`web_poet.fields.FieldInfo` instances.
"""
return getattr(cls_or_instance, _FIELDS_INFO_ATTRIBUTE_READ, {})
```
--------------------------------
### Define BookPage using WebPage shortcuts (Python)
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/from-ground-up.rst
Shows a refactored BookPage class inheriting from web_poet.WebPage, utilizing shortcuts provided by the base class for accessing response URL and CSS selectors directly. This simplifies the to_item method.
```python
from web_poet import WebPage
class BookPage(WebPage):
def to_item(self) -> dict:
return {
"url": self.url,
"title": self.css("h1").get(),
}
```
--------------------------------
### Get Overriding Page Objects for URL
Source: https://web-poet.readthedocs.io/en/stable/_modules/web_poet/rules
Identifies page objects that override others for a specific URL. It returns a mapping where keys are the overridden page objects and values are the overriding ones.
```python
def overrides_for(self, url: _Url | str) -> Mapping[type[ItemPage], type[ItemPage]]:
"""Finds all of the page objects associated with the given URL and
returns a Mapping where the 'key' represents the page object that is
**overridden** by the page object in 'value'."""
result: dict[type[ItemPage], type[ItemPage]] = {}
for replaced_page, matcher in self._overrides_matchers.items():
if replaced_page is None:
continue
page = self._match_url_for_page_object(url, matcher)
if page:
result[replaced_page] = page
return result
```
--------------------------------
### Run pytest with Web-Poet test options
Source: https://web-poet.readthedocs.io/en/stable/_sources/page-objects/testing.rst
Demonstrates how to run pytest with specific options for Web-Poet to control test reporting granularity. The `--web-poet-test-per-item` flag changes the test structure from one test per field to one test per fixture.
```bash
python -m pytest --web-poet-test-per-item
```
--------------------------------
### Define BookPage with WebPage inheritance (Python)
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/from-ground-up.rst
Demonstrates a basic BookPage class inheriting from web_poet.WebPage, implementing the to_item method to extract URL and title from response data. This leverages the base class's __init__ for response handling.
```python
from web_poet import WebPage
class BookPage(WebPage):
def to_item(self) -> dict:
return {
"url": self.response.url,
"title": self.response.css("h1").get(),
}
```
--------------------------------
### Web-Poet Page Object with Time Fields
Source: https://web-poet.readthedocs.io/en/stable/_sources/page-objects/testing.rst
An example of a Web-Poet page object that extracts and formats time-based data. It demonstrates capturing current time in UTC and local time, highlighting the importance of timezone handling in tests.
```python
import datetime
from web_poet import WebPage, validates_input
class DateItemPage(WebPage):
@validates_input
async def to_item(self) -> dict:
# e.g. 2001-01-01 11:00:00 +00
now = datetime.datetime.now(datetime.timezone.utc)
return {
# '2001-01-01T11:00:00Z'
"time_utc": now.strftime("%Y-%M-%dT%H:%M:%SZ"),
# if the current timezone is CET, then '2001-01-01T12:00:00+01:00'
"time_local": now.astimezone().strftime("%Y-%M-%dT%H:%M:%S%z"),
}
```
--------------------------------
### Ensuring Awaitable Execution with `ensure_awaitable`
Source: https://web-poet.readthedocs.io/en/stable/_sources/page-objects/index.rst
Provides an example of how to handle both synchronous and asynchronous `to_item` methods when retrieving a page object directly. The `ensure_awaitable` utility ensures consistent handling.
```python
from web_poet.utils import ensure_awaitable
# Assume 'foo_page' is an instance of a page object
# item = await ensure_awaitable(foo_page.to_item())
```
--------------------------------
### Search ApplyRules by Attributes
Source: https://web-poet.readthedocs.io/en/stable/api-reference
Searches the registry for ApplyRules that match all provided attributes. This is useful for finding specific rules based on criteria like 'use' or 'instead_of'.
```python
rules = registry.search(use=ProductPO, instead_of=GenericPO)
print(len(rules)) # 1
print(rules[0].use) # ProductPO
print(rules[0].instead_of) # GenericPO
```
--------------------------------
### Run Tests with Tox and Mypy
Source: https://web-poet.readthedocs.io/en/stable/contributing
This command executes the test suite for the web-poet project using tox, which also performs type checking with mypy across different Python versions. Ensure tox is installed in your environment before running.
```shell
tox
```
--------------------------------
### Resolve rule conflicts by subclassing and adjusting priority
Source: https://web-poet.readthedocs.io/en/stable/page-objects/rules
Provides an example of how to resolve rule conflicts when dealing with external packages. By subclassing a conflicting page object class and adjusting the priority, you can ensure your rule takes precedence.
```python
from package1 import A
from web_poet import handle_urls
# Assume package1.A and package2.B are conflicting page object classes
# with default priority (500).
@handle_urls(..., priority=510) # Adjust priority to ensure precedence
class NewA(A):
pass
```
--------------------------------
### Parse with web-poet Page Object
Source: https://web-poet.readthedocs.io/en/stable/_sources/intro/from-ground-up.rst
Converts the parsing logic into a web-poet Page Object class. This approach encapsulates the parsing logic within a dedicated class, utilizing web-poet's HttpResponse for standardized response handling and providing helper methods like 'css'.
```python
import requests
from web_poet import Injectable, HttpResponse
class BookPage(Injectable):
def __init__(self, response: HttpResponse):
self.response = response
def to_item(self) -> dict:
return {
"url": self.response.url,
"title": self.response.css("h1").get(),
}
def download(url: str) -> Response:
response = requests.get(url)
return HttpResponse(
url=response.url,
body=response.content,
headers=response.headers,
)
url = "http://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"
response = download(url)
book_page = BookPage(response=response)
item = book_page.to_item()
```