easyplaytv-service/…/providers/bbc_vod.py — BBC iPlayer catalogue
Since the 3-package split this catalogue scraper ships in the shared runtime at easyplaytv-service/src/easyplaytv_service/vod_sync/providers/bbc_vod.py (and the vendored copy inside service.easyplaytv). The video addon is playback-only and no longer contains a bbc_vod.py.
Role
Scrapes BBC's iPlayer category/episode pages. Each iPlayer HTML page
embeds a JSON blob in window.__IPLAYER_REDUX_STATE__
(the same data property their React app builds on); we parse that JSON
directly and turn it into the addon's house dict shape.
Constants
Root of all iPlayer pages.
14 paired slugs/labels. Slugs are BBC's own URL components; labels are
display strings. Cross-referenced by genres.py's
UNIFIED_GENRES map so the addon's "Drama" tile pulls BBC's
drama-and-soaps slug.
BBC's image URLs have {recipe} placeholders for size selection;
these are the two recipes we substitute.
Matches the inline JSON object that powers iPlayer's own UI. Same regex
as bbc.py:_get_vpid; duplicated because both modules
scrape the same JSON — the/.. BBC scraper is just one-stop.
Helpers
Standard gzip-aware HTML fetch with iPlayer's standard HTML accept headers.
Searches the page for the REDUX_RE regex, json.loads the
blob. Returns None on no match.
Substitutes {recipe} in a BBC image template with one of
"320x180" / "1920x1080".
Parses a BBC episode subtitle like Series 3 · Episode 5 and
returns (series_number, episode_number). Used by
list_episodes when the page doesn't carry numeric series/episode
fields directly.
Listing functions
Returns 14 {id, title} dicts from the hardcoded CATEGORIES —
doesn't hit the network.
Fetches https://www.bbc.co.uk/iplayer/categories/,
extracts the redux state, walks state["categories"]["elements"].
Each show dict has the standard addon shape
(id, title, image, description, episode_id, standalone, f_name).
Notably standalone is set for single-programme shows (films,
one-off documentaries) so library_sync.py
knows whether to fetch seasons.
Returns (shows, total_pages, cur_page) for the pagination
loop in library_sync.py.
Fetches the episode page at
https://www.bbc.co.uk/iplayer/episode/, parses redux
state, returns the state["series" list — each season has
a series_id and a title. Care:
a BBC "pid" in this context is the show pid, not an individual episode's
pid. Confusingly the same name is used in bbc.py:_get_vpid
for the per-episode version id.
Fetches the per-show episodes-page (URL parameters vary if
series_id is set: BBC supports a per-series filter).
Returns the same tuple shape as list_shows. The returned
episode dicts include episode_id (the episode pid used by
bbc.resolve_vod) and
subtitle (the human-readable series+episode subtitle used by
library_sync.py to build a nice display
title).