MIL-003: scraping Hacker News #37
@@ -1,10 +1,11 @@
|
|||||||
"""@brief The ports (interfaces) the use cases need from the outside world."""
|
"""@brief The ports (interfaces) the use cases need from the outside world."""
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
|
from typing import TypeAlias
|
||||||
|
|
||||||
from scrape_movies.domain.story import Story
|
from scrape_movies.domain.story import Story
|
||||||
|
|
||||||
## Fetches the HTML text of a page address.
|
## Fetches the HTML text of a page address.
|
||||||
type HtmlFetcher = Callable[[str], str]
|
HtmlFetcher: TypeAlias = Callable[[str], str]
|
||||||
## Turns Hacker News HTML into stories.
|
## Turns Hacker News HTML into stories.
|
||||||
type StoryParser = Callable[[str], list[Story]]
|
StoryParser: TypeAlias = Callable[[str], list[Story]]
|
||||||
|
|||||||
@@ -1,27 +1,31 @@
|
|||||||
"""@brief The Story entity (a Hacker News article) and the top-story rule."""
|
"""@brief The Story entity (a Hacker News article) and the top-story rule."""
|
||||||
|
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Story:
|
class Story:
|
||||||
"""@brief An article on the Hacker News front page.
|
"""@brief An article on the Hacker News front page.
|
||||||
|
|
||||||
@param title The headline.
|
@param title The headline.
|
||||||
@param link The address the headline points to.
|
@param link The address the headline points to.
|
||||||
@param upvotes The number of points; 0 when the story shows none.
|
@param upvotes The number of points; 0 when the story shows none.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
title: str
|
title: str
|
||||||
link: str
|
link: str
|
||||||
upvotes: int
|
upvotes: int
|
||||||
|
|
||||||
|
|
||||||
def top_story(stories: Sequence[Story]) -> Story | None:
|
def top_story(stories: Sequence[Story]) -> Story | None:
|
||||||
"""@brief Find the story with the most upvotes.
|
"""@brief Find the story with the most upvotes.
|
||||||
|
|
||||||
@param stories The stories in page order.
|
@param stories The stories in page order.
|
||||||
@return The first story with the highest score, or None when there are none.
|
@return The first story with the highest score, or None when there are none.
|
||||||
"""
|
"""
|
||||||
return max(stories, key=lambda story: story.upvotes, default=None)
|
best: Story | None = None
|
||||||
|
for story in stories:
|
||||||
|
if best is None or story.upvotes > best.upvotes:
|
||||||
|
best = story
|
||||||
|
return best
|
||||||
|
|||||||
Reference in New Issue
Block a user