# data/ - 数据模块 [根目录](../CLAUDE.md) > **data** --- ## 变更记录 (Changelog) ### 2026-01-05 16:13:47 - 更新模块文档,添加导航面包屑 - 完善数据质量说明和使用建议 ### 2026-01-05 16:03:40 - 初始化数据模块文档 - 完成三类钢材价格数据文件的结构分析 --- ## 模块职责 负责存储和管理钢材价格原始数据,包含三种不同来源的价格信息: 1. **钢材网架.json** - 第三方平台市场价格数据(我的钢铁网) 2. **钢厂指导价.json** - 钢厂官方指导价格(德钢) 3. **刚协指导价.json** - 钢材行业协会指导价格(云南钢协) --- ## 文件清单 | 文件名 | 大小 | 记录数 | 更新日期 | 数据来源 | |-------|------|--------|----------|----------| | **钢材网架.json** | ~190KB | 211+ 条 | 2026-01-05 | 我的钢铁网 | | **钢厂指导价.json** | ~1600KB | 29,987 条 | 2025-09-04 | 德钢指导价 | | **刚协指导价.json** | ~160KB | 900 条 | 2026-01-05 | 云南钢协 | **总记录数**: 31,098 条 --- ## 数据结构 ### 统一格式 所有 JSON 文件均遵循以下嵌套结构: ```json { "code": 0, // 响应码(0=成功) "isZip": 0, // 是否压缩 "isDes": 0, // 是否加密 "data": { "page": { "result": [...], // 实际数据数组 "pageSize": 100, // 每页大小 "pageNo": 1, // 当前页码 "pageNumber": 1, // 页码 "totalCount": 211, // 总记录数 "totalPage": 3 // 总页数 } } } ``` ### 价格记录字段说明 | 字段名 | 类型 | 必填 | 说明 | 示例值 | |-------|------|------|------|--------| | **GOODS_MATERIAL** | string | 是 | 材质牌号 | `HRB400E`, `HPB300`, `HRB500E` | | **GOODS_SPEC** | string | 是 | 规格型号 | `Φ6`, `Φ8`, `Φ12`, `Φ14`... | | **PIRCE_DATE** | string | 是 | 价格日期 | `2026-01-05 08:00:00` | | **PARTSNAME_NAME** | string | 是 | 品名 | `螺纹钢`, `高线`, `盘螺` | | **PRODUCTAREA_NAME** | string | 是 | 产地/钢厂 | `达州钢铁`, `玉昆`, `韶钢松山` | | **PRICE_ID** | string | 是 | 价格唯一ID | `2008067775216672776` | | **PR_PRICE_SOURCE** | string | 是 | 价格来源 | `我的钢铁`, `云南钢协`, `德钢指导价` | | **PR_PRICE_REGION** | string | 是 | 价格地区 | `重庆`, `昆明`, `成都`, `广州` | | **PNTREE_NAME** | string | 是 | 分类名称 | `钢筋` | | **PR_PRICESET_HANGPRICE** | integer | 否 | 当前挂牌价 | `3770` (元/吨) | | **PR_LAST_PRICESET_HANGPRICE** | integer | 否 | 上次挂牌价 | `3770` (元/吨) | | **PR_MAKEPRICE_UPDW** | string | 否 | 钢厂价涨跌 | `0`, `-20`, `+30` | | **PR_HANGPRICE_UPDW** | string | 否 | 挂牌价涨跌 | `0`, `-20`, `+30` | | **OPERATOR_CODE** | string | 否 | 操作员代码 | `1048`, `1128` | | **OPERATOR_NAME** | string | 否 | 操作员名称 | `姜薇`, `RPA机器人` | --- ## 数据样本分析 ### 1. 钢材网架.json (我的钢铁网) **特征**: - 数据源: 第三方平台"我的钢铁" - 涵盖地区: 重庆、成都、广州、南宁等 - 主要钢厂: 达州钢铁、成渝钒钛、韶钢松山、桂万钢 - 包含完整的价格涨跌信息 **示例记录**: ```json { "GOODS_MATERIAL": "HRB400E", "GOODS_SPEC": "Φ12", "PIRCE_DATE": "2026-01-05 08:00:00", "PARTSNAME_NAME": "螺纹钢", "PRODUCTAREA_NAME": "达州钢铁", "PRICE_ID": "2008071950960877594", "PR_PRICE_SOURCE": "我的钢铁", "PR_PRICE_REGION": "重庆", "PR_PRICESET_MAKEPRICE": 3350, "PR_LAST_PRICESET_MAKEPRICE": 3370, "PR_MAKEPRICE_UPDW": "-20", "PNTREE_NAME": "钢筋" } ``` **覆盖地区**: - 重庆、成都、广州、南宁 - 数据较新(2026-01-05) ### 2. 钢厂指导价.json (德钢指导价) **特征**: - 数据源: 德钢官方指导价 - 涵盖地区: 云南省内(玉溪、昭通、文山、景洪、蒙自) - 钢厂品牌: 德钢 - 数据量最大(约3万条) - 仅包含挂牌价,无钢厂价 **示例记录**: ```json { "GOODS_MATERIAL": "HRB500E", "GOODS_SPEC": "Φ28", "PIRCE_DATE": "2025-09-04 08:00:00", "PARTSNAME_NAME": "螺纹钢", "PRODUCTAREA_NAME": "德钢", "PRICE_ID": "2001490258921979958", "PR_PRICE_SOURCE": "德钢指导价", "PR_PRICE_REGION": "玉溪", "PR_LAST_PRICESET_HANGPRICE": 3350, "PR_HANGPRICE_UPDW": "-30", "PR_PRICESET_HANGPRICE": 3320, "PNTREE_NAME": "钢筋", "OPERATOR_CODE": "1048", "OPERATOR_NAME": "姜薇" } ``` **数据质量警告**: - 数据日期较旧(2025-09-04),需要更新 ### 3. 刚协指导价.json (云南钢协) **特征**: - 数据源: 云南钢协官方指导价 - 涵盖地区: 昆明、玉溪、楚雄、大理 - 钢厂品牌: 玉昆 - 数据较新(2026-01-05) - 仅包含挂牌价,无钢厂价 **示例记录**: ```json { "GOODS_MATERIAL": "HRB400E", "GOODS_SPEC": "Φ12", "PIRCE_DATE": "2026-01-05 08:00:00", "PARTSNAME_NAME": "螺纹钢", "PRODUCTAREA_NAME": "玉昆", "PRICE_ID": "2008067775216672776", "PR_PRICE_SOURCE": "云南钢协", "PR_PRICE_REGION": "昆明", "PR_LAST_PRICESET_HANGPRICE": 3770, "PR_HANGPRICE_UPDW": "0", "PR_PRICESET_HANGPRICE": 3770, "PNTREE_NAME": "钢筋", "OPERATOR_CODE": "1048", "OPERATOR_NAME": "姜薇" } ``` --- ## 数据特征统计 ### 材质分布 - **HRB400E**: 最常见的螺纹钢材质(抗震) - **HPB300**: 高线材质(光圆钢筋) - **HRB500E**: 高强度螺纹钢 - **HRB400**: 普通螺纹钢 ### 规格范围 - 最小: Φ6(盘螺、高线) - 最大: Φ40(螺纹钢) - 常用规格: Φ8, Φ10, Φ12, Φ14, Φ16, Φ18, Φ20, Φ22, Φ25 ### 地区覆盖 - **西南地区**: 重庆、成都、南宁、云南(昆明、玉溪、楚雄、大理等) - **华南地区**: 广州 - **主要钢厂**: 达州钢铁、成渝钒钛、韶钢松山、桂万钢、玉昆、德钢 --- ## 数据质量说明 ### 数据完整性 - ✅ 包含完整的 `PRICE_ID` 唯一标识 - ✅ 包含价格日期(`PIRCE_DATE`) - ⚠️ 部分字段可能缺失(如 `PR_PRICESET_MAKEPRICE`) - ⚠️ 钢厂指导价数据日期较旧(2025-09-04) ### 数据一致性 - ⚠️ 字段命名错误:`PIRCE_DATE` 应为 `PRICE_DATE` - ⚠️ 价格字段在不同文件中有不同的子字段(钢厂价 vs 挂牌价) - ⚠️ 部分数据源缺少涨跌幅信息 --- ## 使用建议 ### 数据导入流程 #### 1. 读取 JSON 文件 ```javascript const fs = require('fs'); const path = require('path'); // 读取数据文件 const filePath = path.join(__dirname, '钢材网架.json'); const rawData = fs.readFileSync(filePath, 'utf8'); const jsonData = JSON.parse(rawData); // 提取价格记录 const records = jsonData.data.page.result; ``` #### 2. 数据验证与清洗 ```javascript function validateAndClean(record) { // 必填字段检查 const requiredFields = [ 'PRICE_ID', 'GOODS_MATERIAL', 'GOODS_SPEC', 'PIRCE_DATE', 'PARTSNAME_NAME', 'PRODUCTAREA_NAME', 'PR_PRICE_SOURCE', 'PR_PRICE_REGION', 'PNTREE_NAME' ]; for (const field of requiredFields) { if (!record[field]) { throw new Error(`Missing required field: ${field}`); } } // 字段重命名(修正错误) return { ...record, PRICE_DATE: record.PIRCE_DATE, // 修正字段名 price_date: new Date(record.PIRCE_DATE), make_price: record.PR_PRICESET_MAKEPRICE || null, hang_price: record.PR_PRICESET_HANGPRICE || null, make_price_updw: record.PR_MAKEPRICE_UPDW || null, hang_price_updw: record.PR_HANGPRICE_UPDW || null }; } ``` #### 3. 批量插入数据库 ```sql -- MySQL 建表语句 CREATE TABLE steel_prices ( id BIGINT PRIMARY KEY AUTO_INCREMENT, price_id VARCHAR(64) UNIQUE NOT NULL COMMENT '价格唯一ID', goods_material VARCHAR(32) NOT NULL COMMENT '材质牌号', goods_spec VARCHAR(16) NOT NULL COMMENT '规格型号', partsname_name VARCHAR(32) NOT NULL COMMENT '品名', productarea_name VARCHAR(64) NOT NULL COMMENT '产地/钢厂', price_source VARCHAR(32) NOT NULL COMMENT '价格来源', price_region VARCHAR(32) NOT NULL COMMENT '价格地区', pntree_name VARCHAR(32) NOT NULL COMMENT '分类名称', price_date DATETIME NOT NULL COMMENT '价格日期', make_price INT COMMENT '钢厂价(元/吨)', hang_price INT COMMENT '挂牌价(元/吨)', last_make_price INT COMMENT '上次钢厂价', last_hang_price INT COMMENT '上次挂牌价', make_price_updw VARCHAR(8) COMMENT '钢厂价涨跌', hang_price_updw VARCHAR(8) COMMENT '挂牌价涨跌', operator_code VARCHAR(16) COMMENT '操作员代码', operator_name VARCHAR(32) COMMENT '操作员名称', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_price_date (price_date), INDEX idx_region_material (price_region, goods_material), INDEX idx_source_date (price_source, price_date), INDEX idx_price_id (price_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='钢材价格表'; ``` #### 4. 使用 UPSERT 避免重复 ```javascript // 使用 INSERT ... ON DUPLICATE KEY UPDATE const sql = ` INSERT INTO steel_prices ( price_id, goods_material, goods_spec, partsname_name, productarea_name, price_source, price_region, pntree_name, price_date, make_price, hang_price, make_price_updw, hang_price_updw, operator_code, operator_name ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE make_price = VALUES(make_price), hang_price = VALUES(hang_price), updated_at = CURRENT_TIMESTAMP `; ``` ### 查询优化建议 #### 常用查询场景 ```sql -- 1. 按地区和材质查询最新价格 SELECT * FROM steel_prices WHERE price_region = '重庆' AND goods_material = 'HRB400E' ORDER BY price_date DESC LIMIT 10; -- 2. 查询指定日期范围的价格 SELECT goods_spec, AVG(hang_price) as avg_price, MIN(hang_price) as min_price, MAX(hang_price) as max_price FROM steel_prices WHERE price_date BETWEEN '2026-01-01' AND '2026-01-05' AND price_region = '昆明' AND goods_material = 'HRB400E' GROUP BY goods_spec ORDER BY goods_spec; -- 3. 价格趋势分析 SELECT DATE(price_date) as date, goods_spec, AVG(hang_price) as avg_price FROM steel_prices WHERE price_region = '重庆' AND goods_material = 'HRB400E' AND price_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) GROUP BY DATE(price_date), goods_spec ORDER BY date DESC, goods_spec; ``` #### 索引优化 ```sql -- 复合索引(地区+材质+日期) CREATE INDEX idx_region_material_date ON steel_prices(price_region, goods_material, price_date DESC); -- 覆盖索引(查询优化) CREATE INDEX idx_source_region_date_price ON steel_prices(price_source, price_region, price_date, hang_price); ``` --- ## 数据更新策略 ### 建议更新频率 - **钢材网架.json**: 每日更新(市场价格波动频繁) - **钢厂指导价.json**: 每周或按钢厂发布周期更新 - **刚协指导价.json**: 每日或每周更新 ### 自动化采集(未来实现) - 定时任务自动抓取各平台数据 - 数据变更检测与增量更新 - 历史价格数据归档 - 异常数据告警 --- ## 常见问题 (FAQ) ### Q: 为什么 `PIRCE_DATE` 拼写是错误的? A: 这是原始数据源的字段命名错误。建议在数据库模型中修正为 `PRICE_DATE`,并在数据导入时进行字段重命名。 ### Q: 价格字段 `PR_PRICESET_MAKEPRICE` 和 `PR_PRICESET_HANGPRICE` 有什么区别? A: - `MAKEPRICE`: 钢厂出厂价(钢厂直接销售价格) - `HANGPRICE`: 市场挂牌价(经销商挂牌价格) - 不同数据源可能只包含其中一种 ### Q: 如何处理重复的 `PRICE_ID`? A: `PRICE_ID` 应该是全局唯一的。如发现重复: 1. 检查数据来源是否正确 2. 使用 `UPSERT` 语句更新现有记录 3. 记录冲突日志供后续分析 4. 考虑添加数据源标识符避免跨源冲突 ### Q: 数据文件太大如何高效处理? A: 建议采用以下策略: 1. 使用流式读取(Node.js `stream`) 2. 批量处理(每批 1000 条) 3. 使用事务批量插入 4. 考虑使用 worker 线程并行处理 --- ## 相关文件路径 - **数据文件**: `d:\Code\steel_prices_service\data\*.json` - **根文档**: `d:\Code\steel_prices_service\CLAUDE.md` - **索引文件**: `d:\Code\steel_prices_service\.claude\index.json` --- **导航**: [返回根目录](../CLAUDE.md) | [查看项目索引](../.claude/index.json)