├── README.md ├── api └── index.py └── requirements.txt /README.md: -------------------------------------------------------------------------------- 1 | # What's this? 2 | 3 | 此项目改造自 [python_github_calendar_api](https://github.com/Zfour/python_github_calendar_api) 仓库,原理通过 Python 获取 GitHub 的用户贡献信息,你可以部署到 Vercel 上作为 API 使用。调用方式为标准的 key-value 格式:`/api?user=Barry-Flynn`,推荐结合本文档自行部署,如果帮到你了,请给个免费的 star 鼓励支持一下我吧! 4 | 5 | 如果你有 Hexo 博客,可以搭配使用 [Barry-Flynn/hexo-github-calendar](https://github.com/Barry-Flynn/hexo-github-calendar) 插件在前端渲染贡献热力图。 6 | 7 | 8 | ## 如何部署自用的 Vercel API 9 | 10 | ### 1. 注册 Vercel 11 | 12 | 首先前往 [Vercel 官网](https://vercel.com/),点击右上角的 sign up 进行注册。 13 | 14 | ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8391485/1612880174758-059d6e22-d5ec-4478-9b8c-4a9d7c041f44.png) 15 | 16 | 极有可能遇到的 bug 17 | 18 | 若注册时提示 `Error:This user account is blocked.Contact support@vercel.com for more information.` 19 | 20 | 这是由于 `Vercel` 不支持大部分国内邮箱。可以将 `github` 账号主邮箱改为 `Gmail` 邮箱。 21 | 22 | 但是根据群友反应,将 `github` 账号主邮箱切换为 `Gmail` 以后,`Vercel` 又会提示需要使用手机号码验证。然而 `github` 并没有提供手机号码绑定的内容。 23 | 24 | 综上,建议一开始注册 `github` 账号时就使用 `Gmail` 等国外邮箱进行注册。 25 | 26 | 1. 国内访问`Gmail`的方案: 27 | 28 | - 直接使用 QQ 邮箱手机版,它提供 `Gmail` 的访问路线,可以直接注册并使用。 29 | 30 | - 使用 `Ghelper` 等浏览器插件访问。详情可以参考这篇文章:[玩转 Microsoft-Edge](https://github.com/Zfour/python_github_calendar_api/blob/master/posts/8c8df126) 31 | 32 | 2. 若是执着于当前`Github`账号,可以参考以下方案进行尝试: 33 | 34 | - 完成了 `Gmail` 等国外邮箱的注册,打开 [github-> 头像 ->settings->Emails](https://github.com/settings/emails)->Add email address, 并完成邮箱验证。 35 | - 在Add email address 下方的Primary email address 选项中将 `Gmail` 设置为主邮箱。 36 | 37 | ### 2. 新建项目,fork我的项目 38 | 39 | 打开 [dashboard](https://vercel.com/dashboard) 点击新建项目的 `New Project` 按钮。点击导入第三方库。 40 | 41 | ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8391485/1612949541795-cfe67df4-a443-4604-86fd-a34ea9c34bed.png) 42 | 43 | 44 | 45 | 填入俺提供的自建 API 项目地址: 46 | 47 | ``` 48 | https://github.com/Barry-Flynn/python_github_calendar_api 49 | ``` 50 | 51 | 52 | 53 | ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8391485/1612949577842-18cc23f8-5cf6-4f72-b892-d244d22a3089.png) 54 | 55 | 选择私有账户。点击`select`。 56 | 57 | 58 | 59 | ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8391485/1612949622863-54b72f81-9add-479d-94ed-aeb125099afe.png) 60 | 61 | 选择github按钮然后会帮你将仓库克隆到你的github中,填入自定义仓库名称,如 `python_github_calendar_api`。 62 | 63 | ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8391485/1612949755226-a97f3c75-8328-4630-91f2-2dd9dddf3665.png) 64 | 65 | 之后会识别出项目文件,单击 `Continue`。 66 | 67 | ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8391485/1612949831064-f4b2cef1-eb64-4bac-8841-b991768ffee8.png) 68 | 69 | `Vercel` 的 `PROJECT NAME` 可以自定义,不用太过在意,但是之后不支持修改,若要改名,只能删除 `PROJECT` 以后重建一个了。下方三个选项保持默认就好。 70 | 71 | 72 | ![image.png](https://cdn.nlark.com/yuque/0/2021/png/8391485/1612949883724-064103a2-658f-49cb-b1e6-f3a7f0a511d1.png) 73 | 74 | 75 | 76 | 此时点击Deploy,`Vercel` 的api部署已经完成。 77 | 78 | ### 3. 检查API是否配置成功 79 | 80 | 访问**API链接**(图中链接+'/api'+查询参数),如我的为 81 | 82 | https://python-github-calendar-api.vercel.app/api/?user=Barry-Flynn 83 | 84 | 如果显示数据则说明API配置成功。 85 | -------------------------------------------------------------------------------- /api/index.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import requests 3 | import re 4 | from http.server import BaseHTTPRequestHandler 5 | import json 6 | 7 | def list_split(items, n): 8 | return [items[i:i + n] for i in range(0, len(items), n)] 9 | def getdata(name): 10 | 11 | # 2024-03-29 定义 headers 请求头 12 | # 请见 https://github.com/yuhengwei2001/python_github_calendar_api/commit/0f37cfc003f09e99a1892602d8bc2b38137899d2#diff-b014e93fcab9bae29f453d7a616da5eac2f02947f32d02a1a1bf200eeaab5a39L11 13 | headers = { 14 | 'Referer': 'https://github.com/'+ name, 15 | 'Sec-Ch-Ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"', 16 | 'Sec-Ch-Ua-Mobile': '?0', 17 | 'Sec-Ch-Ua-Platform': '"Windows"', 18 | 'Sec-Fetch-Dest': 'empty', 19 | 'Sec-Fetch-Mode': 'cors', 20 | 'Sec-Fetch-Site': 'same-origin', 21 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0', 22 | 'X-Requested-With': 'XMLHttpRequest' 23 | } 24 | # 发送请求时添加 headers 请求头 25 | # gitpage = requests.get("https://github.com/" + name) 26 | gitpage = requests.get("https://github.com/" + name + "?action=show&controller=profiles&tab=contributions&user_id="+ name, headers=headers) 27 | data = gitpage.text 28 | 29 | # 2023-11-22 更新正则 https://github.com/Zfour/python_github_calendar_api/issues/18 30 | datadatereg = re.compile(r'data-date="(.*?)" id="contribution-day-component') 31 | datacountreg = re.compile(r'(.*?) contribution') 32 | 33 | datadate = datadatereg.findall(data) 34 | datacount = datacountreg.findall(data) 35 | datacount = list(map(int, [0 if i == "No" else i for i in datacount])) 36 | 37 | # 检查datadate和datacount是否为空 38 | if not datadate or not datacount: 39 | # 处理空数据情况 40 | return {"total": 0, "contributions": []} 41 | 42 | # 将datadate和datacount按照字典序排序 43 | sorted_data = sorted(zip(datadate, datacount)) 44 | datadate, datacount = zip(*sorted_data) 45 | 46 | contributions = sum(datacount) 47 | datalist = [] 48 | for index, item in enumerate(datadate): 49 | itemlist = {"date": item, "count": datacount[index]} 50 | datalist.append(itemlist) 51 | datalistsplit = list_split(datalist, 7) 52 | returndata = { 53 | "total": contributions, 54 | "contributions": datalistsplit 55 | } 56 | return returndata 57 | class handler(BaseHTTPRequestHandler): 58 | def do_GET(self): 59 | # 2024-03-15 规范接口的传参方式 https://github.com/Zfour/python_github_calendar_api/issues/20#issuecomment-1999115747 60 | path = self.path 61 | spl=path.split('?')[1:] 62 | for kv in spl: 63 | key,user=kv.split("=") 64 | if key=="user": break 65 | data = getdata(user) 66 | self.send_response(200) 67 | self.send_header('Access-Control-Allow-Origin', '*') 68 | self.send_header('Content-type', 'application/json') 69 | self.end_headers() 70 | self.wfile.write(json.dumps(data).encode('utf-8')) 71 | return 72 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2020.12.5 2 | chardet==4.0.0 3 | idna==2.10 4 | requests==2.25.1 5 | urllib3==1.26.2 6 | --------------------------------------------------------------------------------