# 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 - 血管模型库数据抓取工具 [![Python](https://img.shields.io/badge/Python-3.12+-blue.svg)](https://python.org) [![uv](https://img.shields.io/badge/uv-Package%20Manager-green.svg)](https://github.com/astral-sh/uv) [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](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