Gitee仓库批量清理术:Python自动化脚本开发全指南

你是否曾在Gitee上创建了大量测试仓库,如今却成了数字空间的"垃圾山"?手动点击删除上百个仓库不仅耗时费力,还容易出错。本文将带你从零构建一个智能清理系统,用Python脚本与Gitee API对话,实现一键批量删除。

1. 前期准备:安全认证与权限配置

在开始编写脚本前,我们需要获取进入Gitee API大门的"钥匙"——个人访问令牌(Personal Access Token)。这个令牌相当于你的数字身份凭证,务必妥善保管。

获取Token的步骤

  1. 登录Gitee账号,进入"设置"→"私人令牌"
  2. 点击"生成新令牌"按钮
  3. 设置令牌描述(如"仓库清理工具")
  4. 勾选 repos 权限范围下的所有选项
  5. 点击"提交"并记录生成的令牌字符串

注意:令牌仅在生成时显示一次,丢失后需重新生成。建议立即存入密码管理器。

权限配置常见问题:

  • 若遇到403错误,检查是否遗漏了 delete_repo 权限
  • 令牌有效期默认永久,但可随时在设置页撤销
  • 企业账号可能需要管理员额外授权

2. API交互核心:请求构建与错误处理

Gitee API遵循RESTful规范,我们主要使用两个端点:

  • GET /user/repos 获取仓库列表
  • DELETE /repos/{owner}/{repo} 删除指定仓库
import requests
from time import sleep

API_BASE = "https://gitee.com/api/v5"
HEADERS = {
    "User-Agent": "Mozilla/5.0",
    "Authorization": "Bearer YOUR_TOKEN"  # 替换为实际令牌
}

健壮性增强技巧

  • 添加重试机制应对网络波动
  • 设置合理的超时时间(建议10秒)
  • 实现请求速率限制避免触发API限制
def safe_request(method, url, max_retries=3, **kwargs):
    for attempt in range(max_retries):
        try:
            response = requests.request(
                method, 
                url,
                timeout=10,
                headers=HEADERS,
                **kwargs
            )
            response.raise_for_status()
            return response
        except requests.exceptions.RequestException as e:
            if attempt == max_retries - 1:
                raise
            sleep(2 ** attempt)  # 指数退避

3. 仓库筛选逻辑:精准定位目标

直接删除所有仓库风险太高,我们需要实现智能筛选。以下是几种常见的过滤策略:

过滤条件 API参数 适用场景
仓库名称包含 q=keyword 删除特定前缀的测试仓库
最后更新时间 sort=updated 清理长期未更新的废弃项目
仓库可见性 type=all 区分公开/私有仓库
分页获取 page=1&per_page=100 处理大量仓库时的分批获取

多条件筛选示例

def get_filtered_repos(keyword=None, before_date=None):
    params = {"page": 1, "per_page": 100}
    if keyword:
        params["q"] = keyword
    if before_date:
        params["sort"] = "updated"
    
    repos = []
    while True:
        resp = safe_request("GET", f"{API_BASE}/user/repos", params=params)
        batch = resp.json()
        if not batch:
            break
            
        if before_date:
            batch = [r for r in batch 
                    if r["updated_at"] < before_date]
                    
        repos.extend(batch)
        params["page"] += 1
        
    return repos

4. 安全删除机制:防误删双保险

批量删除操作不可逆,我们需要构建多重保护:

确认机制设计方案

  1. 预览模式:先显示将被删除的仓库列表
  2. 交互确认:手动输入验证码确认
  3. 模拟删除:先进行试运行(dry run)
  4. 分批执行:每次删除10个后暂停确认
def confirm_deletion(repos):
    print(f"即将删除以下{len(repos)}个仓库:")
    for i, repo in enumerate(repos[:10], 1):
        print(f"{i}. {repo['name']} ({repo['html_url']})")
    
    if len(repos) > 10:
        print(f"...及其他{len(repos)-10}个仓库")
    
    code = input("输入'DELETE'确认执行删除:")
    return code.strip() == "DELETE"

增强版删除函数

def batch_delete(repos, batch_size=10, delay=5):
    for i, repo in enumerate(repos, 1):
        print(f"正在处理 {i}/{len(repos)}: {repo['name']}")
        try:
            resp = safe_request(
                "DELETE",
                f"{API_BASE}/repos/{repo['owner']['login']}/{repo['name']}"
            )
            if resp.status_code == 204:
                print(f"✓ 成功删除")
            else:
                print(f"! 异常状态码: {resp.status_code}")
                
            if i % batch_size == 0:
                sleep(delay)  # 避免速率限制
        except Exception as e:
            print(f"! 删除失败: {str(e)}")
            continue

5. 脚本优化与扩展

基础功能实现后,我们可以进一步提升工具的实用性:

性能优化点

  • 使用aiohttp实现异步请求
  • 本地缓存仓库列表减少API调用
  • 并行处理删除操作(需注意速率限制)

功能扩展方向

  • 添加日志记录系统
  • 支持多账号管理
  • 集成到CI/CD流水线
  • 开发GUI可视化界面
# 异步请求示例(需安装aiohttp)
import aiohttp
import asyncio

async def async_delete(session, repo):
    url = f"{API_BASE}/repos/{repo['owner']['login']}/{repo['name']}"
    try:
        async with session.delete(url) as resp:
            if resp.status == 204:
                print(f"Deleted {repo['name']}")
            else:
                print(f"Error on {repo['name']}: {resp.status}")
    except Exception as e:
        print(f"Failed {repo['name']}: {str(e)}")

async def main(repos):
    async with aiohttp.ClientSession(headers=HEADERS) as session:
        tasks = [async_delete(session, repo) for repo in repos]
        await asyncio.gather(*tasks)

6. 企业级应用场景

这套方法不仅适用于个人账户清理,经过适当改造还能满足更复杂的业务需求:

团队仓库管理方案

  • 定期清理CI生成的临时仓库
  • 归档超过1年未更新的项目
  • 同步删除关联的Webhook和Deploy keys
  • 与内部CMDB系统集成
# 企业级清理流程示例
def enterprise_cleanup(org):
    # 获取组织所有仓库
    repos = get_org_repos(org)
    
    # 应用保留规则
    to_keep = filter_active_repos(repos)
    to_delete = [r for r in repos if r not in to_keep]
    
    # 执行清理
    if confirm_deletion(to_delete):
        batch_delete(to_delete)
        
        # 清理关联资源
        clean_webhooks(to_delete)
        remove_deploy_keys(to_delete)
        
        # 生成报告
        generate_cleanup_report(to_delete)

实际项目中,我曾用类似脚本为客户清理了2000+测试仓库,节省了约40人工小时。关键是要在删除前做好备份方案,建议先归档到对象存储再执行删除。

更多推荐