手摸手制作一份 2019 年 GitHub 年度报告
前言
我们即将与 2019 挥手作别,踏入崭新的 2020。一到年末,各个平台都在整理数据,出具一份属于自己平台的「年度报告」。而对于技术人而言,如果你是一位开源爱好者,GitHub 的年度报告就是你 2019 年的技术总结。
阮一峰老师曾在科技爱好者周刊中提到「数据的力量」:
GitHub 个人页有一个日历栏目,只要当天有代码提交,那一天的小方格就会变成绿色。如果这一年,你每天编码,日历就全是绿的,否则就会有白色的小方块。所有人都可以看到这个「编码日历」。很多人为了让绿色小方格子不要中断,就会尽量每天提交代码。时间一长,真的多做了不少项目。
因此,这次年度报告我想主要针对这份「编码日历」,把你的「编码日历」组装到一张图片上展示给别人。
因为前一段时间正好在学习 GraphQL,所以将通过 GitHub 的接口 GitHub GraphQL API v4 来获取相关的用户数据。
这份年度报告涉及到的主要技术:
需求确立
在开始 Coding 之前需要先梳理一下需求。生成报告的整个流程大致如下:
因此,需要做的事包括:
- 调通 GitHub GraphQL API v4,获取到需要的数据
- 对数据进行统计整理
- 设计一份年度报告
- 结合整理后的数据生成报告,并将最终报告返回给用户
- 接入微信公众平台,走通整个流程
数据获取
何为 GraphQL?
因为要通过 GitHub GraphQL API v4 获取数据,所以先来聊聊 GraphQL。
官方对于 GraphQL 的定义是:
一种用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。
这样说很抽象,大家可能对 RESTful 比较熟悉些,那么我们就拿 GitHub REST API v3 与 GitHub GraphQL API v4 获取数据的方式做一个简单的对比,GraphQL 的特点自然就一目了然。
以获取用户数据为例,相关接口文档:
- REST API v3: Users:https://developer.github.com/v3/users/
- GraphQL API v4: User:https://developer.github.com/v4/object/user/
对于 RESTful 风格而言,自然是要发起一个 GET
请求。由于我们要获取某个指定用户的数据,所以需要在 PATH 中指定 :username
:
GET /users/:username |
请求成功后 GitHub 将会返回以下数据:
{ |
但有时我们不需要这么多的数据,我们可能只想获取用户的头像地址。在 RESTful 风格的接口下,我们无法只获取某一条数据,但对于 GraphQL 接口,我们可以发起这样一条请求:
{ |
这样一来,服务端将根据我们请求数据的格式,返回给我们对应的字段,即仅返回 user
下的 avatarUrl
数据:
{ |
在 RESTful 中,我们被迫接收服务端已组装好的数据,但 GraphQL 给了我们更多的自由,让我们可以只取所需。
除此之外,RESTful 以资源划分接口,数据之间相对离散,如果想请求不同的资源则需要发起多次请求。而 GraphQL 的数据更具整体性,资源之间以图(即 Graph 名称的由来)的形式彼此关联,一次请求即可获取多种资源。
构造 GraphQL 请求
我想要获取的数据主要有:
- 用户名
- 用户在 2019 年每日的贡献情况
- 用户 Followers 数量
根据接口文档 User 与 ContributionsCollection 可知,这些数据都在 user
中,对应的字段如下:
- 用户昵称:
name
- Followers 数量:
followers.totalCount
- 编码日历:
contributionsCollection.contributionCalendar
- 总贡献数量:
totalContributions
- 每周贡献情况:
weeks
- 每日贡献情况:
contributionDays
- 当天日历颜色:
color
- 当天贡献数:
contributionCount
- 当天日期:
date
- 当天日历颜色:
- 每日贡献情况:
- 总贡献数量:
因此,可以构造出如下 query
:
query = """ |
构造好 query
后,我们使用 requests
发起请求:
import requests |
若请求成功,GitHub 会返回如下格式的 JSON 数据:
{ |
数据统计
我主要针对 weeks
做了一些简单的数据统计。主要包括:
- 有提交代码的天数(
contributionCount > 0
) - 连续提交代码的最大天数
- 完成贡献次数最多的日期
这些数据对 weeks
进行一次遍历即可得出,在此不多做赘述。
设计报告
作为一个后端开发,真的没有多少设计天赋,说多了都是泪……
整份报告大致分成三个区域:
- 头部 Title
- Title 下的「编码日历」
- 中间部分显示一些分析数据
- 底部宣示主权
反反复复改了多版,询问了很多朋友的意见,最后的结果依旧不是很好看……
数据拼接
报告设计完成以后就可以把最终要展示的数据拼接到报告上了。
绘制「编码日历」
在遍历 weeks
统计数据的过程中,可以顺便完成「编码日历」的绘制。
「编码日历」中的每一天就是一个小方块,方块的颜色我们已经从接口返回数据的 color
字段中获取到了。我选择使用 line()
绘制一条颜色为 color
的直线代表方块,把直线的 width
加粗,以获得方块的效果。
from PIL import Image, ImageDraw |
粘贴文字
报告的其他部分就主要是文字内容了,设置好字体、颜色等,使用 text()
在指定位置贴上文字。
from PIL import ImageFont |
接入公众号
公众号方面直接使用了开发框架 WeRoBot。
设定:当用户发送信息为「2019 $github_id」时触发生成年度报告。
import werobot |
生成年度报告后,我们使用微信的新增临时素材接口上传报告图片,并获取到临时素材的编号 media_id
:
from werobot.client import Client |
然后,我们再将这一图片信息返回给用户:
from werobot.replies import ImageReply |
结果展示
当用户在公众号发送 2019+空格+github_id
时,将返回 github_id
所对应的报告。最终生成的报告如下:
源码见 GitHub 仓库:https://github.com/JalanJiang/2019-github-annual-report
接入的服务器为辣鸡配置,还请各位大佬手下留情。
总结
整个过程涉及到微信公众号和 GitHub 接口的调用,用户从输入到数据返回需要等待几秒的时间。为了避免超时的尴尬情况,这里只对用户提交记录做了简单的分析。
在完成这个项目的过程中几度因为设计出的报告太丑而想要放弃,感谢几位朋友一直鼓励我、给我提出修改意见才让我坚持了下来。
2019 年再见啦,希望 2020 年能尝试更多有趣的事情。:)
- 本文链接:http://jalan.space/2019/12/31/2019/2019-github-annual-report/
- 版权声明:本博客所有文章除特别声明外,均采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。
分享