怎样获得 GitHub 的 stars 列表
一直有一个想法:把 GitHub 上加星的仓库做成一个列表或者其他便于浏览查找的形式。今天,我就发现了这种工具。趁着午休,把它用上了,展示仓库:tianheg/stars。
该仓库中包含的这个列表是基于一个名为 starred
的 pip 包生成的,再通过 GitHub Action 持续集成,达到每天自动生成列表的目的。该仓库地址:maguowei/starred。
接下来记录整个过程:
一、
新建一个名字任意的仓库,新建文件名为 ci.yml
路径为 ~/.github/workflows/ci.yml
,并存放以下内容:
1name: update stars # GitHub Action 的名字
2on:
3 workflow_dispatch: # 为了手动部署,查看运行过程
4 schedule:
5 - cron: '00 0 * * *' # 定时:此时的时间是 08:00 CST – China Standard Time
6jobs:
7 awesome-stars:
8 name: update awesome-stars
9 runs-on: ubuntu-latest # 运行在最新的 Ubuntu 环境中,即 Ubuntu 20.04
10 steps:
11 - uses: actions/[email protected]
12 - name: Set up Python
13 uses: actions/[email protected]
14 with:
15 python-version: 3.7 # 安装 3.7 版本的 python
16 - name: Install dependencies # 更新 pip,安装 starred 包
17 run: |
18 python -m pip install --upgrade pip
19 pip install starred
20 - name: update repo
21 env:
22 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23 run: starred --username tianheg --repository stars --sort --token ${GITHUB_TOKEN} --message 'stars update by github actions cron' # 执行生成 stars 列表的操作
手动运行该 GitHub Action,即生成一个属于你自己的 stars 列表,这是我的:
二、
我们来读读 starred
的代码,地址:maguowei/starred/blob/master/starred/starred.py:
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import sys
5from io import BytesIO
6from collections import OrderedDict
7import click
8from github3 import GitHub
9from github3.exceptions import NotFoundError
10from starred import VERSION
11
12
13desc = '''# Awesome Stars [](https://github.com/sindresorhus/awesome)
15
16> A curated list of my GitHub stars! Generated by [starred](https://github.com/maguowei/starred)
17
18
19## Contents
20'''
21
22license_ = '''
23## License
24
25[]\
26(https://creativecommons.org/publicdomain/zero/1.0/)
27
28To the extent possible under law, [{username}](https://github.com/{username})\
29 has waived all copyright and related or neighboring rights to this work.
30'''
31
32html_escape_table = {
33 ">": ">",
34 "<": "<",
35}
36
37
38def html_escape(text):
39 """Produce entities within text."""
40 return "".join(html_escape_table.get(c, c) for c in text)
41
42@click.command()
43@click.option('--username', envvar='USER', help='GitHub username')
44@click.option('--token', envvar='GITHUB_TOKEN', help='GitHub token')
45@click.option('--sort', is_flag=True, help='sort by language')
46@click.option('--repository', default='', help='repository name')
47@click.option('--message', default='update stars', help='commit message')
48@click.version_option(version=VERSION, prog_name='starred')
49def starred(username, token, sort, repository, message):
50 """GitHub starred
51
52 creating your own Awesome List used GitHub stars!
53
54 example:
55 starred --username maguowei --sort > README.md
56 """
57 if repository:
58 if not token:
59 click.secho('Error: create repository need set --token', fg='red')
60 return
61 file = BytesIO()
62 sys.stdout = file
63 else:
64 file = None
65
66 gh = GitHub(token=token)
67 stars = gh.starred_by(username)
68 click.echo(desc)
69 repo_dict = {}
70
71 for s in stars:
72 language = s.language or 'Others'
73 description = html_escape(s.description).replace('\n', '') if s.description else ''
74 if language not in repo_dict:
75 repo_dict[language] = []
76 repo_dict[language].append([s.name, s.html_url, description.strip()])
77
78 if sort:
79 repo_dict = OrderedDict(sorted(repo_dict.items(), key=lambda l: l[0]))
80
81 for language in repo_dict.keys():
82 data = u' - [{}](#{})'.format(language, '-'.join(language.lower().split()))
83 click.echo(data)
84 click.echo('')
85
86 for language in repo_dict:
87 click.echo('## {} \n'.format(language.replace('#', '# #')))
88 for repo in repo_dict[language]:
89 data = u'- [{}]({}) - {}'.format(*repo)
90 click.echo(data)
91 click.echo('')
92
93 click.echo(license_.format(username=username))
94
95 if file:
96 try:
97 rep = gh.repository(username, repository)
98 readme = rep.readme()
99 readme.update(message, file.getvalue())
100 except NotFoundError:
101 rep = gh.create_repository(repository, 'A curated list of my GitHub stars!')
102 rep.create_file('README.md', 'starred initial commit', file.getvalue())
103 click.launch(rep.html_url)
104
105
106if __name__ == '__main__':
107 starred()
- 4 - 10 行是引用的类库
- 13 - 30 是生成的 README.md 中的文字叙述
- 42 - 48 是命令指示