Module hdrezka.post.site

Site chrome parsers: navbar, catalog filters, series updates, favorites.

Sub-modules

hdrezka.post.site.content

Combined catalog page payload.

hdrezka.post.site.favorites

Favorites category list parsing.

hdrezka.post.site.filters

Catalog page filter / sort controls parsing.

hdrezka.post.site.navbar

Top navigation bar parsing.

hdrezka.post.site.updates

Sidebar series update feed parsing.

Functions

def parse_favorites_cats(html: str | bs4.BeautifulSoup | bs4.element.Tag) ‑> tuple[FavoritesCat, ...]
Expand source code
def parse_favorites_cats(html: str | BeautifulSoup | Tag) -> tuple[FavoritesCat, ...]:
    """
    Parse ``a.b-favorites_content__cats_list_link`` entries.

    Returns an empty tuple when the list is missing.
    """
    soup = as_soup(html)
    cats = []
    for a in soup.select('a.b-favorites_content__cats_list_link'):
        href = attr(a, 'href', default='') or ''
        cats.append(FavoritesCat(
            name=text(a.select_one('.name')),
            url=href,
            count=get_any_int(text(a.select_one('.num-holder'))),
            id=_cat_id_from_url(href),
        ))
    return tuple(cats)

Parse a.b-favorites_content__cats_list_link entries.

Returns an empty tuple when the list is missing.

def parse_navbar(html: str | bs4.BeautifulSoup | bs4.element.Tag) ‑> Navbar
Expand source code
def parse_navbar(html: str | BeautifulSoup | Tag) -> Navbar:
    """
    Parse ``ul#topnav-menu`` into a ``Navbar``.

    Returns an empty ``Navbar`` when the menu is missing.
    """
    soup = as_soup(html)
    menu = soup.select_one('ul#topnav-menu.b-topnav__inner') or soup.select_one('ul#topnav-menu')
    if menu is None:
        return Navbar()
    items = []
    for li in menu.find_all('li', class_='b-topnav__item', recursive=False):
        classes = li.get('class') or []
        is_single = 'single' in classes
        link = li.select_one('a.b-topnav__item-link')
        if link is None:
            continue
        items.append(NavItem(
            name=text(link),
            url=attr(link, 'href', default='') or '',
            single=is_single,
            submenu=None if is_single else _parse_submenu(li),
        ))
    return Navbar(items=tuple(items))

Parse ul#topnav-menu into a Navbar.

Returns an empty Navbar when the menu is missing.

def parse_page_filters(html: str | bs4.BeautifulSoup | bs4.element.Tag) ‑> PageFilters
Expand source code
def parse_page_filters(html: str | BeautifulSoup | Tag) -> PageFilters:
    """
    Parse ``ul.b-content__main_filters`` into ``PageFilters``.

    Returns empty tuples when the block is absent.
    """
    soup = as_soup(html)
    root = soup.select_one('ul.b-content__main_filters')
    if root is None:
        return PageFilters()
    sorts = tuple(
        _link(a, param='filter')
        for a in root.select('li.b-content__main_filters_item > a.b-content__main_filters_link')
    )
    types = tuple(
        _link(a, param='genre')
        for a in root.select('li.b-content__filters_types a.filter-link')
    )
    return PageFilters(sorts=sorts, types=types)

Parse ul.b-content__main_filters into PageFilters.

Returns empty tuples when the block is absent.

def parse_series_updates(html: str | bs4.BeautifulSoup | bs4.element.Tag) ‑> tuple[SeriesUpdateBlock, ...]
Expand source code
def parse_series_updates(html: str | BeautifulSoup | Tag) -> tuple[SeriesUpdateBlock, ...]:
    """
    Parse ``.b-seriesupdate__block`` entries from the inline sidebar.

    Returns an empty tuple when the sidebar feed is missing.
    """
    soup = as_soup(html)
    sidebar = soup.select_one('.b-content__inline_sidebar') or soup
    blocks = []
    for block in sidebar.select('.b-seriesupdate__block'):
        date = text(block.select_one('.b-seriesupdate__block_date'))
        items = []
        for li in block.select('ul.b-seriesupdate__block_list > li.b-seriesupdate__block_list_item'):
            item = _parse_item(li)
            if item is not None:
                items.append(item)
        blocks.append(SeriesUpdateBlock(date=date, items=tuple(items)))
    return tuple(blocks)

Parse .b-seriesupdate__block entries from the inline sidebar.

Returns an empty tuple when the sidebar feed is missing.

Classes

class FavoritesCat (name: str, url: str, count: int = 0, id: int | None = None)
Expand source code
class FavoritesCat(NamedTuple):
    """User favorites collection link from the favorites page sidebar/list."""
    name: str
    url: str
    count: int = 0
    id: int | None = None

User favorites collection link from the favorites page sidebar/list.

Ancestors

  • builtins.tuple

Instance variables

var count : int
Expand source code
class FavoritesCat(NamedTuple):
    """User favorites collection link from the favorites page sidebar/list."""
    name: str
    url: str
    count: int = 0
    id: int | None = None

Alias for field number 2

var id : int | None
Expand source code
class FavoritesCat(NamedTuple):
    """User favorites collection link from the favorites page sidebar/list."""
    name: str
    url: str
    count: int = 0
    id: int | None = None

Alias for field number 3

var name : str
Expand source code
class FavoritesCat(NamedTuple):
    """User favorites collection link from the favorites page sidebar/list."""
    name: str
    url: str
    count: int = 0
    id: int | None = None

Alias for field number 0

var url : str
Expand source code
class FavoritesCat(NamedTuple):
    """User favorites collection link from the favorites page sidebar/list."""
    name: str
    url: str
    count: int = 0
    id: int | None = None

Alias for field number 1

Expand source code
class FilterLink(NamedTuple):
    """One filter or content-type control on a catalog page."""
    name: str
    url: str
    param: str
    value: str
    active: bool = False

One filter or content-type control on a catalog page.

Ancestors

  • builtins.tuple

Instance variables

var active : bool
Expand source code
class FilterLink(NamedTuple):
    """One filter or content-type control on a catalog page."""
    name: str
    url: str
    param: str
    value: str
    active: bool = False

Alias for field number 4

var name : str
Expand source code
class FilterLink(NamedTuple):
    """One filter or content-type control on a catalog page."""
    name: str
    url: str
    param: str
    value: str
    active: bool = False

Alias for field number 0

var param : str
Expand source code
class FilterLink(NamedTuple):
    """One filter or content-type control on a catalog page."""
    name: str
    url: str
    param: str
    value: str
    active: bool = False

Alias for field number 2

var url : str
Expand source code
class FilterLink(NamedTuple):
    """One filter or content-type control on a catalog page."""
    name: str
    url: str
    param: str
    value: str
    active: bool = False

Alias for field number 1

var value : str
Expand source code
class FilterLink(NamedTuple):
    """One filter or content-type control on a catalog page."""
    name: str
    url: str
    param: str
    value: str
    active: bool = False

Alias for field number 3

class FindBestBlock (categories: tuple[FindBestOption, ...] = (),
years: tuple[FindBestOption, ...] = ())
Expand source code
class FindBestBlock(NamedTuple):
    """Category and year selectors from ``.b-topnav__findbest_block``."""
    categories: tuple[FindBestOption, ...] = ()
    years: tuple[FindBestOption, ...] = ()

Category and year selectors from .b-topnav__findbest_block.

Ancestors

  • builtins.tuple

Instance variables

var categories : tuple[FindBestOption, ...]
Expand source code
class FindBestBlock(NamedTuple):
    """Category and year selectors from ``.b-topnav__findbest_block``."""
    categories: tuple[FindBestOption, ...] = ()
    years: tuple[FindBestOption, ...] = ()

Alias for field number 0

var years : tuple[FindBestOption, ...]
Expand source code
class FindBestBlock(NamedTuple):
    """Category and year selectors from ``.b-topnav__findbest_block``."""
    categories: tuple[FindBestOption, ...] = ()
    years: tuple[FindBestOption, ...] = ()

Alias for field number 1

class FindBestOption (name: str, value: str, selected: bool = False)
Expand source code
class FindBestOption(NamedTuple):
    """Option from a navbar “best of” ``<select>``."""
    name: str
    value: str
    selected: bool = False

Option from a navbar “best of” <select>.

Ancestors

  • builtins.tuple

Instance variables

var name : str
Expand source code
class FindBestOption(NamedTuple):
    """Option from a navbar “best of” ``<select>``."""
    name: str
    value: str
    selected: bool = False

Alias for field number 0

var selected : bool
Expand source code
class FindBestOption(NamedTuple):
    """Option from a navbar “best of” ``<select>``."""
    name: str
    value: str
    selected: bool = False

Alias for field number 2

var value : str
Expand source code
class FindBestOption(NamedTuple):
    """Option from a navbar “best of” ``<select>``."""
    name: str
    value: str
    selected: bool = False

Alias for field number 1

class NavCollection (name: str, url: str, classes: tuple[str, ...] = ())
Expand source code
class NavCollection(NamedTuple):
    """Collection / platform link from a category submenu (right column)."""
    name: str
    url: str
    classes: tuple[str, ...] = ()

Collection / platform link from a category submenu (right column).

Ancestors

  • builtins.tuple

Instance variables

var classes : tuple[str, ...]
Expand source code
class NavCollection(NamedTuple):
    """Collection / platform link from a category submenu (right column)."""
    name: str
    url: str
    classes: tuple[str, ...] = ()

Alias for field number 2

var name : str
Expand source code
class NavCollection(NamedTuple):
    """Collection / platform link from a category submenu (right column)."""
    name: str
    url: str
    classes: tuple[str, ...] = ()

Alias for field number 0

var url : str
Expand source code
class NavCollection(NamedTuple):
    """Collection / platform link from a category submenu (right column)."""
    name: str
    url: str
    classes: tuple[str, ...] = ()

Alias for field number 1

class NavItem (name: str,
url: str,
single: bool = False,
submenu: NavSubmenu | None = None)
Expand source code
class NavItem(NamedTuple):
    """Single top-nav entry (with or without submenu)."""
    name: str
    url: str
    single: bool = False
    submenu: NavSubmenu | None = None

Single top-nav entry (with or without submenu).

Ancestors

  • builtins.tuple

Instance variables

var name : str
Expand source code
class NavItem(NamedTuple):
    """Single top-nav entry (with or without submenu)."""
    name: str
    url: str
    single: bool = False
    submenu: NavSubmenu | None = None

Alias for field number 0

var single : bool
Expand source code
class NavItem(NamedTuple):
    """Single top-nav entry (with or without submenu)."""
    name: str
    url: str
    single: bool = False
    submenu: NavSubmenu | None = None

Alias for field number 2

var submenuNavSubmenu | None
Expand source code
class NavItem(NamedTuple):
    """Single top-nav entry (with or without submenu)."""
    name: str
    url: str
    single: bool = False
    submenu: NavSubmenu | None = None

Alias for field number 3

var url : str
Expand source code
class NavItem(NamedTuple):
    """Single top-nav entry (with or without submenu)."""
    name: str
    url: str
    single: bool = False
    submenu: NavSubmenu | None = None

Alias for field number 1

class NavSubmenu (genres: tuple[Hyperlink, ...] = (),
collections: tuple[NavCollection, ...] = (),
find_best: FindBestBlock | None = None)
Expand source code
class NavSubmenu(NamedTuple):
    """Dropdown content under a top-nav category."""
    genres: tuple[Hyperlink, ...] = ()
    collections: tuple[NavCollection, ...] = ()
    find_best: FindBestBlock | None = None

Dropdown content under a top-nav category.

Ancestors

  • builtins.tuple

Instance variables

var collections : tuple[NavCollection, ...]
Expand source code
class NavSubmenu(NamedTuple):
    """Dropdown content under a top-nav category."""
    genres: tuple[Hyperlink, ...] = ()
    collections: tuple[NavCollection, ...] = ()
    find_best: FindBestBlock | None = None

Alias for field number 1

var find_bestFindBestBlock | None
Expand source code
class NavSubmenu(NamedTuple):
    """Dropdown content under a top-nav category."""
    genres: tuple[Hyperlink, ...] = ()
    collections: tuple[NavCollection, ...] = ()
    find_best: FindBestBlock | None = None

Alias for field number 2

var genres : tuple[Hyperlink, ...]
Expand source code
class NavSubmenu(NamedTuple):
    """Dropdown content under a top-nav category."""
    genres: tuple[Hyperlink, ...] = ()
    collections: tuple[NavCollection, ...] = ()
    find_best: FindBestBlock | None = None

Alias for field number 0

class Navbar (items: tuple[NavItem, ...] = ())
Expand source code
class Navbar(NamedTuple):
    """Full site top navigation map."""
    items: tuple[NavItem, ...] = ()

Full site top navigation map.

Ancestors

  • builtins.tuple

Instance variables

var items : tuple[NavItem, ...]
Expand source code
class Navbar(NamedTuple):
    """Full site top navigation map."""
    items: tuple[NavItem, ...] = ()

Alias for field number 0

class PageContent (items: list[InlineItem],
filters: PageFilters = PageFilters(sorts=(), types=()),
series_updates: tuple[SeriesUpdateBlock, ...] = (),
favorites_cats: tuple[FavoritesCat, ...] = ())
Expand source code
class PageContent(NamedTuple):
    """Catalog page fetch result: items plus optional chrome parsed from the same HTML."""
    items: list[InlineItem]
    filters: PageFilters = PageFilters()
    series_updates: tuple[SeriesUpdateBlock, ...] = ()
    favorites_cats: tuple[FavoritesCat, ...] = ()

Catalog page fetch result: items plus optional chrome parsed from the same HTML.

Ancestors

  • builtins.tuple

Instance variables

var favorites_cats : tuple[FavoritesCat, ...]
Expand source code
class PageContent(NamedTuple):
    """Catalog page fetch result: items plus optional chrome parsed from the same HTML."""
    items: list[InlineItem]
    filters: PageFilters = PageFilters()
    series_updates: tuple[SeriesUpdateBlock, ...] = ()
    favorites_cats: tuple[FavoritesCat, ...] = ()

Alias for field number 3

var filtersPageFilters
Expand source code
class PageContent(NamedTuple):
    """Catalog page fetch result: items plus optional chrome parsed from the same HTML."""
    items: list[InlineItem]
    filters: PageFilters = PageFilters()
    series_updates: tuple[SeriesUpdateBlock, ...] = ()
    favorites_cats: tuple[FavoritesCat, ...] = ()

Alias for field number 1

var items : list[InlineItem]
Expand source code
class PageContent(NamedTuple):
    """Catalog page fetch result: items plus optional chrome parsed from the same HTML."""
    items: list[InlineItem]
    filters: PageFilters = PageFilters()
    series_updates: tuple[SeriesUpdateBlock, ...] = ()
    favorites_cats: tuple[FavoritesCat, ...] = ()

Alias for field number 0

var series_updates : tuple[SeriesUpdateBlock, ...]
Expand source code
class PageContent(NamedTuple):
    """Catalog page fetch result: items plus optional chrome parsed from the same HTML."""
    items: list[InlineItem]
    filters: PageFilters = PageFilters()
    series_updates: tuple[SeriesUpdateBlock, ...] = ()
    favorites_cats: tuple[FavoritesCat, ...] = ()

Alias for field number 2

class PageFilters (sorts: tuple[FilterLink, ...] = (),
types: tuple[FilterLink, ...] = ())
Expand source code
class PageFilters(NamedTuple):
    """
    Filters available on a catalog page.

    ``sorts`` — ``filter=`` controls (popular, watching, …).
    ``types`` — ``genre=`` content-type controls (films, anime, …).
    """
    sorts: tuple[FilterLink, ...] = ()
    types: tuple[FilterLink, ...] = ()

Filters available on a catalog page.

sortsfilter= controls (popular, watching, …). typesgenre= content-type controls (films, anime, …).

Ancestors

  • builtins.tuple

Instance variables

var sorts : tuple[FilterLink, ...]
Expand source code
class PageFilters(NamedTuple):
    """
    Filters available on a catalog page.

    ``sorts`` — ``filter=`` controls (popular, watching, …).
    ``types`` — ``genre=`` content-type controls (films, anime, …).
    """
    sorts: tuple[FilterLink, ...] = ()
    types: tuple[FilterLink, ...] = ()

Alias for field number 0

var types : tuple[FilterLink, ...]
Expand source code
class PageFilters(NamedTuple):
    """
    Filters available on a catalog page.

    ``sorts`` — ``filter=`` controls (popular, watching, …).
    ``types`` — ``genre=`` content-type controls (films, anime, …).
    """
    sorts: tuple[FilterLink, ...] = ()
    types: tuple[FilterLink, ...] = ()

Alias for field number 1

class SeriesUpdateBlock (date: str,
items: tuple[SeriesUpdateItem, ...] = ())
Expand source code
class SeriesUpdateBlock(NamedTuple):
    """Series updates grouped under one date heading."""
    date: str
    items: tuple[SeriesUpdateItem, ...] = ()

Series updates grouped under one date heading.

Ancestors

  • builtins.tuple

Instance variables

var date : str
Expand source code
class SeriesUpdateBlock(NamedTuple):
    """Series updates grouped under one date heading."""
    date: str
    items: tuple[SeriesUpdateItem, ...] = ()

Alias for field number 0

var items : tuple[SeriesUpdateItem, ...]
Expand source code
class SeriesUpdateBlock(NamedTuple):
    """Series updates grouped under one date heading."""
    date: str
    items: tuple[SeriesUpdateItem, ...] = ()

Alias for field number 1

class SeriesUpdateItem (name: str, url: str, season: str = '', episode: str = '', translation: str = '')
Expand source code
class SeriesUpdateItem(NamedTuple):
    """One series episode update row."""
    name: str
    url: str
    season: str = ''
    episode: str = ''
    translation: str = ''

One series episode update row.

Ancestors

  • builtins.tuple

Instance variables

var episode : str
Expand source code
class SeriesUpdateItem(NamedTuple):
    """One series episode update row."""
    name: str
    url: str
    season: str = ''
    episode: str = ''
    translation: str = ''

Alias for field number 3

var name : str
Expand source code
class SeriesUpdateItem(NamedTuple):
    """One series episode update row."""
    name: str
    url: str
    season: str = ''
    episode: str = ''
    translation: str = ''

Alias for field number 0

var season : str
Expand source code
class SeriesUpdateItem(NamedTuple):
    """One series episode update row."""
    name: str
    url: str
    season: str = ''
    episode: str = ''
    translation: str = ''

Alias for field number 2

var translation : str
Expand source code
class SeriesUpdateItem(NamedTuple):
    """One series episode update row."""
    name: str
    url: str
    season: str = ''
    episode: str = ''
    translation: str = ''

Alias for field number 4

var url : str
Expand source code
class SeriesUpdateItem(NamedTuple):
    """One series episode update row."""
    name: str
    url: str
    season: str = ''
    episode: str = ''
    translation: str = ''

Alias for field number 1