# VMR-Scraper
**Repository Path**: bulrush2008/VMR-Scraper
## Basic Information
- **Project Name**: VMR-Scraper
- **Description**: 分析、下载网站数据:https://www.vascularmodel.com/dataset.html
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2025-11-05
- **Last Updated**: 2026-03-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# VMR Scraper - 血管模型库数据抓取工具
[](https://python.org)
[](https://github.com/astral-sh/uv)
[](LICENSE)
## 项目概述
VMR Scraper 是专为 [Vascular Model Repository](https://www.vascularmodel.com) 网站开发的专用数据抓取工具,旨在自动提取和分析血管模型元数据,为医学研究和数据分析提供结构化数据支持。
### 项目成就
✅ **第一阶段已完成**:成功提取了 **316 个血管模型** 的完整元数据
- **数据完整性**:从年龄、性别到病理信息的全面覆盖
- **统计价值**:平均年龄 30.9 岁,涵盖 20 种不同血管疾病
- **技术卓越性**:采用现代 Python 技术栈和测试驱动开发
- **可扩展性**:模块化设计,易于维护和扩展
## 数据概览
| 指标 | 数值 | 描述 |
|--------|-------|-------------|
| **总模型数** | 316 | 完整血管模型数据集 |
| **唯一基础编号** | 288 | 编号从 0001 到 0288(连续) |
| **变体模型** | 28 | 部分基础编号存在多种病理变体 |
| **平均年龄** | 30.9 年 | 年龄范围:0.02-80.0 年 |
| **性别分布** | 男性 160 (50.6%)
女性 105 (33.2%) | 完整性别统计 |
| **疾病类型** | 20 | 从健康对照组到各种血管疾病 |
| **主要解剖部位** | Aorta (28.8%)
Coronary (27.5%)
Pulmonary (15.2%) | 覆盖主要血管系统 |
### 主要疾病分布
1. **健康对照组** - 89 个模型 (28.2%)
2. **腹主动脉瘤** - 32 个模型 (10.1%)
3. **主动脉缩窄** - 31 个模型 (9.8%)
4. **川崎病** - 27 个模型 (8.5%)
5. **冠状动脉疾病** - 22 个模型 (7.0%)
6. **脑动脉瘤** - 22 个模型 (7.0%)
### 数据结构洞察
**模型编号系统:**
- **基础编号**:0001 到 0288(288 个唯一标识符)
- **总模型数**:316(包括变体)
- **变体示例**:
- `0067 H CORO KD` vs `0067 H AO H`(同一患者,不同病理)
- `0075 H CORO CAD` vs `0075 H AO H`(相同基础编号,不同状况)
**变体分布:**
- 28 个基础编号有多种病理变体
- 260 个基础编号只有一个模型
- 这反映了患者可能患有多种血管疾病的真实临床场景
## 快速开始
### 环境要求
- Python 3.12 或更高版本
- uv(现代 Python 包管理器)
### 安装步骤
```bash
# 克隆项目
git clone
cd VMR_Scraper
# 初始化 uv 项目环境
uv init
# 创建 Python 3.12 虚拟环境
uv venv --python 3.12
# 激活虚拟环境 (Windows)
.venv\Scripts\activate
# 激活虚拟环境 (Linux/Mac)
source .venv/bin/activate
# 安装依赖包
uv add requests beautifulsoup4 selenium pandas
uv add aiofiles aiohttp tqdm
# 安装开发依赖
uv add --dev pytest pytest-asyncio black flake8 mypy isort
```
### 运行项目
```bash
# 运行主脚本(协调两个数据流阶段)
uv run main.py
# 运行特定阶段
uv run main.py --stage metadata # 第一阶段:元数据采集
uv run main.py --stage download # 第二阶段:文件下载
# 运行测试套件
uv run pytest
# 代码格式化和检查
uv run black .
uv run flake8 .
uv run mypy .
uv run isort .
```
## 项目结构
```
VMR_Scraper/
├── src/ # 生产代码目录
│ ├── __init__.py # 包初始化
│ ├── analyzer.py # 核心分析引擎(类设计,面向对象)
│ ├── utils.py # 核心工具库(HTTP、日志、重试机制)
│ └── config.py # 配置管理模块
├── dev/ # 开发工具目录
│ ├── data_processing.py # 数据处理流水线(CSV → Markdown)
│ ├── markdown_generator.py # 报告生成工具
│ ├── website_analysis.py # 网站结构分析工具
│ └── data_discovery.py # 数据源发现工具
├── tests/ # 测试目录
│ ├── __init__.py
│ ├── test_analyzer.py # 生产代码测试
│ └── test_utils.py # 工具函数测试
├── data/ # 处理后数据输出
│ ├── data_features.md # 中文数据特征表
│ ├── data_features.csv # 处理后的特征数据
│ └── models/ # 下载模型文件目录(第二阶段)
├── raw_data/ # 原始数据目录
│ ├── svprojects.csv # 主数据源(316个模型)
│ └── file_sizes.csv # 文件大小信息
├── docs/ # 文档目录
│ └── development_notes.md # 开发笔记和总结
├── main.py # 程序入口文件
├── CLAUDE.md # 开发指南
├── README.md # 项目文档
├── requirements.txt # 依赖列表
├── pyproject.toml # 项目配置
└── .gitignore # Git 忽略文件
```
### 代码架构说明
#### `src/` 生产代码
- **角色**:核心业务功能,长期维护的生产级代码
- **特点**:面向对象设计,完整测试覆盖,模块化导入
- **内容**:analyzer.py(分析引擎)、utils.py(工具库)、config.py(配置管理)
- **使用**:`from src.analyzer import VascularModelAnalyzer`
#### `dev/` 开发工具
- **角色**:开发辅助工具,任务导向的脚本
- **特点**:过程式编程,独立执行,调试友好
- **内容**:数据处理、报告生成、网站分析等开发脚本
- **使用**:`uv run python dev/data_processing.py`
#### `data/` 处理后数据
- **角色**:生成的报告、分析结果、下载文件
- **内容**:data_features.md(中文特征表)、data_features.csv(结构化数据)
- **版本控制**:data_features.md 和 data_features.csv 已提交,下载模型文件将被跟踪
#### `raw_data/` 原始数据
- **角色**:下载的源数据、原始CSV文件
- **内容**:svprojects.csv(主数据源)、file_sizes.csv(文件大小信息)
#### `docs/` 项目文档
- **角色**:开发笔记、API文档、使用指南
- **内容**:development_notes.md(开发总结和经验记录)
### 文件位置管理原则
**核心原则**:每个文件都有明确的归属位置,遵循项目最佳实践
- **代码文件**:按功能性质分配(`src/` vs `dev/` vs `tests/`)
- **数据文件**:按处理阶段分类(`raw_data/` vs `data/`)
- **文档文件**:统一放入 `docs/` 目录
- **配置文件**:项目配置放入 `src/`
- **临时文件**:开发过程中及时清理,避免污染项目结构
#### 数据文件版本控制
- **处理后数据**:`data_features.md` 和 `data_features.csv` 提交到版本控制
- **模型说明文件**:`.md` 说明文件将被 Git 跟踪,提供模型详细信息
- **原始数据**:`raw_data/` 目录下的原始 CSV 文件
- **大型模型文件**:`.zip` 等大型下载文件将被排除(避免仓库过大)
**版本控制策略**:
```
✅ 跟踪的文件:
├── data/data_features.md # 中文特征表
├── data/data_features.csv # 结构化数据
├── data/models/*.md # 模型说明文件
└── raw_data/ # 原始 CSV 文件
❌ 排除的文件:
├── data/models/*.zip # 大型模型压缩文件(通常 100MB+)
└── data/*.zip # 其他大型 zip 文件
```
**数据流阶段:**
**第一阶段:元数据分析和提取**
```
https://www.vascularmodel.com/dataset.html
↓ (analyzer.py 网页请求和解析)
316个模型页面详细信息
↓ (analyzer.py 提取元数据)
结构化元数据(名称、性别、年龄、健康状况等)
↓ (analyzer.py 生成 Markdown 表格)
data_features.md(316行数据的特征表)
```
**第二阶段:批量数据下载**
```
data_features.md(特征表)
↓ (downloader.py 解析下载链接)
316个模型文件下载URL
↓ (downloader.py 并发下载)
模型文件下载到 models/ 目录
↓ (downloader.py 文件组织)
按特征组织的本地数据集
```
## 核心功能
### ✅ 第一阶段功能(已完成)
1. **网站结构分析**
- 自动识别数据源和 API 端点
- 分析 HTML 结构和 JavaScript 依赖
- 确定数据获取策略
2. **元数据提取**
- 从 CSV 文件提取 316 个模型的完整信息
- 包含 29 个字段:年龄、性别、病理、解剖部位等
- 数据清理和标准化处理
3. **统计分析**
- 自动生成人口学统计
- 疾病和解剖部位分布分析
- 年龄分组和性别分布统计
4. **报告生成**
- Markdown 格式的详细数据特征表
- CSV 格式的结构化数据
- 完整的统计摘要
### 🔄 第二阶段功能(计划中)
1. **文件下载**
- 批量下载 316 个模型文件
- 支持并发下载和断点续传
- 文件完整性验证
2. **数据组织**
- 按疾病类型、解剖部位分类存储
- 自动目录结构生成
- 元数据和文件关联管理
## 数据字段说明
每个血管模型包含以下信息:
| 字段 | 描述 | 示例 |
|-------|-------------|---------|
| **Model ID** | 唯一模型标识符(格式:NNNN X ANATOMY DISEASE) | `0001 H AO SVD` |
| **Sex** | 患者性别 | `Male`, `Female` |
| **Age** | 患者年龄(年) | `3.00`, `45.00` |
| **Age Group** | 年龄分组 | `Child (6-11 years)` |
| **Anatomy** | 解剖部位 | `Aorta`, `Coronary` |
| **Disease** | 疾病类型 | `Healthy`, `Aneurysm` |
| **Procedure** | 医疗程序 | `None`, `Aortic Reconstruction` |
| **Image Modality** | 成像方式 | `MR`, `CT` |
| **Model Creator** | 模型创建者 | `Alison Marsden` |
| **Download URL** | 下载链接 | `https://www.vascularmodel.com/svprojects/...` |
| **File Size (MB)** | 文件大小 | `229.14` |
### Model ID 格式说明
Model ID 遵循结构化格式:**NNNN X ANATOMY DISEASE**
- **NNNN**:顺序编号(0001-0288)
- **X**:物种(H = Human 人类)
- **ANATOMY**:解剖位置(AO = Aorta 主动脉,CORO = Coronary 冠状动脉等)
- **DISEASE**:疾病状况(H = Healthy 健康,SVD = Single Ventricle Defect 单心室缺陷等)
**示例:**
- `0001 H AO SVD`:模型 0001,人类,主动脉,单心室缺陷
- `0067 H CORO KD`:模型 0067,人类,冠状动脉,川崎病
- `0288 H CORO H`:模型 0288,人类,冠状动脉,健康
## 技术架构
### 核心技术栈
- **编程语言**:Python 3.12+
- **包管理器**:uv
- **HTTP Client**:requests, aiohttp
- **HTML 解析**:BeautifulSoup4
- **数据处理**:pandas
- **异步处理**:asyncio, aiofiles
- **测试框架**:pytest
- **代码质量**:black, flake8, mypy, isort
### 设计模式
- **测试驱动开发(TDD)**:先写测试,后实现功能
- **模块化设计**:功能解耦,易于维护
- **错误处理**:全面的异常处理和重试机制
- **日志记录**:详细的操作日志用于调试
## 测试
### 运行测试
```bash
# 运行所有测试
uv run pytest
# 运行特定测试文件
uv run pytest tests/test_utils.py -v
# 运行特定测试方法
uv run pytest tests/test_analyzer.py::test_extract_age_from_text -v
# 查看测试覆盖率
uv run pytest --cov=src
```
### 测试覆盖
- ✅ **工具函数测试** - HTTP 请求、文件操作、数据验证
- ✅ **分析器测试** - HTML 解析、元数据提取、数据处理
- ✅ **集成测试** - 端到端工作流验证
## 使用示例
### 基础数据处理
```python
from src.analyzer import VascularModelAnalyzer
import pandas as pd
# 读取处理后的数据
df = pd.read_csv('data/data_features.csv')
# 基础统计
print(f"总模型数: {len(df)}")
print(f"平均年龄: {df['Age'].mean():.1f} 岁")
# 按疾病类型分组
disease_counts = df['Disease'].value_counts()
print("疾病分布:")
for disease, count in disease_counts.head():
print(f" {disease}: {count} 个模型")
```
### 高级分析
```python
# 年龄组分析
age_groups = df['Age Group'].value_counts()
print("年龄分布:")
for group, count in age_groups.items():
percentage = (count / len(df)) * 100
print(f" {group}: {count} ({percentage:.1f}%)")
# 解剖部位分析
anatomy_stats = df.groupby('Anatomy').agg({
'Age': ['mean', 'std'],
'Model ID': 'count'
}).round(1)
# 模型编号分析
base_numbers = df['Model ID'].str[:4].value_counts().sort_index()
print(f"\n基础编号范围: {base_numbers.index.min()} - {base_numbers.index.max()}")
print(f"唯一基础编号总数: {len(base_numbers)}")
# 查找变体(相同基础编号,不同状况)
base_counts = df['Model ID'].str[:4].value_counts()
variants = base_counts[base_counts > 1]
print(f"\n具有多种变体的编号: {len(variants)}")
if len(variants) > 0:
print("示例:")
for base_num in variants.head().index:
variant_models = df[df['Model ID'].str.startswith(base_num)]
print(f" {base_num}: {variant_models['Model ID'].tolist()}")
```
## 文档
- **[开发指南](CLAUDE.md)** - 详细的开发文档和架构说明
- **[项目总结](PROJECT_SUMMARY.md)** - 第一阶段完成总结
## 贡献
### 开发工作流
1. Fork 项目
2. 创建功能分支 (`git checkout -b feature/AmazingFeature`)
3. 编写测试用例
4. 实现功能并确保测试通过
5. 运行代码质量检查
6. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
7. 推送到分支 (`git push origin feature/AmazingFeature`)
8. 开启 Pull Request
### 代码标准
```bash
# 代码格式化
uv run black .
# 导入排序
uv run isort .
# 代码检查
uv run flake8 .
# 类型检查
uv run mypy .
```
## 许可证
本项目采用 MIT 许可证。
## 致谢
- **Vascular Model Repository** - 提供宝贵的医学数据资源
- **Stanford University** - 数据的学术支持
- **开源社区** - 提供优秀的工具和库
## 联系方式
如有问题或建议,请:
- 📧 查看项目仓库的 issues 和讨论
- 📖 参考项目中的文档
- 🐛 通过项目的 issue tracker 报告问题
## 未来计划
### 第二阶段目标
- [ ] 开发高效的文件下载器
- [ ] 实现并发下载和断点续传功能
- [ ] 添加文件完整性验证
- [ ] 创建数据组织和索引系统
### 扩展功能
- [ ] 支持更多数据源
- [ ] 添加数据可视化功能
- [ ] 开发 Web 界面
- [ ] 集成机器学习分析工具
---
**项目状态**:✅ 第一阶段完成 | 🔄 第二阶段开发中
**最后更新**:2025-11-06