【github】主页显示star和fork
- 数据收集:定期(例如每天)获取你所有仓库的 Star 和 Fork 总数。
- 数据存储:将收集到的数据(时间戳、总 Star 数、总 Fork 数)存储起来。
- 图表生成:根据存储的数据生成变化曲线图(通常是 SVG 或 PNG 格式)。
- 自动更新:使用 GitHub Actions 自动化上述过程,并将生成的图表提交到你的主页仓库。
- README 展示:在
用户名/用户名/README.md
中引用生成的图表。
下面是一个比较详细的方案,以 Python 和 Matplotlib 为例,并结合 GitHub Actions:
方案:使用 GitHub Actions + Python + Matplotlib
1. 项目结构 (在你的 用户名/用户名
仓库中)
.
├── .github/
│ └── workflows/
│ └── update_stats.yml # GitHub Actions 配置文件
├── scripts/
│ └── generate_chart.py # Python 脚本
├── data/
│ └── stats_history.csv # 存储历史数据
├── images/ # 存储生成的图表
│ └── stars_chart.svg
│ └── forks_chart.svg
└── README.md
2. Python 脚本 (scripts/generate_chart.py
)
这个脚本会:
- 从 GitHub API 获取当前所有仓库的 Star 和 Fork 总数。
- 读取
data/stats_history.csv
中的历史数据。 - 将新数据追加到 CSV 文件。
- 使用 Matplotlib 生成 Star 和 Fork 变化曲线图,并保存为 SVG。
import os
import requests
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates# --- 配置 ---
GITHUB_USERNAME = os.environ.get("GITHUB_ACTOR") # 从 GitHub Actions 环境变量获取用户名
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN") # GitHub Actions 会自动提供
STATS_FILE = "data/stats_history.csv"
STARS_CHART_FILE = "images/stars_chart.svg"
FORKS_CHART_FILE = "images/forks_chart.svg"# --- 1. 获取当前 Star 和 Fork 总数 ---
def get_total_stats():total_stars = 0total_forks = 0page = 1while True:url = f"https://api.github.com/users/{GITHUB_USERNAME}/repos?per_page=100&page={page}"headers = {"Authorization": f"token {GITHUB_TOKEN}"}response = requests.get(url, headers=headers)response.raise_for_status() # 如果请求失败则抛出异常repos = response.json()if not repos:breakfor repo in repos:total_stars += repo["stargazers_count"]total_forks += repo["forks_count"]page += 1return total_stars, total_forks# --- 2. 加载/更新历史数据 ---
def update_stats_history(stars, forks):today = datetime.now().strftime("%Y-%m-%d")new_data = {"date": [today], "total_stars": [stars], "total_forks": [forks]}new_df = pd.DataFrame(new_data)if os.path.exists(STATS_FILE):history_df = pd.read_csv(STATS_FILE)# 如果今天的数据已存在,则更新它,否则追加if today in history_df["date"].values:history_df.loc[history_df["date"] == today, ["total_stars", "total_forks"]] = [stars, forks]else:history_df = pd.concat([history_df, new_df], ignore_index=True)else:os.makedirs(os.path.dirname(STATS_FILE), exist_ok=True)history_df = new_dfhistory_df["date"] = pd.to_datetime(history_df["date"]) # 确保日期是 datetime 类型history_df = history_df.sort_values(by="date") # 按日期排序history_df["date"] = history_df["date"].dt.strftime("%Y-%m-%d") # 转回字符串保存history_df.to_csv(STATS_FILE, index=False)return pd.read_csv(STATS_FILE, parse_dates=["date"]) # 返回解析日期后的 DataFrame 用于绘图# --- 3. 生成图表 ---
def generate_plot(df, column, title, filename):plt.style.use('seaborn-v0_8-darkgrid') # 使用一个好看的样式fig, ax = plt.subplots(figsize=(10, 5)) # 调整图像大小ax.plot(df["date"], df[column], marker='o', linestyle='-', color='skyblue', linewidth=2, markersize=5)# 设置标题和标签ax.set_title(f"{GITHUB_USERNAME}'s {title} Over Time", fontsize=16, color='white')ax.set_xlabel("Date", fontsize=12, color='lightgray')ax.set_ylabel(title, fontsize=12, color='lightgray')# 美化日期格式ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))ax.xaxis.set_major_locator(mdates.AutoDateLocator(minticks=5, maxticks=10)) # 自动选择合适的日期间隔plt.xticks(rotation=30, ha='right', color='lightgray')plt.yticks(color='lightgray')# 设置背景和边框颜色fig.patch.set_facecolor('#24292e') # GitHub 暗色背景ax.set_facecolor('#2d333b')ax.spines['top'].set_visible(False)ax.spines['right'].set_visible(False)ax.spines['bottom'].set_color('gray')ax.spines['left'].set_color('gray')ax.tick_params(axis='x', colors='lightgray')ax.tick_params(axis='y', colors='lightgray')plt.grid(True, linestyle='--', alpha=0.5, color='gray') # 网格线plt.tight_layout() # 自动调整子图参数,使其填充整个图像区域os.makedirs(os.path.dirname(filename), exist_ok=True)plt.savefig(filename, facecolor=fig.get_facecolor(), transparent=False) # 保存 SVGplt.close()print(f"Chart saved to {filename}")# --- Main ---
if __name__ == "__main__":if not GITHUB_USERNAME or not GITHUB_TOKEN:print("Error: GITHUB_ACTOR and GITHUB_TOKEN environment variables must be set.")exit(1)current_stars, current_forks = get_total_stats()print(f"Current total stars: {current_stars}, total forks: {current_forks}")history_df = update_stats_history(current_stars, current_forks)generate_plot(history_df, "total_stars", "Total Stars", STARS_CHART_FILE)generate_plot(history_df, "total_forks", "Total Forks", FORKS_CHART_FILE)print("Stats updated and charts generated successfully!")
3. GitHub Actions Workflow (.github/workflows/update_stats.yml
)
这个 workflow 会:
- 每天定时运行(或手动触发)。
- Checkout 代码。
- 设置 Python 环境并安装依赖。
- 运行
generate_chart.py
脚本。 - 提交并推送更新后的
stats_history.csv
和图表文件。
name: Update Profile Stats Chartson:schedule:- cron: '0 0 * * *' # 每天午夜 UTC 时间运行workflow_dispatch: # 允许手动触发jobs:update_charts:runs-on: ubuntu-latestpermissions:contents: write # 需要写入权限来提交文件actions: read # GITHUB_TOKEN 默认有 actions:read# GITHUB_TOKEN 默认也有 contents:read# 显式声明可以确保权限steps:- name: Checkout repositoryuses: actions/checkout@v4- name: Set up Pythonuses: actions/setup-python@v5with:python-version: '3.x'- name: Install dependenciesrun: |python -m pip install --upgrade pippip install requests pandas matplotlib- name: Run script to generate chartsenv:GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 由 GitHub Actions 自动提供# GITHUB_ACTOR 会自动设置为触发 workflow 的用户,即你自己run: python scripts/generate_chart.py- name: Commit and push changesrun: |git config --local user.email "action@github.com"git config --local user.name "GitHub Action"# 检查是否有文件变动if ! git diff --quiet data/stats_history.csv images/stars_chart.svg images/forks_chart.svg; thengit add data/stats_history.csv images/stars_chart.svg images/forks_chart.svggit commit -m "📊 Update profile stats charts and data"git pushelseecho "No changes to commit."fi
4. 在 README.md 中展示图表
在你的 用户名/用户名/README.md
文件中添加以下内容:
### 🚀 My GitHub Stats Over Time**Total Stars ⭐**
<p align="center"><img src="./images/stars_chart.svg" alt="My Total Stars History" />
</p>**Total Forks 🍴**
<p align="center"><img src="./images/forks_chart.svg" alt="My Total Forks History" />
</p><!-- 你也可以使用 GitHub 的缓存来避免浏览器缓存问题,但通常直接引用仓库内路径更好 -->
<!-- <img src="https://raw.githubusercontent.com/你的用户名/你的用户名/你的分支名/images/stars_chart.svg" /> -->
确保分支名正确,通常是 main
或 master
。
设置步骤:
- 创建文件和目录:在你的
用户名/用户名
仓库中,按照上面的项目结构创建scripts/generate_chart.py
,.github/workflows/update_stats.yml
。data/
和images/
目录会在脚本第一次运行时自动创建(如果它们不存在且脚本有创建权限)。 - 修改
GITHUB_USERNAME
(可选): 脚本中的GITHUB_USERNAME = os.environ.get("GITHUB_ACTOR")
会自动获取你的用户名。如果想硬编码,可以修改。 - 提交并推送这些新文件 到你的 GitHub 仓库。
- 触发 Workflow:
- 你可以等待
cron
计划的下一次运行。 - 或者,进入你的仓库 -> Actions 标签页 -> 找到 “Update Profile Stats Charts” workflow -> 点击 “Run workflow” 手动触发一次。
- 你可以等待
- 检查结果:
- Workflow 运行成功后,
data/stats_history.csv
文件应该会被创建/更新。 images/stars_chart.svg
和images/forks_chart.svg
应该会被生成。- 这些文件会被自动 commit 和 push 到你的仓库。
- 你的 README.md 应该会显示这些图表。
- Workflow 运行成功后,
“Fancy” 提示:
- Matplotlib 样式:
plt.style.use()
可以使用很多内置样式 (ggplot
,seaborn-v0_8-darkgrid
,fivethirtyeight
等)。你也可以自定义颜色、字体、线条粗细等。 - SVG 优势: SVG 是矢量图,放大不失真,而且可以直接用文本编辑器修改(如果你懂 SVG 语法)。
- 颜色主题: 可以根据你的 GitHub 主页主题(亮色/暗色)调整图表的背景色、文字颜色等。上面脚本中的颜色是为暗色主题优化的。
- 平滑曲线: 可以使用
scipy.interpolate.make_interp_spline
等库来生成更平滑的曲线,但这会增加脚本的复杂性。 - 渐变填充: Matplotlib 也支持在曲线下方进行渐变颜色填充,可以让图表更美观。
注意事项:
- API Rate Limits: GitHub API 有速率限制。对于个人用户,通常是每小时 5000 次请求(使用
GITHUB_TOKEN
)。获取所有仓库信息通常只需要几次请求(取决于你有多少仓库,per_page=100
)。每天运行一次脚本是完全没问题的。 - 首次运行: 第一次运行时,
stats_history.csv
不存在,图表上只有一个数据点。随着时间推移,曲线才会显现。 - 安全性:
GITHUB_TOKEN
是由 GitHub Actions 自动提供的,并且具有适当的权限,无需手动创建。 - 分支保护: 如果你的主分支受保护,你可能需要调整 GitHub Actions 的权限或分支保护规则,以允许 Action 推送更改。