Back to skills
extension
Category: Data & AnalyticsNo API key required

产业链全景图谱生成器

从CSV或xlsx数据表生成产业链全景图谱HTML可视化图表。当用户提供产业链示例CSV/xlsx、产业链数据表,或要求制作产业链图谱、产业全景图、产业链可视化图表时调用此技能。

personAuthor: user_d9b4f512hubcommunity

产业链全景图谱生成器

从CSV或xlsx数据表自动生成专业级产业链全景图谱HTML可视化图表,支持上/中/下游三列布局、颜色编码、自动渲染模式选择。支持屏幕展示版和宽幅印刷版两种模式。

已验证适用的产业链类型(60+种):煤化工、煤制油、煤焦化、精细煤化工、煤制气、钢铁、钢材深加工、氯碱化工、钢焦化氢联产、绿色钢铁与高端装备制造、煤焦钢一体化、特钢及高端金属材料、先进钢铁制造、特色装备制造、新能源汽车、智能煤机装备、军民融合装备制造、通用设备制造、新材料、高性能复合材料、碳基新材料、先进化工材料、新能源电池材料、电子信息、LED光电、半导体光电、能源电子、信创、节能环保、大宗工业固废综合利用、粉煤灰综合利用、煤矸石综合利用、冶炼渣综合利用、现代医药、创新药、大健康、现代生物医药、现代中药、低空经济、低空飞行器制造、低空基础设施、低空经济运营服务、无人机、人工智能基础设施、人工智能软件、人工智能应用与服务、具身智能与机器人、人工智能、氢能、氢能基础设施、氢能装备制造、氢燃料电池、制氢、党参中药、农产品精深加工、特优现代农业、小米(谷子)、智慧农业、文化旅游、红色文化旅游、康养度假、生态旅游、文旅景区开发、国防军工装备制造、航空航天装备制造、军民两用技术、军民融合等。

数据格式要求

支持CSV和xlsx两种输入格式。列名可略有不同,脚本会自动检测关键词匹配。

| 标准列名 | 关键词检测 | 说明 | 示例 | |---------|-----------|------|------| | 一级环节 | 含"一级" | 上游/中游/下游大类 | 上游:煤炭资源与核心装备 | | 二级子环节 | 含"二级" | 子分类 | 煤炭开采与洗选 | | 三级子环节 | 含"三级" | 具体环节 | 动力煤开采 | | 代表公司 | 含"公司"/"企业"/"代表" | 企业名称(可选) | 中国神华 | | 环节概述 | 含"概述"/"描述"/"说明" | 环节说明文字(可选) | 直接从事煤矿开采作业… |

一级环节文本中包含"上游""中游""下游"关键词时,自动分配橙/蓝/绿色方案,其他归为灰色"其他"类。

自动渲染模式

  • tag模式:数据无企业列时自动启用,三级子环节作为彩色标签排列在二级section内
  • box模式:数据含企业列时自动启用,三级子环节作为box,内含企业标签

数据处理规则

  • CSV编码自动检测顺序:UTF-8-sig → UTF-8 → GBK → GB2312 → GB18030
  • xlsx使用openpyxl读取
  • 企业名称在同一个三级环节内自动去重
  • 层级分组结构:一级环节 → 二级子环节(sections) → 三级子环节(tags/boxes) → 代表公司(companies)
  • Windows环境Python输出中文需设置UTF-8编码(脚本已内置处理)
  • xlsx文件被Excel占用时直接save会PermissionError,需先save到临时文件再shutil.copy2覆盖到目标路径

使用方法

印刷版(默认,宽幅排版)

python scripts/generate_atlas.py data.xlsx --print -o output.html -t "煤化工产业链全景图"
python scripts/generate_atlas.py data.csv --print -o output.html -t "产业链全景图"

屏幕展示版(含图例、统计、描述)

python scripts/generate_atlas.py data.xlsx --screen -o output.html -t "产业链全景图谱"

参数说明

| 参数 | 说明 | 默认值 | |------|------|--------| | data_path | 数据文件路径(.csv 或 .xlsx,必填) | — | | --print | 生成印刷版(默认启用) | true | | --screen | 生成屏幕展示版(覆盖--print) | false | | -o / --output | 输出HTML路径 | 与数据文件同目录 | | -t / --title | 图谱标题 | "产业链全景图" | | -s / --subtitle | 副标题(仅屏幕版生效) | 空 | | --max-companies | 每个三级环节最多显示企业数(box模式) | 6 |

印刷版排版规格详解(PRINT_CSS_TAG_MODE / PRINT_CSS_BOX_MODE)

页面设置

  • 自定义页面尺寸:387mm × 210mm(宽幅横版)
  • @page size: 387mm 210mm; margin: 0mm(由atlas padding控制边距)
  • html/body width: 387mm
  • atlas: display:flex; flex-direction:column; min-height:206mm; padding:2mm; margin:0 auto
  • 背景:浅米色 #F5F0E6
  • 全局line-height: 1.15
  • 字体:font-family "Microsoft YaHei","PingFang SC","Noto Sans SC","Helvetica Neue",Arial,sans-serif

标题(atlas-title)

  • 字号:24pt
  • font-weight: 800
  • color: #1a252f
  • letter-spacing: 2px
  • 标题与下方图文间距:7mm(atlas-header margin-bottom)
  • 印刷版无副标题
  • atlas-header: text-align:center; flex-shrink:0

三列布局(上游/中游/下游)

  • .columns: display:flex; gap:5pt; flex:1; align-items:stretch; min-height:0; justify-content:center(三列整体居中)
  • .column: flex:0 0 auto; width:fit-content; min-width:0; display:flex; flex-direction:column(每列收缩至刚好容纳内容)
  • 列头(col-header):
    • padding: 1.2mm 3mm
    • color: #fff(白色文字)
    • font-size: 15pt
    • font-weight: 700
    • text-align: center
    • letter-spacing: 1px
    • border-radius: 3px 3px 0 0
    • flex-shrink: 0
    • background: 各环节的header_grad渐变色
  • 列体(col-body):
    • flex:1; display:flex; flex-direction:column
    • padding: 1.5mm; gap:0
    • border: 2px solid(颜色用该环节primary色)
    • border-top: none(与列头衔接)
    • border-radius: 0 0 3px 3px
    • justify-content: space-between(首段顶部对齐、末段底部对齐,纵向上下两端对齐)
    • align-items: center(二级面板水平居中)

二级面板(section)

  • width: fit-content; max-width: calc(34.2mm * 3 + 4mm)(收缩至刚好容纳3个标签宽度,防止溢出)
  • border: 1.5px solid(颜色用该环节的tag_border浅色)
  • border-radius: 2px
  • overflow: hidden
  • section-header:
    • padding: 0.6mm 2mm
    • font-size: 13pt
    • font-weight: 700
    • display: flex; align-items: center; gap: 1.5mm
    • background: section_bg色(浅橙/浅蓝/浅绿)
    • color: tag_color色
    • 左侧色条.bar: width:4px; height:10px; border-radius:1px; flex-shrink:0; background: primary色
  • section-body(tag模式):
    • padding: 1mm 1.5mm
    • display: flex; flex-wrap: wrap
    • gap: 0(水平方向无间距)
    • row-gap: 3pt(垂直方向标签行间距3pt)
  • section-body(box模式):
    • padding: 1mm 1.5mm
    • display: flex; flex-direction: column; gap: 0.8mm

三级标签(item-tag,tag模式)

  • display: flex; align-items: center; justify-content: center; text-align: center(横向纵向双重居中)
  • width: 34.2mm(固定宽度)
  • padding: 0.4mm 1mm
  • font-size: 12pt
  • line-height: 1.25
  • border-radius: 3px
  • border: 1px solid
  • word-break: break-all(长名称自动换行)
  • 每行排3个标签(由max-width约束)
  • 背景色/文字色/边框色:按环节主题色(tag_bg / tag_color / tag_border)

三级面板(box,box模式)

  • 背景:#fafbfc
  • border-radius: 2px
  • padding: 0.6mm 1.5mm
  • border: 1px solid rgba(0,0,0,.04)
  • box-title: 10pt,700字重,tag_color色,底部虚线分隔

企业标签(company-tag,box模式)

  • 每行排3个企业标签
  • 标签宽度:calc(33.33% - 1.5mm)
  • 标签间距gap:1.5mm
  • justify-content: space-between
  • ::after伪元素防止末行标签拉伸
  • 字号:9pt
  • padding: 0.25mm 0.8mm
  • text-align: center
  • white-space: nowrap + overflow:hidden + text-overflow:ellipsis
  • border-radius: 3px
  • 印刷版默认每个三级环节最多显示6家企业

颜色方案

| 环节 | 主色 | 深色 | 标签背景 | 标签文字 | 标签边框 | 面板背景 | 渐变头 | |------|------|------|---------|---------|---------|---------|--------| | 上游 | #E67E22 | #D35400 | #FDF2E9 | #C0530A | #F5CBA7 | #FEF7F2 | linear-gradient(135deg,#E67E22,#D35400) | | 中游 | #2471A3 | #1B4F72 | #EBF5FB | #1A5276 | #AED6F1 | #F0F8FD | linear-gradient(135deg,#2980B9,#1F618D) | | 下游 | #229954 | #196F3D | #EAFAF1 | #1B7A43 | #ABEBC6 | #F0FBF5 | linear-gradient(135deg,#27AE60,#1E8449) | | 其他 | #7F8C8D | #566573 | #F2F4F4 | #566573 | #BDC3C7 | #F7F9F9 | linear-gradient(135deg,#95A5A6,#7F8C8D) |

字号规格汇总表(印刷版tag模式)

| 元素 | 字号 | 字重 | 说明 | |------|------|------|------| | 标题 atlas-title | 24pt | 800 | letter-spacing:2px | | 一级面板 col-header | 15pt | 700 | 白色文字,渐变背景 | | 二级面板 section-header | 13pt | 700 | tag_color色,section_bg背景 | | 三级标签 item-tag | 12pt | 正常 | tag_color色,tag_bg背景 | | 企业标签 company-tag(box模式) | 9pt | 正常 | tag_color色,tag_bg背景 | | box标题(box模式) | 10pt | 700 | tag_color色 |

截图生成(高清PNG)

使用Playwright生成4倍retina高清截图,保存到桌面:

from playwright.sync_api import sync_playwright
from PIL import Image
import os, sys, io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
Image.MAX_IMAGE_PIXELS = 300000000

# 页面387mm×210mm → 视口1464×794 @96dpi
# 4倍缩放 → 最终5856×3176像素高清PNG
VIEWPORT_W = 1464  # 387mm @96dpi
VIEWPORT_H = 794   # 210mm @96dpi
SCALE = 4

html_path = os.path.abspath('output.html')
url = 'file:///' + html_path.replace(chr(92), '/')  # Windows路径转file:// URL

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context(
        viewport={"width": VIEWPORT_W, "height": VIEWPORT_H},
        device_scale_factor=SCALE,
    )
    page = context.new_page()
    page.goto(url)
    page.wait_for_load_state("networkidle")  # 等待渲染完成
    page.screenshot(path="C:/Users/1/Desktop/output.png", full_page=True)
    browser.close()

# 生成预览缩略图用于Read工具验证(原图超2000px限制)
img = Image.open("C:/Users/1/Desktop/output.png")
img.thumbnail((1900, 1900), Image.LANCZOS)
img.save("preview.png")

截图参数:

  • 视口:1464 × 794(对应387mm × 210mm @96dpi)
  • device_scale_factor: 4(4倍retina高清)
  • full_page: True(全页捕获,不丢失底部内容)
  • page.goto(url) + page.wait_for_load_state("networkidle")(确保渲染完成,无需wait_for_timeout)
  • 输出尺寸:5856 × 3176像素
  • 保存路径:C:\Users<用户名>\Desktop\
  • PIL需设置 Image.MAX_IMAGE_PIXELS = 300000000 防止DecompressionBombError
  • Windows路径转file:// URL时用 chr(92) 替代反斜杠转义(避免Python字符串转义问题)
  • Python中文输出需 sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8',errors='replace')
  • 截图后用PIL Image.thumbnail((1900,1900))生成预览缩略图,再用Read工具验证渲染效果

屏幕展示版特性(非印刷版)

  • 浅米色网格背景(24px方格)
  • 顶部统计栏:大环节数、子环节数、细分领域数
  • 流向指示器:I → II → III
  • 卡片含描述摘要(限2行,box模式)
  • 底部图例
  • hover动画效果
  • max-width: 1920px

CSS陷阱与注意事项

1. flex容器内文本居中

flex容器内的文本节点会被包裹为匿名flex子项,该子项会填满容器宽度,导致justify-content:center无法居中文字。**必须同时设置text-align:center**才能确保文字横向居中。例如"石墨烯与碳纳米材料"等长标签名称需要此双重居中。

2. fit-content + flex-wrap 溢出

display:flex;flex-wrap:wrap容器使用width:fit-content时,浏览器会取max-content(即所有子项排一行的宽度),导致内容溢出页面(曾出现截图宽度9156px而非5856px的问题)。必须设置max-width约束到目标行宽,如max-width:calc(34.2mm * 3 + 4mm)限制为3个标签宽。

3. row-gap实现仅垂直间距

flex-wrap:wrap容器中,gap同时控制水平和垂直间距。若只需垂直间距而保持水平无间距,使用gap:0; row-gap:3ptrow-gap仅影响行间垂直间距,不影响同行标签间的水平布局。

4. 列宽收缩链

实现"各列刚好容纳内容"的紧凑布局需要层层收缩:

  • item-tag: 固定width:34.2mm
  • section: width:fit-content + max-width:calc(34.2mm*3+4mm) → 收缩至3个标签宽
  • column: flex:0 0 auto + width:fit-content → 收缩至刚好容纳所有section
  • columns: justify-content:center → 三列整体居中

5. 其他注意事项

  • 印刷版去除图例、统计栏、描述文字、流向箭头,仅保留核心图谱内容
  • 印刷版默认每个三级环节最多6家企业,可用--max-companies调整
  • 企业标签固定3列排列,6家=2行3列,超出部分不显示
  • 三列纵向使用space-between实现上下两端对齐
  • 大面板边框2px主题色,二级面板边框1.5px浅色,视觉层次分明
  • 截图必须用full_page=True防止底部内容截断

6. xlsx标签修改工作流

用户生成图谱后常发"XX改成YY"修改xlsx标签,标准流程:

  1. 用openpyxl加载xlsx,ws.iter_rows()遍历所有单元格查找匹配(注意:方法是iter_rows()不是iterrows()iterrows会报AttributeError)
  2. 修改cell.value后,先save到临时文件(如C:/Users/1/.qoderworkcn/workspace/mrmsovt88oyobi57/tmp_xlsx.xlsx),再用shutil.copy2覆盖到目标路径(避免xlsx被Excel占用时PermissionError)
  3. 重新执行generate_atlas.py生成HTML + 4x截图
import openpyxl, shutil, os
xlsx_path = 'C:/Users/1/Desktop/data.xlsx'
wb = openpyxl.load_workbook(xlsx_path)
ws = wb.active
for row in ws.iter_rows():  # 注意是iter_rows不是iterrows
    for cell in row:
        if cell.value == '旧标签名':
            cell.value = '新标签名'
tmp_path = 'C:/Users/1/.qoderworkcn/workspace/mrmsovt88oyobi57/tmp_xlsx.xlsx'
wb.save(tmp_path)
shutil.copy2(tmp_path, xlsx_path)
os.remove(tmp_path)

示例

# 从xlsx生成印刷版(tag模式,无企业数据)
python scripts/generate_atlas.py 煤化工产业链图谱_三级环节.xlsx --print -o 输出.html -t "煤化工产业链全景图"

# 从xlsx生成煤制油产业链图
python scripts/generate_atlas.py 煤制油产业链图谱_三级环节.xlsx --print -o 输出.html -t "煤制油产业链图"

# 从CSV生成印刷版(box模式,含企业数据)
python scripts/generate_atlas.py 产业链数据.csv --print -o 输出.html -t "产业链全景图"

# 限制每环节最多3家企业
python scripts/generate_atlas.py 产业链数据.csv --print --max-companies 3 -o 输出.html

# 生成屏幕展示版
python scripts/generate_atlas.py 产业链数据.xlsx --screen -o 输出.html -t "产业链全景图谱"