7.6 KiB
7.6 KiB
📋 实施计划:Ruff 代码优化 + 项目质量提升
生成时间:2026-03-20 工作目录:/Users/win/2025/AICoding/JobData
一、现状问题总览
1.1 Ruff 实际扫描结果(34 个错误,22 个可自动修复)
| 规则 | 数量 | 说明 | 可自动修复 |
|---|---|---|---|
F401 |
20 | 未使用的 import | ✅ |
E402 |
5 | import 不在文件顶部 | ❌ |
F541 |
3 | f-string 没有占位符 | ✅ |
F821 |
3 | 引用了未定义的变量名 | ❌ |
F811 |
2 | 重复定义(导入后又被覆盖) | ✅ |
E722 |
1 | 裸 except:(不捕获具体异常) |
❌ |
| 合计 | 34 | 22 可自动修复 |
1.2 受影响文件清单
| 文件 | 问题数 | 最严重问题 |
|---|---|---|
app/api/v1/token/token.py |
8 | E402 + F811(import 顺序混乱,重复定义) |
app/services/job.py |
3 | F821 未定义变量 udt、fpt;E722 裸 except |
app/services/crawler/zhilian.py |
1 | F821 未定义变量 json |
app/services/company_cleaner.py |
3 | F541 空 f-string |
app/services/crawler/__init__.py |
3 | F401 无效的服务导出 |
app/repositories/clickhouse_repo.py |
2 | F401 math, Generator |
app/schemas/token.py |
2 | F401 Dict, Any |
app/controllers/job.py |
1 | F401 Optional |
app/controllers/keyword.py |
1 | F401 CRUDBase |
app/core/algorithms/antispider.py |
1 | F401 os |
app/core/ip_tracking.py |
1 | F401 Any |
app/core/locks.py |
1 | F401 time |
app/api/v1/analytics.py |
1 | F401 List |
app/api/v1/ingest/ingest.py |
1 | F401 Optional |
app/schemas/analytics.py |
1 | F401 Any |
app/services/crawler/boss.py |
1 | F401 os |
1.3 Ruff 扫描之外的深层问题(代码审查发现)
🔴 CRITICAL — 安全问题(硬编码凭据)
| 文件 | 行号 | 问题 |
|---|---|---|
app/settings/config.py |
~23 | SECRET_KEY = "CHANGE_ME_DEV_ONLY" JWT 密钥 |
app/settings/config.py |
~27-30 | ClickHouse 主机 IP、用户名、密码明文 |
app/settings/config.py |
~44-45 | SMTP 真实邮箱账号 + 授权码明文 |
app/settings/config.py |
~52 | MySQL root 密码 + 生产 IP 硬编码在连接串 |
app/services/job.py |
~533-535 | 外部 API salt 硬编码 |
🔴 HIGH — 性能问题(事件循环阻塞)
| 文件 | 行号 | 问题 |
|---|---|---|
app/services/job.py |
~547 | async def 中调用同步 requests.post 阻塞事件循环 |
app/services/job.py |
~926-933 | 串行逐条发送远程推送,N 条数据 = N 次串行阻塞 |
app/core/locks.py |
~38 | 同步 redis.Redis 在 async 方法中调用,阻塞事件循环 |
🟡 MEDIUM — 代码质量
| 文件 | 问题 |
|---|---|
app/services/job.py |
7 个 _check_*_duplicate 方法几乎完全重复,仅 SQL 参数不同 |
app/services/job.py |
1 个死代码方法:_check_qcwy_company_duplicate_by_name 从未被调用 |
app/repositories/clickhouse_repo.py |
group_by_column 直接拼入 SQL(潜在 SQL 注入) |
app/api/v1/__init__.py |
同一 router 注册两次(/job 和 /universal),OpenAPI 文档重复 |
| 全项目 | 零测试文件,关键业务逻辑(去重、路由分发)无任何测试保护 |
二、实施步骤
Phase 1:Ruff 自动修复(低风险,5 分钟)
# 自动修复 22 个可自动修复的问题
pipenv run ruff check app/ --fix
# 验证修复结果
pipenv run ruff check app/ --statistics
自动修复覆盖:F401(未使用 import)、F541(空 f-string)、F811(重复定义)
Phase 2:手动修复 Ruff 报告的无法自动修复问题(12 个)
2.1 F821 未定义变量(CRITICAL,会导致运行时崩溃)
app/services/job.py:348 — 变量 udt 未定义
需要读取上下文,确认 udt 应该是什么(可能是 update_date_time 的缩写或某个局部变量)。
app/services/job.py:374 — 变量 fpt 未定义
需要读取上下文,确认 fpt 应该是什么(可能是 first_publish_time 缩写)。
app/services/crawler/zhilian.py:60 — json 模块未导入但被使用
修复:在文件顶部添加 import json。
2.2 E722 裸 except(app/services/job.py:302)
# 修改前
except:
pass
# 修改后
except Exception as e:
logger.error(f"处理失败: {e}")
2.3 E402 import 不在顶部(app/api/v1/token/token.py:92-96)
将条件式 import 移至文件顶部,或使用 TYPE_CHECKING 保护块。
Phase 3:凭据安全(CRITICAL,建议本次一并完成)
目标:将所有硬编码凭据移入环境变量
- 在项目根目录创建
.env.example(安全模板) - 修改
app/settings/config.py,用pydantic-settings从环境变量读取所有敏感值 - 启动时校验必填环境变量,缺失则报错退出(Fail Fast)
- 将
.env加入.gitignore(已有则确认)
# config.py 改造后示例
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
SECRET_KEY: str # 必填,无默认值
CLICKHOUSE_HOST: str = "localhost"
CLICKHOUSE_USER: str = "default"
CLICKHOUSE_PASS: str # 必填
SMTP_USER: str = ""
SMTP_PASS: str = ""
DB_URL: str # 必填
class Config:
env_file = ".env"
Phase 4:性能修复(async 阻塞问题)
- 将
app/services/job.py中的requests.post替换为httpx.AsyncClient(已在依赖中) - 将
_batch_send_to_remote_server改为asyncio.gather并发执行 - 将
app/core/locks.py中的同步redis.Redis替换为aioredis(或redis.asyncio)
Phase 5:代码去重(可维护性)
合并 7 个重复的 _check_*_duplicate 方法为 1 个通用方法:
async def _check_duplicate(
self,
table: str,
conditions: dict[str, str], # {"column_name": "value"}
days: int = 90
) -> bool:
...
删除死代码:_check_qcwy_company_duplicate_by_name
三、关键文件索引
| 文件 | 操作 | 说明 |
|---|---|---|
app/settings/config.py |
重构 | 凭据移入环境变量 |
app/services/job.py |
修复 | F821、E722、async 阻塞、方法去重 |
app/services/crawler/zhilian.py |
修复 | 添加 import json |
app/api/v1/token/token.py |
整理 | 修复 E402 import 顺序 |
app/services/company_cleaner.py |
自动修复 | F541 空 f-string |
app/core/locks.py |
修复 | 同步 redis → 异步 |
app/repositories/clickhouse_repo.py |
修复 | 删除未用 import |
.env.example |
新建 | 环境变量模板 |
四、风险与缓解
| 风险 | 缓解措施 |
|---|---|
| 修复 F821 时误判变量用途 | 先读原函数完整逻辑再修复 |
| 凭据迁移后服务无法启动 | 先创建 .env 再重启服务 |
| async 改造引入新 bug | 修改后在本地运行完整功能测试 |
| 方法合并破坏去重逻辑 | 保持原有 SQL 逻辑不变,只提取公共参数 |
五、执行顺序建议
Phase 1(5min) → pipenv run ruff check app/ --fix
Phase 2(30min) → 手动修复 F821 × 3、E722 × 1、E402 × 5
Phase 3(60min) → 凭据安全迁移(需配合运维创建 .env)
Phase 4(90min) → async 阻塞修复(requests → httpx)
Phase 5(60min) → 去重方法合并(可选,不影响功能)
SESSION_ID(供 /ccg:execute 使用)
- CODEX_SESSION: N/A(本次分析由 Claude 本地执行)
- GEMINI_SESSION: N/A