MIL-003: scraping Hacker News #37

Merged
Tirsvad merged 9 commits from mil-003-hacker-news into main 2026-10-28 07:24:45 +01:00
2 changed files with 34 additions and 29 deletions
Showing only changes of commit 72369d6537 - Show all commits
+3 -2
View File
@@ -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]]
+31 -27
View File
@@ -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