1. 项目概述:墨刀需求文档自动化处理方案
作为一名在测试自动化领域深耕多年的工程师,我深刻理解需求文档处理这个看似简单实则耗时的工作痛点。每当产品经理甩过来一个墨刀链接,测试团队往往需要花费数小时甚至一整天时间手动整理页面内容、标注关键信息。这个开源项目正是为了解决这个行业普遍痛点而生。
该项目通过两阶段自动化流程,将墨刀原型文档转化为结构化Markdown:
- 第一阶段使用Playwright进行页面采集,实现自动登录、智能遍历、滚动截图和内容提取
- 第二阶段调用视觉大模型进行AI结构化处理,生成规范化的Markdown文档
核心价值在于:
- 将原本需要数小时的人工整理工作缩短到分钟级别
- 生成的文档可直接用于AI知识库检索和测试用例生成
- 完整保留原型中的标注信息(箭头、序号、红字等)
- 支持增量处理和中断恢复,适合大型项目迭代
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构与实现原理
2.1 整体架构设计
项目采用典型的两阶段管道式架构,各阶段职责明确:
code复制┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 墨刀URL │ → │ save_modao.py │ → │ 原始截图+MD │
└───────────────┘ └───────────────┘ └───────┬───────┘
↓
┌───────────────┐ ┌───────────────┐ ┌───────┴───────┐
│ 测试用例 │ ← │ AI处理 │ ← │ image_to_md.py│
└───────────────┘ └───────────────┘ └───────────────┘
这种设计有三大优势:
- 职责分离:采集与处理解耦,可独立优化
- 容错性强:中间产物(截图+原始MD)可作为检查点
- 扩展灵活:AI处理阶段可替换不同模型
2.2 阶段一:墨刀页面采集
2.2.1 核心功能实现
save_modao.py脚本的核心技术栈:
- Playwright:实现浏览器自动化控制
- Pillow:用于图像处理和拼接
- OpenCV:辅助图像特征匹配
关键技术点解析:
- 智能页面遍历算法
python复制def traverse_modao(page):
# 获取画布列表
canvases = get_canvas_list(page)
for canvas in canvases:
# 切换到当前画布
page.click(canvas['selector'])
# 获取该画布下的页面列表
pages = get_page_list(page)
for p in pages:
# 切换到目标页面
page.click(p['selector'])
# 等待页面加载
page.wait_for_selector('.main-content')
# 执行截图和内容提取
capture_page(page, p)
这种广度优先遍历方式确保:
- 不会遗漏任何画布和页面
- 保持与墨刀一致的浏览顺序
- 自动跳过"演示"、"废纸篓"等非需求页面
- 自适应滚动截图技术
针对长页面处理,我们实现了智能滚动算法:
python复制def capture_long_page(page, element):
viewport_height = page.viewport_size['height']
element_height = element.bounding_box()['height']
# 计算需要滚动的次数
scroll_times = math.ceil(element_height / viewport_height * 0.8) # 0.8为重叠系数
screenshots = []
for i in range(scroll_times):
# 计算当前滚动位置
scroll_pos = i * viewport_height * 0.8
# 执行滚动
page.evaluate(f"window.scrollTo(0, {scroll_pos})")
# 截取当前视口
screenshot = page.screenshot()
screenshots.append(screenshot)
return stitch_images(screenshots)
关键参数说明:
- 重叠系数0.8:确保相邻截图有20%重叠区域,便于后续拼接
- 动态计算滚动次数:适应不同高度的页面
- 视口高度自适应:兼容不同分辨率的设备
- 图像拼接优化方案
我们采用多阶段拼接策略确保质量:
- 特征点匹配:使用SIFT算法找到相邻图像的特征点
- 变换矩阵计算:通过RANSAC算法估算最优变换
- 渐变融合:在重叠区域应用alpha混合消除接缝
python复制def stitch_images(images):
# 初始化基础图像
base = images[0]
for i in range(1, len(images)):
# 特征点检测与匹配
kp1, des1 = sift.detectAndCompute(base, None)
kp2, des2 = sift.detectAndCompute(images[i], None)
matches = flann.knnMatch(des1, des2, k=2)
# 计算单应性矩阵
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
src_pts = np.float32([kp1[m.queryIdx].pt for m in good])
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good])
H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
# 图像变换与融合
warped = cv2.warpPerspective(images[i], H,
(base.shape[1], base.shape[0]+images[i].shape[0]))
warped[0:base.shape[0], 0:base.shape[1]] = base
base = blend_overlap(base, warped)
return base
2.2.2 内容提取与清洗
原始内容提取面临的主要挑战:
- UI元素干扰(如导航栏、按钮文字)
- 原型中的占位文本(如"请输入...")
- 重复的系统默认文本
我们的解决方案:
python复制def clean_content(text):
# 定义过滤规则
filters = [
r'^[0-9]{1,2}/[0-9]{1,2}$', # 页码
r'^V?[0-9]+\.[0-9]+\.[0-9]+$', # 版本号
r'^[a-zA-Z0-9]{8}$', # 随机ID
r'^请输入.*$', # 占位文本
]
# 按行处理
lines = text.split('\n')
cleaned = []
for line in lines:
line = line.strip()
if not line:
continue
# 应用过滤规则
skip = False
for pattern in filters:
if re.fullmatch(pattern, line):
skip = True
break
if not skip and len(line) > 1: # 过滤单字符行
cleaned.append(line)
return '\n'.join(cleaned)
2.3 阶段二:AI结构化处理
2.3.1 视觉大模型应用
项目采用阿里百炼的qwen3-vl模型,主要考虑:
- 多模态能力:同时理解图像和文本
- 中文优化:对中文文档解析效果更好
- API稳定性:企业级服务保障
核心调用逻辑:
python复制def analyze_image(image_path):
# 读取图像
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode('utf-8')
# 构造提示词
prompt = """你是一个专业的需求文档分析助手,请严格按照以下要求处理:
1. 完整提取所有可见文字,保持原顺序
2. 识别并标注所有箭头、序号、红字等标记
3. 区分内容区块并添加适当标题
4. 输出结构化JSON格式"""
# 调用API
response = requests.post(
"https://bailian.aliyuncs.com/v1/completions",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": MODEL_NAME,
"prompt": prompt,
"images": [image_data],
"max_tokens": 2000
}
)
return parse_response(response.json())
2.3.2 提示词工程
经过多次迭代,我们总结出有效的提示词设计原则:
- 角色设定:明确AI的角色和专业领域
- 任务分解:将复杂任务拆解为明确步骤
- 格式约束:严格规定输出格式
- 负面约束:明确禁止的行为
典型提示词结构:
code复制【角色】
你是一个资深产品需求分析师,擅长从原型图中提取需求要点。
【任务】
请分析这张原型图,提取所有需求相关信息,注意:
1. 保持原文,不修改任何表述
2. 识别所有视觉标记(红字、箭头等)
3. 按功能模块组织内容
【输出要求】
返回JSON格式,包含以下字段:
- title: 页面标题
- sections: 功能区块列表
- annotations: 标注信息
- elements: 交互元素
【禁止行为】
1. 不添加图片中没有的内容
2. 不忽略任何文字信息
3. 不改变原有表述方式
2.3.3 结构化输出处理
AI返回的JSON数据会转换为标准Markdown,关键转换逻辑:
python复制def json_to_markdown(data):
# 生成标题
md = f"# {data.get('title', '未命名页面')}\n\n"
# 处理内容区块
if 'sections' in data:
for section in data['sections']:
md += f"## {section['title']}\n\n"
for item in section['content']:
md += f"- {item}\n"
md += "\n"
# 处理标注信息
if 'annotations' in data:
md += "## 标注信息\n\n"
for anno in data['annotations']:
md += f"- **{anno['type']} {anno['id']}**: {anno['content']}\n"
md += "\n"
# 处理交互元素
if 'elements' in data:
md += "## 页面元素\n\n"
for elem in data['elements']:
md += f"- **{elem['type']}**: {elem['name']}"
if 'state' in elem:
md += f" ({elem['state']})"
md += "\n"
return md
3. 实战应用与效果展示
3.1 典型工作流示例
假设我们收到一个会员系统的墨刀原型,处理过程如下:
- 采集阶段
bash复制python save_modao.py "https://modao.cc/app/8F3kD9G7H2J4K5L6"
输出目录结构:
code复制modao-export/
└── 会员系统V3.2/
├── images/
│ ├── 01_会员首页.png
│ ├── 02_权益详情.png
│ └── 03_开通流程.png
└── md/
├── index.md
├── 01_会员首页.md
└── ...
- AI处理阶段
bash复制python image_to_md.py ./modao-export/会员系统V3.2
生成的结构化文档示例:
markdown复制# 01_会员首页
## 主功能区
- **会员状态显示区**:
- 顶部显示当前等级:黄金会员
- 进度条:650/1000积分(距下一级还差350分)
- 特权图标:专属客服(红点提示)、折扣券(new标签)
## 标注信息
- ① 红箭头指向进度条,标注"消费1元=1积分"
- ② 橙色感叹号标注在会员等级旁,提示"等级有效期至2024-12-31"
## 交互元素
- **按钮**:
- 立即续费(高亮)
- 积分兑换(灰色禁用)
- **下拉菜单**:
- 会员权益说明
- 积分规则
3.2 测试用例生成
基于结构化文档自动生成的测试用例:
| 模块 | 测试点 | 操作步骤 | 预期结果 |
|---|---|---|---|
| 会员状态 | 等级显示 | 1. 进入会员首页 2. 检查等级显示 |
显示正确的会员等级和图标 |
| 积分计算 | 消费积分 | 1. 完成一笔消费 2. 返回会员首页 |
积分进度条按比例增长 |
| 续费功能 | 续费按钮状态 | 1. 检查立即续费按钮 | 按钮可点击,样式正确 |
3.3 效率对比
传统方式 vs 本方案:
| 指标 | 传统方式 | 本方案 | 提升 |
|---|---|---|---|
| 10页文档处理时间 | 4-6小时 | 8-12分钟 | 30倍 |
| 标注遗漏率 | 15%-20% | <2% | 10倍 |
| 版本更新同步 | 需重新整理 | 增量更新 | 无限 |
4. 高级配置与优化技巧
4.1 性能调优建议
- 并发处理配置
python复制# 在image_to_md.py中增加并发处理
from concurrent.futures import ThreadPoolExecutor
def process_images(image_dir, output_dir, max_workers=4):
images = list_image_files(image_dir)
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = []
for img in images:
future = executor.submit(
process_single_image,
img,
os.path.join(output_dir, f"{os.path.splitext(img)[0]}.md")
)
futures.append(future)
for future in as_completed(futures):
try:
future.result()
except Exception as e:
log_error(e)
- 缓存机制实现
为避免重复处理相同图片:
python复制def needs_processing(input_path, output_path):
if not os.path.exists(output_path):
return True
input_mtime = os.path.getmtime(input_path)
output_mtime = os.path.getmtime(output_path)
return input_mtime > output_mtime
4.2 自定义规则配置
在项目根目录添加config.yaml:
yaml复制# 内容过滤规则
content_filters:
skip_keywords:
- "示例文本"
- "请输入"
- "点击这里"
ui_elements:
- "导航栏"
- "返回按钮"
- "用户头像"
# AI处理参数
ai_settings:
max_retry: 3
timeout: 30
temperature: 0.2
加载配置:
python复制import yaml
def load_config():
with open("config.yaml") as f:
return yaml.safe_load(f)
4.3 异常处理策略
完善的错误处理机制包括:
- 网络异常重试
python复制def call_ai_api(prompt, image, retry=3):
for attempt in range(retry):
try:
response = requests.post(API_URL, json={"prompt": prompt, "image": image}, timeout=30)
return response.json()
except (requests.Timeout, requests.ConnectionError) as e:
if attempt == retry - 1:
raise
time.sleep(2 ** attempt) # 指数退避
- 图像处理容错
python复制def safe_stitch(images):
try:
return stitch_images(images)
except StitchError as e:
# 尝试降级方案:简单垂直拼接
height = sum(img.shape[0] for img in images)
width = max(img.shape[1] for img in images)
result = np.zeros((height, width, 3), dtype=np.uint8)
y = 0
for img in images:
h, w = img.shape[:2]
result[y:y+h, 0:w] = img
y += h
return result
5. 常见问题排查指南
5.1 采集阶段问题
问题1:登录失败
- 现象:脚本卡在登录页面
- 检查:
- 确认墨刀账号密码正确
- 检查是否有验证码触发
- 查看Playwright是否启用了无痕模式
问题2:截图不全
- 现象:长页面缺失底部内容
- 解决方案:
- 调整
scroll_step参数(默认800px) - 增加页面加载等待时间
- 检查元素定位是否准确
- 调整
5.2 AI处理阶段问题
问题1:API调用超限
- 现象:返回429错误
- 解决方案:
- 增加请求间隔时间
- 申请更高的API配额
- 使用本地模型替代(如部署Ollama)
问题2:内容识别错误
- 现象:遗漏重��标注或文字
- 优化方法:
- 调整提示词强调标注识别
- 预处理图像增强对比度
- 人工校验后加入训练数据
5.3 性能优化记录
案例:大型项目处理超时
- 背景:200+页面的墨刀原型
- 优化措施:
- 实现分画布分批处理
- 增加断点续传功能
- 使用Redis缓存已处理文件状态
- 效果:处理时间从3小时降至35分钟
6. 项目演进方向
6.1 短期规划
-
多平台扩展
- 支持Figma、Axure等主流设计工具
- 开发统一适配层抽象差异
-
测试用例模板
- 内置多种测试模板(功能、UI、兼容性)
- 支持自定义模板导入
6.2 长期愿景
-
全链路自动化
mermaid复制graph LR 需求文档 --> 自动化解析 --> 测试用例 --> 自动化执行 --> 缺陷报告 --> 需求迭代 -
智能分析增强
- 需求一致性检查
- 测试覆盖率分析
- 风险点自动标识
在实际使用中,我发现这套方案特别适合快速迭代的敏捷团队。当产品经理在晨会展示最新原型后,测试团队在会间休息时就能获得结构化文档和基础测试用例,极大缩短了需求消化的时间成本。
