Wikipedia-API

repository·master·Indexed 20 days ago

https://github.com/martin-majlis/wikipedia-api

A Python wrapper for the Wikipedia API (version 0.15.0) designed to simplify the extraction of text, sections, links, categories, and translations. It provides both synchronous (wikipediaapi.Wikipedia) and asynchronous (wikipediaapi.AsyncWikipedia) clients, supporting custom user agents, language codes, and HTML extract formats.

Tokens
35.9K
Snippets
126
Records
165
Agent score
71%

What's inside Wikipedia-API

  1. Overview of the Wikipedia-API file layout

    master

    The project is organized into several functional packages:

    • wikipediaapi/: The root package containing public exports and the CLI entry point (cli.py).
    • _http_client/: The transport layer (sync/async clients, retry logic).
    • _resources/: The API layer (parameter builders, parsers, and public API methods).
    • _types/: Dataclasses for structured data (e.g., Coordinate, SearchMeta).
    • _params/: Dataclasses for managing MediaWiki query parameters.
    • _pages_dict/: Management of page and image collections (PagesDict, ImagesDict).
    • _enums/: Enumerations for API constants (e.g., Namespace, Direction).
    • exceptions/: Custom exception hierarchy (e.g., WikiConnectionError, WikiRateLimitError).
    • _wikipedia/: The concrete client implementations (Wikipedia and AsyncWikipedia).
    • _page/ & _image/: Page and Image object implementations (sync and async versions).
  2. How Wikipedia-API is architected

    master

    The library is built using a decoupled architecture that separates HTTP transport concerns from MediaWiki API logic. This is achieved through two primary layers implemented as abstract mixins:

    1. HTTP transport: Handles the mechanics of making requests, including synchronous vs. asynchronous execution, retries, and rate-limit handling.
    2. API logic: Handles the construction of MediaWiki query parameters and the parsing of JSON responses into Python objects.

    Concrete client classes (like Wikipedia or AsyncWikipedia) are assembled by combining one transport mixin with one API mixin using Python's multiple inheritance. This ensures the API logic layer remains independent of the underlying HTTP library (e.g., httpx).

  3. Understand the two MediaWiki submodule types

    master

    When adding support for a new MediaWiki action=query submodule, you must first identify which of the two families it belongs to. This choice dictates how you dispatch requests and whether the submodule is tied to a specific page.

    TypeAPI shapeExampleDispatch helper
    prop=Requires titles=, result in raw["query"]["pages"]coordinates, images_dispatch_prop or manual _get + iterate pages
    list=No titles=, result in raw["query"][list_key]geosearch, random, searchsingle _get call
    • prop= submodules are per-page data fetched using a page title.
    • list= submodules are standalone queries not tied to a specific page.
  4. Understand the Wikipedia-API architecture

    master

    The library is organized into two primary layers: the Transport Layer and the API Layer.

    Transport Layer

    Handles the low-level HTTP communication with Wikipedia. It uses httpx for requests and tenacity for retry logic (including exponential backoff and honoring Retry-After headers for HTTP 429 responses).

    • SyncHTTPClient: Provides blocking HTTP requests.
    • AsyncHTTPClient: Provides asynchronous coroutines for HTTP requests.

    API Layer

    Implements the MediaWiki API logic and resource management.

    • BaseWikipediaResource: A mixin containing parameter builders, response parsers, and dispatch helpers.
    • WikipediaResource: The synchronous implementation providing methods like extracts, info, langlinks, links, backlinks, categories, and categorymembers.
    • AsyncWikipediaResource: The asynchronous mirror of the synchronous resource, returning AsyncWikipediaPage objects to ensure async compatibility.
  5. Understand the lazy loading and caching behavior of Page objects

    master

    Page objects in Wikipedia-API are created lazily via wiki.page(title). No network call is made during construction. Instead, the first time you access a property (e.g., page.summary), the library triggers the API call. Subsequent accesses to that same property return the cached value.

    Key behaviors:

    • Lazy Fetching: WikipediaPage._fetch(call) is triggered on the first property access.
    • Per-parameter Caching: Some properties like coordinates and images support different parameter sets. Results are cached in page._param_cache[name][cache_key].
    • Sentinel Value: The library uses a NOT_CACHED sentinel to distinguish between a property that has never been fetched and a property that was fetched but returned None.
  6. Use Wiki* type aliases for flexible function signatures

    master

    The library provides type aliases (e.g., WikiSearchSort, WikiGlobe) that represent a Union[Enum, str]. When writing your own functions that wrap the Wikipedia API, use these aliases in your type annotations. This allows your functions to accept either the strongly-typed enum or a simple string while remaining type-safe.

    from wikipediaapi import WikiSearchSort, WikiGlobe, GeoPoint
    
    def search_wiki(query: str, sort: WikiSearchSort):
        # This function accepts SearchSort.RELEVANCE or "relevance"
        pass
    
    def geo_search_wiki(coord: GeoPoint, sort: WikiGlobe):
        # This function accepts Globe.EARTH or "earth"
        pass
  7. How the request lifecycle works

    master

    The library uses a lazy-loading pattern. Data is not fetched until a specific attribute or property is accessed.

    Synchronous Flow

    When you access a property like page.summary:

    1. WikipediaPage.summary checks its internal cache.
    2. If empty, it calls _fetch_page().
    3. This triggers a call to the Wikipedia resource (e.g., Wikipedia.extracts(page)).
    4. The resource uses a Dispatch Helper to build parameters and call the SyncHTTPClient.
    5. The SyncHTTPClient performs the httpx.Client.get request with retries.
    6. The raw JSON response is passed to a Response Parser (e.g., _build_extracts), which populates the page object and returns the value.

    Asynchronous Flow

    When you await page.summary:

    1. AsyncWikipediaPage.summary (an explicit @property returning a coroutine) is called.
    2. It triggers _fetch() (async).
    3. This calls the AsyncWikipedia resource (e.g., AsyncWikipedia.extracts(page)).
    4. The resource uses an async dispatch helper to call AsyncHTTPClient.
    5. The AsyncHTTPClient performs an await httpx.AsyncClient.get request with async retries.
    6. The response is parsed and the page is populated.
  8. Understand the relationship between Wikipedia and Page objects

    master

    The library uses a composition pattern where concrete client instances (like Wikipedia or AsyncWikipedia) act as the primary entry points and manage the transport layer. These clients produce Page objects (like WikipediaPage or AsyncWikipediaPage) which represent specific Wikipedia articles.

    Page objects hold a back-reference to their parent client instance. This allows Page objects to lazily trigger data fetching by calling the client's transport methods only when a specific attribute or property is accessed.

  9. Understand the `exists()` and `pageid` invariant

    master

    The exists() method and the pageid property follow a deterministic relationship used to indicate the presence of a page:

    • If exists() is True: pageid will return a positive integer.
    • If exists() is False: pageid will return a negative integer.

    Both values are deterministic based on abs(hash(title)).

  10. Compare Synchronous and Asynchronous clients

    master

    The library provides two client types: Wikipedia (synchronous) and AsyncWikipedia (asynchronous).

    Key differences:

    • Data-fetching attributes: In the async API, attributes like summary, text, sections, langlinks, links, backlinks, categories, categorymembers, coordinates, images, pageid, fullurl, and displaytitle are coroutines and must be awaited (e.g., await page.summary). In the sync API, they are plain @property values.
    • Existence check: exists() is a plain method in the sync API, but a coroutine in the async API (await page.exists()).
    • Static properties: title, ns, namespace, language, and variant are plain @property values in both APIs and do not require await.
    • Methods: section_by_title() and sections_by_title() are synchronous in both APIs.
    import wikipediaapi
    
    # Synchronous client
    wiki = wikipediaapi.Wikipedia(user_agent='MyProjectName (merlin@example.com)', language='en')
    
    # Asynchronous client
    wiki = wikipediaapi.AsyncWikipedia(user_agent='MyProjectName (merlin@example.com)', language='en')
  11. Understand the VCR JSON Extractor output format

    master

    The extractor produces a flat directory structure. For cassettes containing multiple HTTP interactions, the script generates a separate file for each interaction using an incrementing index.

    File Naming Convention: {test_name}_{interaction_index}.json

    Example Output Structure:

    tests/cassettes-json/
    ├── TestVcrAsyncPageExistence.test_exists_true_0.json
    ├── TestVcrAsyncPageExistence.test_exists_false_0.json
    ├── TestVcrAsyncPageExtractProps.test_summary_0.json
    └── ...