Files
Yilin 2aedb75dba fix(install-stats): handle abbreviated count formats (e.g. 2.8K) (#50)
* fix(install-stats): handle abbreviated count formats (e.g. 2.8K) in skills.sh scraper

The regex only matched plain digit counts (\d+), causing it to miss
abbreviated formats like '2.8K'. This led to seo-geo stealing
logo-creator's count and logo-creator being dropped entirely.

- Add _parse_count() helper to handle K-suffix abbreviations
- Update regex to capture abbreviated count patterns
- Refresh install-stats.json with correct data

* refactor(skills): align SKILL.md frontmatter with Anthropic skill standard (#51)

Remove separate 'triggers' field from all SKILL.md files and merge
trigger keywords into the 'description' field. This follows the
Anthropic skills standard (skills.sh/anthropics/skills/skill-creator)
where frontmatter only has 'name' and 'description'.

Updated: all 9 skills and the template.
2026-02-15 16:02:08 +08:00

68 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Fetch installation stats from skills.sh and output JSON."""
import json
import re
import sys
import urllib.request
SKILLS_SH_URL = "https://skills.sh/resciencelab/opc-skills"
def _parse_count(count_str):
"""Parse install count string, handling abbreviated formats like '2.8K'."""
count_str = count_str.strip().replace(",", "")
if count_str.upper().endswith("K"):
return int(float(count_str[:-1]) * 1000)
return int(count_str)
def fetch_install_stats():
"""Scrape skills.sh page and extract installation counts."""
try:
req = urllib.request.Request(
SKILLS_SH_URL,
headers={"User-Agent": "OPC-Skills-Stats-Fetcher/1.0"}
)
with urllib.request.urlopen(req, timeout=30) as response:
html = response.read().decode("utf-8")
except Exception as e:
print(f"Error fetching {SKILLS_SH_URL}: {e}", file=sys.stderr)
sys.exit(1)
# Extract per-skill installs from skill links
# Pattern: skill name followed by install count in the link structure
skills = {}
# HTML pattern: href="/resciencelab/opc-skills/{skill}">...<span...>{count}</span>
# Count can be plain digits (e.g. "380") or abbreviated (e.g. "2.8K", "5.3K")
skill_pattern = re.compile(
r'href="/resciencelab/opc-skills/([a-z0-9-]+)"[^>]*>.*?'
r'<span[^>]*class="[^"]*font-mono[^"]*"[^>]*>([\d.,]+K?)</span>',
re.IGNORECASE | re.DOTALL
)
for match in skill_pattern.finditer(html):
skill_name = match.group(1).lower()
count_str = match.group(2)
count = _parse_count(count_str)
# Skip template skill
if skill_name != "skill-name":
skills[skill_name] = count
# Calculate total from sum of individual skill installs
# This is more reliable than scraping the total from HTML
total = sum(skills.values())
result = {
"total": total,
"skills": skills,
"source": SKILLS_SH_URL
}
return result
if __name__ == "__main__":
stats = fetch_install_stats()
print(json.dumps(stats, indent=2))