首页 > 其他分享 >利用diagrams渲染mermaid为xml文件

利用diagrams渲染mermaid为xml文件

时间:2024-06-20 17:27:37浏览次数:13  
标签:xml text ele click tag diagrams menu page mermaid

一、背景

        利用chatllama的方法进行数据增广,接入chatgpt 4o得到大量创建图表的mermaid代码。投喂大模型第一步就是将mermaid代码渲染成xml,为后续再将xml渲染成jpg提供铺垫。

mermaid介绍

        Mermaid 是一种基于 JavaScript 的开源图表生成工具,使用一种简单的 Markdown 风格的语法,创建各种类型的图表和图形,包括流程图、序列图、甘特图、类图等。

得到的JSON文档中包含mermaid代码和markdown代码

二、方法

        在 draw.io 网站上自动插入并导出 Mermaid 图表,从json中关键字“id”中的内容作为文件名保存xml文件。

代码功能概述

  1. validate_mermaid_code:清洗并验证 Mermaid 代码。
def validate_mermaid_code(text):
    # 清洗并验证Mermaid代码
    if text.startswith('```mermaid') and text.endswith('```'):
        text = text[11:-3].strip()
    return text
  1. click_menu_option:模拟点击 draw.io 菜单选项。
def click_menu_option(page, menu_text, option_text):
    for ele in page.ele('tag:div@class=geMenubar').eles('tag:a@class=geItem'):
        if ele.text == menu_text:
            ele.click()
            break

    for ele in page.eles('tag:td@class=mxPopupMenuItem'):
        if ele.text == option_text:
            ele.click()
            break
  1. drawio:将 Mermaid 代码插入到 draw.io 中,并导出为 XML 文件。
def drawio(page, text, file_name, error_dir):
    try:
        click_menu_option(page, '调整图形', '插入')
        click_menu_option(page, '插入', '高级')
        click_menu_option(page, '高级', 'Mermaid...')
        textarea = page.ele(
            'tag:textarea@style=box-sizing: border-box; resize: none; width: 100%; height: 354px; margin-bottom: 16px;')            #找到重置tag的属性
        textarea.clear()
        textarea.input(text)          

        for ele in page.eles('tag:button@class=geBtn gePrimaryBtn'):
            if ele.text == '插入':
                ele.click()

        if page.ele('tag:div@title=出错'):
            error_message = page.ele('tag:div@title=出错').text
            print(f"Error detected: {error_message}")
            page.ele('tag:button@class=geBtn').click()
            raise Exception("Error detected in Mermaid code insertion.")

        click_menu_option(page, '文件', '导出为')
        click_menu_option(page, '导出为', 'XML...')

        for ele in page.eles('tag:button@class=geBtn gePrimaryBtn'):
            if ele.text == '导出':
                ele.click()

        ele = page.ele('tag:input@@type=text@@style=box-sizing: border-box; width: 100%;')
        if ele.value == "未命名绘图.drawio.xml":
            ele.clear()
            ele.input(file_name)

        page.ele('tag:select@style=text-overflow: ellipsis; grid-column: 1;').select("设备")
        ele = page.ele('tag:div@style=flex-basis: 100%; text-align: right; margin-top: 16px;').ele(
            'tag:button@class=geBtn gePrimaryBtn')
        if ele.text == "保存":
            ele.click()

        click_menu_option(page, '文件', '关闭')

        ele = page.ele('tag:div@style=text-align: center; white-space: nowrap; margin-top: 12px;').ele(
            'tag:button@class=geBtn')
        if ele.text == "放弃更改":
            ele.click()

        try:
            page.ele('稍后再决定').click()
        except:
            pass
    except Exception as e:
        print(f"Error encountered: {e}")
        os.makedirs(error_dir, exist_ok=True)
        with open(os.path.join(error_dir, file_name.replace('.xml', '.txt')), 'w', encoding='utf-8') as f:
            f.write(text)
        raise e
  • 使用 click_menu_option 依次点击菜单,直到打开 Mermaid 插入窗口。
  • 清空文本区域并插入新的 Mermaid 代码。
  • 检查是否有错误信息,如果有则处理错误。
  • 依次点击菜单,直到导出 XML 文件。
  • 处理导出文件的命名和保存。
  • 如果遇到异常,创建错误文件夹并将出错的 Mermaid 代码保存到文件中。
  1. run:读取 JSON 文件中的 Mermaid 代码,并循环处理这些代码,将其插入到 draw.io 并导出。
def run(url, file_list, start_idx=0):
    page = WebPage()
    page.get(url)
    try:
        page.ele('稍后再决定').click()
    except:
        pass
    for cnt, text in tqdm(enumerate(file_list[start_idx:]), total=6500):
        try:
            file_name = f"{text['id'].replace('#', '_')}.xml"
            validated_text = validate_mermaid_code(text['answer_mode4'])
            drawio(page, validated_text, file_name, error_dir='./error_output')

            os.makedirs("./output", exist_ok=True)
            with open(f"./output/{text['id'].replace('#', '_')}.txt", 'w', encoding='utf-8') as f:
                f.write(text['answer_mode4'])
        except Exception as e:
            print(f"Failed | {e}")
            continue

这里是最麻烦的,网页卡住不动,程序就死掉了。需要设想好各种情况,如果出错或者网页崩溃,能够做到自更新。 

main函数

if __name__ == '__main__':
    url = "https://app.diagrams.net/"
    data = []
    with open(r'g1149_syn_mermaid_v2.json', 'r', encoding='utf-8') as f:
        for line in f.readlines():
            rec = json.loads(line.strip())
            if 'answer_mode4' in rec:
                text = rec['answer_mode4']
                data.append({"id": rec['id'], "answer_mode4": text})

    run(url, data, start_idx=0)  #设置start_idx方便调试

三、实际问题

1、需要科学上网才能跑,如果科学上网工具不行,网络波动大,那这个是跑不了的。

2、页面容易崩溃,崩溃后需要手动重启,这是最抓马的。大概4h崩溃一次。所以添加调试功能非常重要。

3、生成流程图的时候很快,但是在保存xml的时候就很慢很慢,我搜索了很多资料,也问了老师,老师说是页面渲染需要时间,无法解决。但是我知道肯定不是这样的原因,如果有大佬能优化这个,球球告知分享。

4、开始时,窗口要最大化,不然第一条的属性栏会莫名其貌的被隐藏。导致程序无法正常运行。

四、完整代码

# -*- coding: utf-8 -*-
import os
import json
from DrissionPage import WebPage
from tqdm import tqdm



def validate_mermaid_code(text):
    # 清洗并验证Mermaid代码
    if text.startswith('```mermaid') and text.endswith('```'):
        text = text[11:-3].strip()
    return text


def click_menu_option(page, menu_text, option_text):
    for ele in page.ele('tag:div@class=geMenubar').eles('tag:a@class=geItem'):
        if ele.text == menu_text:
            ele.click()
            break

    for ele in page.eles('tag:td@class=mxPopupMenuItem'):
        if ele.text == option_text:
            ele.click()
            break


def drawio(page, text, file_name, error_dir):
    try:
        print("Attempting to insert and export Mermaid code.")
        click_menu_option(page, '调整图形', '插入')
        click_menu_option(page, '插入', '高级')
        click_menu_option(page, '高级', 'Mermaid...')

        textarea = page.ele(
            'tag:textarea@style=box-sizing: border-box; resize: none; width: 100%; height: 354px; margin-bottom: 16px;')
        textarea.clear()
        textarea.input(text)

        for ele in page.eles('tag:button@class=geBtn gePrimaryBtn'):
            if ele.text == '插入':
                ele.click()

        # 检查是否有错误信息
        if page.ele('tag:div@title=出错'):
            error_message = page.ele('tag:div@title=出错').text
            print(f"Error detected: {error_message}")
            # 点击确认按钮
            page.ele('tag:button@class=geBtn').click()
            raise Exception("Error detected in Mermaid code insertion.")

        click_menu_option(page, '文件', '导出为')
        click_menu_option(page, '导出为', 'XML...')

        for ele in page.eles('tag:button@class=geBtn gePrimaryBtn'):
            if ele.text == '导出':
                ele.click()

        ele = page.ele('tag:input@@type=text@@style=box-sizing: border-box; width: 100%;')
        if ele.value == "未命名绘图.drawio.xml":
            ele.clear()
            ele.input(file_name)

        page.ele('tag:select@style=text-overflow: ellipsis; grid-column: 1;').select("设备")
        ele = page.ele('tag:div@style=flex-basis: 100%; text-align: right; margin-top: 16px;').ele(
            'tag:button@class=geBtn gePrimaryBtn')
        if ele.text == "保存":
            ele.click()

        click_menu_option(page, '文件', '关闭')

        ele = page.ele('tag:div@style=text-align: center; white-space: nowrap; margin-top: 12px;').ele(
            'tag:button@class=geBtn')
        if ele.text == "放弃更改":
            ele.click()

        try:
            page.ele('稍后再决定').click()
        except:
            pass
    except Exception as e:
        print(f"Error encountered: {e}")
        # 将出错文件复制到新文件夹
        os.makedirs(error_dir, exist_ok=True)
        with open(os.path.join(error_dir, file_name.replace('.xml', '.txt')), 'w', encoding='utf-8') as f:
            f.write(text)
        raise e

def run(url, file_list, start_idx=0):
    page = WebPage()
    page.get(url)
    try:
        page.ele('稍后再决定').click()
    except:
        pass
    for cnt, text in tqdm(enumerate(file_list[start_idx:]),total=6500):
        try:
            # 使用文件名中的ID命名文件
            file_name = f"{text['id'].replace('#', '_')}.xml"
            validated_text = validate_mermaid_code(text['answer_mode4'])
            drawio(page, validated_text, file_name, error_dir='./error_output')

            # 写入TXT文件
            os.makedirs("./output", exist_ok=True)
            with open(f"./output/{text['id'].replace('#', '_')}.txt", 'w', encoding='utf-8') as f:
                f.write(text['answer_mode4'])
        except Exception as e:
            print(f"Failed | {e}")
            continue


if __name__ == '__main__':
    url = "https://app.diagrams.net/"
    data = []
    with open(r'g1149_syn_mermaid_v2.json', 'r', encoding='utf-8') as f:
        for line in f.readlines():
            rec = json.loads(line.strip())
            if 'answer_mode4' in rec:
                text = rec['answer_mode4']
                data.append({"id": rec['id'], "answer_mode4": text})
    
    run(url, data, start_idx=0)

五、后续工作

将渲染的xml文件再次渲染为JPG文件 。

标签:xml,text,ele,click,tag,diagrams,menu,page,mermaid
From: https://blog.csdn.net/weixin_46636042/article/details/139835570

相关文章

  • Android的Manifest.xml文件有什么用
     Android的Manifest.xml文件是一个重要的配置文件,用于描述应用程序的各种信息,包括应用程序的包名、版本号、应用程序的入口Activity、权限要求等等。它的作用如下:1.声明权限:Manifest文件可以声明应用程序需要使用的权限,例如访问网络、读写SD卡等。当用户安装应用程序时,系统会向......
  • testng.xml文件
    1)首先要声明一个suite的名字,用于描述将要运行的测试脚本集,可以根据自己需要任意命名,最终这个名字会在testng的测试报告中看到。<!DOCTYPEsuiteSYSTEM"http://testng.org/testng-1.0.dtd"><suitename="SuiteName"verbose="1"><testname="TestName">......
  • maven 加载不到 mybatis xml 配置文件
     <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin>......
  • Unity 读取xml
      ReadXml.cs内容:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem.Xml;publicclassReadXml:MonoBehaviour{privateXmlDocumentxmldoc;privateXmlNoderoot;privatestringurl;voidStart(......
  • 【固定格式代码】SSM框架pom.xml配置
    <?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM......
  • 【固定格式代码】SSM框架web.xml配置
    <?xmlversion="1.0"encoding="UTF-8"?><web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee......
  • Dynamics CRM 365 使用FetchXml 查询数据(Query data using FetchXml )
    前言FetchXml是一种基于XML的专有查询语言,用于从Dataverse检索数据。添加引用Microsoft.CrmSdk.CoreAssembliesSystem.Configuration检索数据(Retrievedata)RetrieveMultipleusingMicrosoft.Xrm.Sdk.Query;usingMicrosoft.Xrm.Sdk;usingMicrosoft.Xrm.Tooling.C......
  • Dynamics CRM 365 使用 FetchXml 分页(Page results using FetchXml)
    介绍可以通过设置页面大小来指定对每个请求检索的行数的限制。通过使用分页,您可以检索连续的数据页,这些数据页表示符合查询条件的所有记录。默认和最大页面大小为5,000行。如果不设置页面大小,Dataverse将一次返回多达5000行数据。要获得更多行,必须发送额外的请求。不要将fetch......
  • Dynamics CRM 365 使用 FetchXml 聚合数据(Aggregate data using FetchXml)
    前言FetchXML包括分组和聚合功能,可用于计算多行数据的总和、平均值、最小值、最大值和计数。若要返回聚合值,必须:将aggregate设置为true。为每个属性元素设置别名alias属性。将每个属性元素的aggregate属性设置为以下聚合函数之一:函数返回值avg包含数据的......
  • 冲刺06fragment_reg_chi_fil_inf.xml
    <?xmlversion="1.0"encoding="utf-8"?><FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent&......