怎样获得 GitHub 的 stars 列表
一直有一个想法:把 GitHub 上加星的仓库做成一个列表或者其他便于浏览查找的形式。今天,我就发现了这种工具。趁着午休,把它用上了,展示仓库:tianheg/stars。
该仓库中包含的这个列表是基于一个名为 starred
的 pip 包生成的,再通过
GitHub Action
持续集成,达到每天自动生成列表的目的。该仓库地址:maguowei/starred。
接下来记录整个过程:
一、
新建一个名字任意的仓库,新建文件名为 ci.yml
路径为
=~/.github/workflows/ci.yml=,并存放以下内容:
name: update stars # GitHub Action 的名字 on: workflow_dispatch: # 为了手动部署,查看运行过程 schedule: - cron: '00 0 * * *' # 定时:此时的时间是 08:00 CST – China Standard Time jobs: awesome-stars: name: update awesome-stars runs-on: ubuntu-latest # 运行在最新的 Ubuntu 环境中,即 Ubuntu 20.04 steps: - uses: actions/checkout@v1 - name: Set up Python uses: actions/setup-python@v1 with: python-version: 3.7 # 安装 3.7 版本的 python - name: Install dependencies # 更新 pip,安装 starred 包 run: | python -m pip install --upgrade pip pip install starred - name: update repo env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 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
4 import sys
5 from io import BytesIO
6 from collections import OrderedDict
7 import click
8 from github3 import GitHub
9 from github3.exceptions import NotFoundError
10 from starred import VERSION
11
12
13 desc = '''# 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
22 license_ = '''
23 ## License
24
25 []\
26 (https://creativecommons.org/publicdomain/zero/1.0/)
27
28 To 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
32 html_escape_table = {
33 ">": ">",
34 "<": "<",
35 }
36
37
38 def 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')
49 def 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
106 if __name__ == '__main__':
107 starred()
- 4 - 10 行是引用的类库
- 13 - 30 是生成的 README.md 中的文字叙述
- 42 - 48 是命令指示