#!/usr/bin/env python3
"""Parse GitHub Trending page via curl + regex.
Use this when browser_navigate to GitHub trending fails (CDP timeout).
Write to /tmp/parse_trending.py, then run: python3 /tmp/parse_trending.py
Usage:
python3 /tmp/parse_trending.py # daily trending (default)
python3 /tmp/parse_trending.py weekly # this week
python3 /tmp/parse_trending.py monthly # this month
Output: JSON array of repo objects.
"""
import subprocess, re, json, sys
since = sys.argv[1] if len(sys.argv) > 1 else "daily"
url = f"https://github.com/trending?since={since}"
result = subprocess.run(['curl', '-s', url], capture_output=True, text=True)
html = result.stdout
# Find all article elements (each is a trending repo card)
articles = re.findall(r']*>(.*?)', html, re.DOTALL)
results = []
for art in articles:
# Extract repo name from h2 > a href=\"/owner/repo\"
# ⚠️ The FIRST in is often a /sponsors/ or /login? link, NOT the repo.
# Skip any href starting with "sponsors/" or "login?".
h2_section = re.search(r']*>(.*?)
', art, re.DOTALL)
if h2_section:
repo_hrefs = re.findall(r'href=\"/[^\"#]+/[^\"]+\"', h2_section.group(1))
# Pick the first href that is NOT a sponsors or login link
name = ''
for href in repo_hrefs:
href_val = href.split('"')[1] # extract value from href="..."
if not href_val.startswith('/sponsors/') and not href_val.startswith('/login?'):
name = href_val.lstrip('/')
break
else:
# Fallback: scan the whole article
all_hrefs = re.findall(r'href=\"/[^\"#]+/[^\"]+\"', art)
for href in all_hrefs:
href_val = href.split('"')[1]
if not href_val.startswith('/sponsors/') and not href_val.startswith('/login?'):
name = href_val.lstrip('/')
break
else:
name = ''
# Extract description from
]*>(.*?)
', art, re.DOTALL)
desc = desc_match.group(1).strip() if desc_match else ''
# Extract total stars from stargazers link
stars_match = re.search(r'href=\"[^\"]*stargazers\"[^>]*>\s*(.*?)\s*', art, re.DOTALL)
stars = ''
if stars_match:
s = stars_match.group(1).strip()
s = re.sub(r'[,\s]', '', s)
stars = s
# Extract language (known languages only)
lang_match = re.search(
r']*>(TypeScript|Python|JavaScript|Rust|Go|C\+\+|Java|Kotlin|Swift|Ruby|PHP|Shell|HTML|CSS|Jupyter Notebook)',
art
)
lang = lang_match.group(1) if lang_match else ''
# Extract stars today / this week / this month
stars_period = ''
for span in re.finditer(r']*>(.*?)', art, re.DOTALL):
t = span.group(1).strip()
if 'stars today' in t or 'stars this week' in t or 'stars this month' in t:
stars_period = t
if name:
results.append({
'name': name,
'desc': desc,
'stars': stars,
'lang': lang,
'starsPeriod': stars_period,
})
print(json.dumps(results, ensure_ascii=False, indent=2))