├── .gitignore ├── LICENSE ├── README.md ├── code_statistics.py ├── day.py ├── month.py ├── requirements.txt ├── run.sh ├── template ├── 周统计模板.xlsx └── 月统计模板.xlsx └── week.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Mario 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitLab 开发者代码提交量统计 2 | 统计 GitLab 所有开发者代码提交情况,按删除、新增、总计、次数四个维度展示,支持日、月、周三种时间范围,自动将统计结果推送钉钉群 3 | 4 | 5 | ### 使用说明 6 | 1. 安装需要的支持库 7 | `pip install -r requirements.txt` 8 | 9 | 2. 修改 `code_statistics.py` 文件 L13-L24 内容以及 `day.py、month.py、week.py` 三个文件的倒数第二行内容,最后运行即可,这三个文件分别对应 日、月、周三个统计时间范围,需要统计哪个时间就运行哪个脚本 10 | 11 | 12 | ### 自动运行 13 | Linux 设置 crontab 定时任务即可 14 | 15 | ```bash 16 | 50 20 * * 1-6 bash run.sh day.py 17 | 00 21 * * 7 bash run.sh week.py 18 | 30 10 2 1-12 * bash run.sh month.py 19 | ``` 20 | 21 | 22 | ### 已知问题 23 | 1. 统计人数超过 25 人,Excel模板排版会有问题,因为数据直接由Excel处理的,所以需要拖下表格让他支持更多行 24 | -------------------------------------------------------------------------------- /code_statistics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # coding=utf8 3 | # @Author: Mario 4 | # @Date : 2021/01/01 5 | # @Desc : GitLab 按时间查看各用户代码提交量官方API版(钉钉推送版) 6 | 7 | import datetime 8 | import json 9 | 10 | import requests 11 | from dateutil.parser import parse 12 | 13 | # 需修改如下四条信息 14 | gitlab_url = "" # GitLab 地址 15 | private_token = "" # GitLab Access Tokens(管理员权限) 16 | report_path = "/data/" # 生成的报告文件存放目录 17 | dingding_token = "" # 钉钉机器人token 18 | 19 | info_master = [] 20 | info_other = [] 21 | statistics = {} 22 | 23 | # 需要去除的统计的 Git 用户名 24 | exclude_names = ["Administrator",] 25 | 26 | headers = { 27 | 'Connection': 'close', 28 | } 29 | 30 | 31 | # UTC时间转时间戳 32 | def utc_time(time): 33 | dt = parse(time) 34 | return int(dt.timestamp()) 35 | 36 | 37 | # 根据日期获取星期 38 | def get_week_num(date): 39 | week = datetime.datetime.strptime(date, "%Y-%m-%d").weekday() + 1 40 | if week == 1: 41 | return "周一" 42 | elif week == 2: 43 | return "周二" 44 | elif week == 3: 45 | return "周三" 46 | elif week == 4: 47 | return "周四" 48 | elif week == 5: 49 | return "周五" 50 | elif week == 6: 51 | return "周六" 52 | else: 53 | return "周日" 54 | 55 | 56 | # 获取 GitLab 上的所有项目 57 | def gitlab_projects(project_kind): 58 | project_ids = [] 59 | page = 1 60 | while True: 61 | url = gitlab_url + "api/v4/projects/?private_token=" + private_token + "&page=" + str(page) + "&per_page=20" 62 | while True: 63 | try: 64 | res = requests.get(url, headers=headers, timeout=10) 65 | break 66 | except Exception as e: 67 | print(e) 68 | continue 69 | projects = json.loads(res.text) 70 | if len(projects) == 0: 71 | break 72 | else: 73 | for project in projects: 74 | if project["namespace"]["kind"] != project_kind or project["archived"]: # 统计哪种类型未归档的仓库 user、group 75 | continue 76 | else: 77 | # print(project["namespace"]["name"] + " ID:" + str(project["id"]) + " 描述:" + project["description"]) 78 | project_ids.append(project["id"]) 79 | page += 1 80 | print("共获取到 " + str(len(project_ids)) + " 个有效项目") 81 | return project_ids 82 | 83 | 84 | # 获取 GitLab 上的项目 id 中的分支 85 | def project_branches(project_id): 86 | branch_names = [] 87 | page = 1 88 | while True: 89 | url = gitlab_url + "api/v4/projects/" + str( 90 | project_id) + "/repository/branches?private_token=" + private_token + "&page=" + str(page) + "&per_page=20" 91 | while True: 92 | try: 93 | res = requests.get(url, headers=headers, timeout=10) 94 | break 95 | except Exception as e: 96 | print(e) 97 | continue 98 | branches = json.loads(res.text) 99 | if len(branches) == 0: 100 | break 101 | else: 102 | for branch in branches: 103 | branch_names.append(branch["name"]) 104 | page += 1 105 | return branch_names 106 | 107 | 108 | # 获取 GitLab 上的项目分支中的 commits,当 title 或 message 首单词为 Merge 时,表示合并操作,剔除此代码量 109 | def project_commits(project_id, branch, start_time, end_time): 110 | commit_ids = [] 111 | page = 1 112 | while True: 113 | url = gitlab_url + "api/v4/projects/" + str( 114 | project_id) + "/repository/commits?ref_name=" + branch + "&private_token=" + private_token + "&page=" + str( 115 | page) + "&per_page=20" 116 | while True: 117 | try: 118 | res = requests.get(url, headers=headers, timeout=10) 119 | break 120 | except Exception as e: 121 | print(e) 122 | continue 123 | commits = json.loads(res.text) 124 | if len(commits) == 0: 125 | break 126 | else: 127 | for commit in commits: 128 | if "Merge" in commit["title"] or "Merge" in commit["message"] or "合并" in commit["title"] or "合并" in \ 129 | commit["message"]: # 不统计合并操作 130 | continue 131 | elif utc_time(commit["authored_date"]) < utc_time(start_time) or utc_time( 132 | commit["authored_date"]) > utc_time(end_time): # 不满足时间区间 133 | continue 134 | else: 135 | commit_ids.append(commit["id"]) 136 | page += 1 137 | return commit_ids 138 | 139 | 140 | # 根据 commits 的 id 获取代码量,type: 1 为主分支,2为其他分支 141 | def commit_code(project_id, commit_id, branch_type): 142 | global info_master, info_other 143 | url = gitlab_url + "api/v4/projects/" + str( 144 | project_id) + "/repository/commits/" + commit_id + "?private_token=" + private_token 145 | while True: 146 | try: 147 | res = requests.get(url, headers=headers, timeout=10) 148 | break 149 | except Exception as e: 150 | print(e) 151 | continue 152 | data = json.loads(res.text) 153 | obj = {"name": data["author_name"], "additions": data["stats"]["additions"], 154 | "deletions": data["stats"]["deletions"], "total": data["stats"]["total"]} # Git工具用户名,新增代码数,删除代码数,总计代码数 155 | if data["author_name"] not in exclude_names: # 去除不需要统计的Git用户名 156 | if branch_type == 1: 157 | info_master.append(obj) 158 | elif branch_type == 2: 159 | info_other.append(obj) 160 | # else: 161 | # do some things 162 | 163 | 164 | # GitLab 数据查询 165 | def gitlab_info(start_time, end_time, project_kind): 166 | for project_id in gitlab_projects(project_kind): # 遍历所有项目ID 167 | for branch_name in project_branches(project_id): # 遍历每个项目中的分支 168 | if branch_name == "master" and project_kind != "user": # 主分支(个人仓直接统计全部) 169 | for commit_id in project_commits(project_id, branch_name, start_time, end_time): # 遍历每个分支中的 commit id 170 | commit_code(project_id, commit_id, 1) # 获取代码提交量 171 | else: # 其他分支 172 | for commit_id in project_commits(project_id, branch_name, start_time, end_time): 173 | commit_code(project_id, commit_id, 2) # 获取代码提交量 174 | 175 | 176 | # 统计数据处理 177 | def gitlab_statistics_data(branch_type): 178 | global statistics 179 | statistics.clear() 180 | 181 | name = [] # Git工具用户名 182 | additions = [] # 新增代码数 183 | deletions = [] # 删除代码数 184 | total = [] # 总计代码数 185 | times = [] # 提交次数 186 | 187 | if branch_type == 1: 188 | info = info_master 189 | elif branch_type == 2: 190 | info = info_other 191 | # else 192 | # do some things 193 | 194 | for i in info: 195 | for key, value in i.items(): 196 | if key == "name": 197 | name.append(value) 198 | if key == "additions": 199 | additions.append(value) 200 | if key == "deletions": 201 | deletions.append(value) 202 | if key == "total": 203 | total.append(value) 204 | times.append(1) # 提交次数 205 | array = list(zip(name, additions, deletions, total, times)) 206 | # print(array) 207 | 208 | # 去重累加 209 | for j in array: 210 | name = j[0] 211 | additions = j[1] 212 | deletions = j[2] 213 | total = j[3] 214 | times = j[4] 215 | if name in statistics.keys(): 216 | statistics[name][0] += additions 217 | statistics[name][1] += deletions 218 | statistics[name][2] += total 219 | statistics[name][3] += times 220 | else: 221 | statistics.update({name: [additions, deletions, total, times]}) 222 | # else: 223 | # do some things 224 | return statistics 225 | 226 | 227 | # 代码统计内容列表处理 228 | def gitlab_statistics_content(file_name): 229 | for i in statistics.keys(): 230 | content_save("" + str(i) + "" + str(statistics[i][0]) + "" + str( 231 | statistics[i][1]) + "" + str(statistics[i][2]) + "" + str( 232 | statistics[i][3]) + "", "a", file_name) 233 | 234 | 235 | # 保存数据到文件 236 | def content_save(data, mode, file_name): 237 | file = open(report_path + "/" + file_name, mode, encoding='utf-8') 238 | file.write(data) 239 | file.close() 240 | 241 | 242 | # 钉钉通知 243 | def dingding(url, imgurl, mes): 244 | content = { 245 | "msgtype": "actionCard", 246 | "actionCard": { 247 | "title": "GitLab代码提交量统计[]", 248 | "text": "![](" + imgurl + ")GitLab代码提交量统计" + mes, 249 | "hideAvatar": "0", 250 | "btnOrientation": "0", 251 | "singleTitle": "点击查看详情", 252 | "singleURL": url 253 | } 254 | } 255 | json_headers = {'Content-Type': 'application/json;charset=utf-8'} 256 | result = requests.post("https://oapi.dingtalk.com/robot/send?access_token=" + dingding_token, json.dumps(content), 257 | headers=json_headers).text 258 | print(result) 259 | -------------------------------------------------------------------------------- /day.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from code_statistics import * 4 | 5 | imgurl = "https://ae01.alicdn.com/kf/U56b2fb24ff7b4e5fa05c5acf7d3d0318r.jpg" 6 | file_name = "day.html" 7 | 8 | if __name__ == "__main__": 9 | print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " [日]") 10 | time1 = time.strftime("%Y-%m-%d 00:00:00") # 开始时间 11 | time2 = time.strftime("%Y-%m-%d 23:59:59") # 结束时间 12 | 13 | # header1 14 | content_save( 15 | "GitLab代码提交量统计

GitLab代码提交量统计(单位:行) 【日报】


注:统计将会剔除所有合并操作
上次更新时间:" + time.strftime( 16 | "%Y-%m-%d %H:%M:%S", 17 | time.localtime()) + "

群组仓库

个人仓库

", "a", file_name) 45 | 46 | dingding("http://localhost/" + file_name, imgurl, "[日报]") # 不需要推送可以注释掉 47 | print("http://localhost/" + file_name) 48 | -------------------------------------------------------------------------------- /month.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # coding=utf8 3 | # GitLab 月代码提交详细统计 4 | 5 | import shutil 6 | import time 7 | 8 | from openpyxl import load_workbook 9 | 10 | from code_statistics import * 11 | 12 | imgurl = "https://ae01.alicdn.com/kf/Uc321eb139bc944989428170e74e9e957W.jpg" 13 | Template_Path = "template/月统计模板.xlsx" # 模板路径 14 | Save_Path = report_path + "/month-group.xlsx" # 保存路径 15 | 16 | date_list = [] # 日期列表 17 | name_list = [] # Git用户名列表 18 | daily_master_statistics = {} # 每日详情数据 19 | daily_dev_statistics = {} 20 | 21 | 22 | # 获取上月日期列表 23 | def get_month_list(): 24 | global date_list 25 | today = datetime.date.today() # 获取当前日期 26 | year = today.year 27 | month = today.month 28 | 29 | # 上月第一天和最后一天 30 | if month == 1: 31 | last_month_start = datetime.date(year - 1, 12, 1) 32 | else: 33 | last_month_start = datetime.date(year, month - 1, 1) 34 | last_month_end = datetime.date(year, month, 1) - datetime.timedelta(1) 35 | 36 | # 遍历上月每一天日期 37 | while last_month_start <= last_month_end: 38 | date_list.append(str(last_month_start)) 39 | last_month_start += datetime.timedelta(1) 40 | 41 | 42 | # 获取Git用户名列表 43 | def get_user_list(date, dictionary): 44 | global name_list 45 | for name in dictionary[date].keys(): 46 | if name in name_list: 47 | continue 48 | else: 49 | name_list.append(name) 50 | 51 | 52 | # 生成每日统计数据 53 | def get_gitlab_daily(start_time, end_time, date): 54 | global daily_dev_statistics, daily_master_statistics 55 | gitlab_info(start_time, end_time, "group") # 群组仓库统计 56 | 57 | # 收集数据 58 | daily_master_statistics[date] = gitlab_statistics_data(1).copy() # master 59 | print("master: ", daily_master_statistics) 60 | 61 | daily_dev_statistics[date] = gitlab_statistics_data(2).copy() # dev 62 | print("dev: ", daily_dev_statistics) 63 | 64 | # 清空数据,准备下一轮循环 65 | info_master.clear() 66 | info_other.clear() 67 | 68 | # 收集Git用户名 69 | get_user_list(date, daily_master_statistics) 70 | get_user_list(date, daily_dev_statistics) 71 | 72 | 73 | # 数据处理写入到excel文件(表面,项目分支名) 74 | def wirte_excel(sheet, branch_type): 75 | wb = load_workbook(Save_Path) 76 | ws_master = wb[sheet] # 访问指定工作表 77 | 78 | if branch_type == "master": 79 | temp = daily_master_statistics 80 | else: 81 | temp = daily_dev_statistics 82 | 83 | # 写入日期到表格 84 | i = 2 # 列 85 | for date in date_list: 86 | ws_master.cell(row=1, column=i, value=date + " (" + get_week_num(date) + ")") 87 | i += 4 88 | 89 | # 写入统计内容到表格 90 | j = 3 # 行 91 | for name in name_list: 92 | k = 2 # 列 93 | # 列写入姓名 94 | ws_master.cell(row=j, column=1, value=name) 95 | for date in date_list: 96 | # 如果有代码提交记录 97 | if name in temp[date].keys(): 98 | ws_master.cell(row=j, column=k, value=temp[date][name][0]) 99 | ws_master.cell(row=j, column=k + 1, value=temp[date][name][1]) 100 | ws_master.cell(row=j, column=k + 2, value=temp[date][name][2]) 101 | ws_master.cell(row=j, column=k + 3, value=temp[date][name][3]) 102 | else: 103 | ws_master.cell(row=j, column=k, value=0) 104 | ws_master.cell(row=j, column=k + 1, value=0) 105 | ws_master.cell(row=j, column=k + 2, value=0) 106 | ws_master.cell(row=j, column=k + 3, value=0) 107 | # 下一列 108 | k += 4 109 | # 下一行 110 | j += 1 111 | wb.save(Save_Path) 112 | 113 | 114 | if __name__ == "__main__": 115 | print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " [月详细-群组仓]") 116 | get_month_list() # 生成上月日期列表 117 | print(date_list) 118 | 119 | # 获取数据中。。。 120 | for date in date_list: 121 | time1 = date + " 00:00:00" # 开始时间 122 | time2 = date + " 23:59:59" # 结束时间 123 | print("\n", time1, time2) 124 | get_gitlab_daily(time1, time2, date) 125 | 126 | shutil.copy(Template_Path, Save_Path) # 拷贝模板 127 | 128 | wirte_excel("master", "master") # master 129 | wirte_excel("dev", "dev") # dev 130 | 131 | dingding("http://localhost/month-group.xlsx", imgurl, "[月]详细统计仅群组仓 👉点击下载") # 不需要推送可以注释掉 132 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2020.11.8 2 | chardet==3.0.4 3 | et-xmlfile==1.0.1 4 | idna==2.10 5 | jdcal==1.4.1 6 | openpyxl==3.0.5 7 | python-dateutil==2.8.1 8 | python-gitlab==2.5.0 9 | requests==2.25.0 10 | six==1.15.0 11 | urllib3==1.26.2 12 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!bin/bash 2 | cd /root/GitLab 3 | python -u $1 >> run_info.log 4 | -------------------------------------------------------------------------------- /template/周统计模板.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fog-Forest/code-statistics/820766e792aa3a0f5abda9a085441a8c650038fc/template/周统计模板.xlsx -------------------------------------------------------------------------------- /template/月统计模板.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fog-Forest/code-statistics/820766e792aa3a0f5abda9a085441a8c650038fc/template/月统计模板.xlsx -------------------------------------------------------------------------------- /week.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # coding=utf8 3 | # GitLab 周代码提交详细统计 4 | 5 | import shutil 6 | import time 7 | 8 | from openpyxl import load_workbook 9 | 10 | from code_statistics import * 11 | 12 | imgurl = "https://ae01.alicdn.com/kf/U950a6ec6d17d4bd7b37afe16959d7cbdO.jpg" 13 | Template_Path = "template/周统计模板.xlsx" # 模板路径 14 | Save_Path = report_path + "/week-group.xlsx" # 保存路径 15 | 16 | date_list = [] # 日期列表 17 | name_list = [] # Git用户名列表 18 | daily_master_statistics = {} # 每日详情数据 19 | daily_dev_statistics = {} 20 | 21 | 22 | # 获取本周日期列表 23 | def get_week_list(): 24 | global date_list 25 | # 获取当前日期 26 | today = datetime.date.today() 27 | # 本周第一天和最后一天 28 | this_week_start = today - datetime.timedelta(today.weekday()) 29 | this_week_end = today + datetime.timedelta(6 - today.weekday()) 30 | 31 | # 遍历上月每一天日期 32 | while this_week_start <= this_week_end: 33 | date_list.append(str(this_week_start)) 34 | this_week_start += datetime.timedelta(1) 35 | 36 | 37 | # 获取Git用户名列表 38 | def get_user_list(date, dictionary): 39 | global name_list 40 | for name in dictionary[date].keys(): 41 | if name in name_list: 42 | continue 43 | else: 44 | name_list.append(name) 45 | 46 | 47 | # 生成每日统计数据 48 | def get_gitlab_daily(start_time, end_time, date): 49 | global daily_dev_statistics, daily_master_statistics 50 | gitlab_info(start_time, end_time, "group") # 群组仓库统计 51 | 52 | # 收集数据 53 | daily_master_statistics[date] = gitlab_statistics_data(1).copy() # master 54 | print("master: ", daily_master_statistics) 55 | 56 | daily_dev_statistics[date] = gitlab_statistics_data(2).copy() # dev 57 | print("dev: ", daily_dev_statistics) 58 | 59 | # 清空数据,准备下一轮循环 60 | info_master.clear() 61 | info_other.clear() 62 | 63 | # 收集Git用户名 64 | get_user_list(date, daily_master_statistics) 65 | get_user_list(date, daily_dev_statistics) 66 | 67 | 68 | # 数据处理写入到excel文件(表面,项目分支名) 69 | def wirte_excel(sheet, branch_type): 70 | wb = load_workbook(Save_Path) 71 | ws_master = wb[sheet] # 访问指定工作表 72 | 73 | if branch_type == "master": 74 | temp = daily_master_statistics 75 | else: 76 | temp = daily_dev_statistics 77 | 78 | # 写入日期到表格 79 | i = 2 # 列 80 | for date in date_list: 81 | ws_master.cell(row=1, column=i, value=date + " (" + get_week_num(date) + ")") 82 | i += 4 83 | 84 | # 写入统计内容到表格 85 | j = 3 # 行 86 | for name in name_list: 87 | k = 2 # 列 88 | # 列写入姓名 89 | ws_master.cell(row=j, column=1, value=name) 90 | for date in date_list: 91 | # 如果有代码提交记录 92 | if name in temp[date].keys(): 93 | ws_master.cell(row=j, column=k, value=temp[date][name][0]) 94 | ws_master.cell(row=j, column=k + 1, value=temp[date][name][1]) 95 | ws_master.cell(row=j, column=k + 2, value=temp[date][name][2]) 96 | ws_master.cell(row=j, column=k + 3, value=temp[date][name][3]) 97 | else: 98 | ws_master.cell(row=j, column=k, value=0) 99 | ws_master.cell(row=j, column=k + 1, value=0) 100 | ws_master.cell(row=j, column=k + 2, value=0) 101 | ws_master.cell(row=j, column=k + 3, value=0) 102 | # 下一列 103 | k += 4 104 | # 下一行 105 | j += 1 106 | wb.save(Save_Path) 107 | 108 | 109 | if __name__ == "__main__": 110 | print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " [周详细-群组仓]") 111 | get_week_list() # 生成本周日期列表 112 | print(date_list) 113 | 114 | # 获取数据中。。。 115 | for date in date_list: 116 | time1 = date + " 00:00:00" # 开始时间 117 | time2 = date + " 23:59:59" # 结束时间 118 | print("\n", time1, time2) 119 | get_gitlab_daily(time1, time2, date) 120 | 121 | shutil.copy(Template_Path, Save_Path) # 拷贝模板 122 | 123 | wirte_excel("master", "master") # master 124 | wirte_excel("dev", "dev") # dev 125 | 126 | dingding("http://localhost/week-group.xlsx", imgurl, "[周]详细统计仅群组仓 👉点击下载") # 不需要推送可以注释掉 127 | --------------------------------------------------------------------------------