mirror of
https://github.com/ReScienceLab/opc-skills.git
synced 2026-09-14 18:03:27 +08:00
2aedb75dba
* 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.
68 lines
2.1 KiB
Python
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))
|