feat: parse RF4DB waterbody catalog
CI / backend-and-migrations (push) Canceled after 0s
CI / astro-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s
CI / compose-e2e (push) Canceled after 0s

This commit is contained in:
ik
2026-09-15 17:19:15 +07:00
parent 75820125aa
commit 4c75db1f74
4 changed files with 107 additions and 1 deletions
+15
View File
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="ru">
<body>
<article class="map-card">
<img src="https://oss.rf4db.com/game/maps/level_001_mosquito.webp" alt="оз. Комариное">
<h3><a href="/ru/maps/level_001_mosquito">оз. Комариное</a></h3>
<dl><dt>Уровень</dt><dd>Lv.1</dd><dt>Рыбы</dt><dd>20</dd></dl>
</article>
<article class="map-card">
<img data-src="/game/maps/level_000_cottage.webp" alt="Дачный пруд">
<h3><a href="/ru/maps/level_000_cottage">Дачный пруд</a></h3>
<dl><dt>Уровень</dt><dd>Старт</dd><dt>Рыбы</dt><dd>7</dd></dl>
</article>
</body>
</html>
+23
View File
@@ -7,6 +7,7 @@ from rf4_research.community_sources import (
CommunityParseError,
parse_rf4db_catches,
parse_rf4db_detail,
parse_rf4db_waterbodies,
parse_rf4map_point,
parse_rf4posts_spot,
parse_rf4stat_fishing,
@@ -51,6 +52,28 @@ def test_rf4db_detail_rejects_unrelated_html() -> None:
parse_rf4db_detail("<html></html>", source_url="https://rf4db.com/ru/catches/id")
def test_parses_rf4db_waterbody_catalog_without_inventing_image_roles() -> None:
rows = parse_rf4db_waterbodies(fixture("rf4db_waterbodies_sample.html"), expected_count=2)
assert len(rows) == 2
assert (rows[0].source_external_id, rows[0].name) == ("level_001_mosquito", "оз. Комариное")
assert (rows[0].unlock_level, rows[0].unlock_label, rows[0].fish_species_count) == (1, "1", 20)
assert rows[0].source_url == "https://rf4db.com/ru/maps/level_001_mosquito"
assert rows[0].image_url == "https://oss.rf4db.com/game/maps/level_001_mosquito.webp"
assert (rows[1].unlock_level, rows[1].unlock_label) == (None, "Старт")
assert rows[1].image_url == "https://rf4db.com/game/maps/level_000_cottage.webp"
def test_rf4db_waterbody_catalog_rejects_unrelated_html() -> None:
with pytest.raises(CommunityParseError, match="waterbody cards not found"):
parse_rf4db_waterbodies("<html></html>")
def test_rf4db_waterbody_catalog_rejects_partial_results() -> None:
with pytest.raises(CommunityParseError, match="expected 19, got 2"):
parse_rf4db_waterbodies(fixture("rf4db_waterbodies_sample.html"))
def test_parses_rf4stat_fishing_rows() -> None:
row = parse_rf4stat_fishing(
fixture("rf4stat_fishing_sample.html"),