Skip to content

Commit 267b003

Browse files
dreamiurgclaude
andcommitted
feat: add ascent count to peak info command
The peak info command now displays the number of ascents logged on PeakBagger.com. Shows both total ascents logged (by all registered users) and the number of viewable ascents. This information is parsed from the peak detail page, so no additional HTTP requests are required. Example output: Ascents Logged 4,388 (3,960 viewable) The ascent counts are also included in JSON output under the "ascent_count" and "viewable_ascent_count" fields. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent fd2212f commit 267b003

File tree

4 files changed

+434
-664
lines changed

4 files changed

+434
-664
lines changed

peakbagger/formatters.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ def _print_peak_detail(self, peak: Peak) -> None:
146146
if peak.country:
147147
table.add_row("Country", peak.country)
148148

149+
# Add ascent counts
150+
if peak.ascent_count is not None:
151+
ascent_text = f"{peak.ascent_count:,}"
152+
if peak.viewable_ascent_count is not None:
153+
ascent_text += f" ({peak.viewable_ascent_count:,} viewable)"
154+
table.add_row("Ascents Logged", ascent_text)
155+
149156
# Add PeakBagger URL
150157
peak_url: str = f"https://www.peakbagger.com/peak.aspx?pid={peak.pid}"
151158
table.add_row("URL", f"[blue]{peak_url}[/blue]")

peakbagger/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class Peak(BaseModel):
2525
default_factory=list, description="Peak lists with ranks"
2626
)
2727
routes: list[dict[str, Any]] = Field(default_factory=list, description="Route information")
28+
ascent_count: int | None = Field(None, description="Total number of ascents logged")
29+
viewable_ascent_count: int | None = Field(None, description="Number of viewable ascents")
2830

2931
def to_dict(self) -> dict[str, Any]:
3032
"""Convert peak to dictionary for JSON serialization."""
@@ -53,6 +55,8 @@ def to_dict(self) -> dict[str, Any]:
5355
"url": f"https://www.peakbagger.com/peak.aspx?pid={self.pid}",
5456
"peak_lists": self.peak_lists,
5557
"routes": self.routes,
58+
"ascent_count": self.ascent_count,
59+
"viewable_ascent_count": self.viewable_ascent_count,
5660
}
5761

5862

peakbagger/scraper.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,19 @@ def parse_peak_detail(html: str, pid: str) -> Peak | None:
172172
# Extract route information
173173
peak.routes = PeakBaggerScraper._extract_routes(html)
174174

175+
# Extract ascent counts
176+
# Format: "Total ascents/attempts logged by registered Peakbagger.com users: <b>4388</b>"
177+
ascent_count_match = re.search(
178+
r"Total ascents/attempts logged.*?<b>(\d+)</b>", html, re.DOTALL
179+
)
180+
if ascent_count_match:
181+
peak.ascent_count = int(ascent_count_match.group(1))
182+
183+
# Format: "(Total: 3960)"
184+
viewable_count_match = re.search(r"\(Total:\s*(\d+)\)", html)
185+
if viewable_count_match:
186+
peak.viewable_ascent_count = int(viewable_count_match.group(1))
187+
175188
return peak
176189

177190
except Exception as e:

0 commit comments

Comments
 (0)