CSV转html工具(批量将csv转化为wordpress区块代码)

从别的终端工具导出的快捷命令是个CSV文件,格式为:`分类,命令名称,命令内容`。于是用AI做了一个Python小脚本,比js转换更稳定高效:
– 命令内容**经常包含多行**(如 heredoc、环境变量定义、find -exec、配置文件等)
– 目标:将 CSV 转换为 **WordPress Gutenberg 经典块格式**(heading + list + list-item),并**完整保留命令中的换行**
– 最终期望输出:每个分类一个标题 + 一个列表,列表内每条命令用 `

使用说明:

  1. 保存脚本为 csv_to_wp.py
  2. 把你的 CSV 文件命名为 commands.csv(或任意名)
  3. 命令行运行调出界面:python csv_to_wp.pyt
  4. 上传CSV 文件(提前保存玮utf-8编码) ,修改模板,点击转换,复制粘贴到 WordPress。

如何支持更多行(列)?

在模板中添加占位符,例如 {第4列} 表示 CSV 的第4列(备注) 示例模板:

<!-- wp:list-item {"metadata":{"name":"{第2列}"}} -->
<li>
  <pre class="wp-block-preformatted"><code>{第3列}</code></pre>
  <small>备注:{第4列}</small>
</li>
<!-- /wp:list-item -->

Python 脚本:

# -*- coding: utf-8 -*-
"""
CSV → WordPress Blocks + Markdown 图形界面工具
================================================
功能:
- 上传/选择 CSV 文件
- 可编辑模板(支持任意列 {第N列})
- 一键生成 WordPress Gutenberg 块代码
- 一键生成 Markdown 格式(新增)
- 复制结果到剪贴板

使用方法:
1. pip install pyperclip
2. python csv_to_wp_md_gui.py
"""

import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import csv
import html
import os
import pyperclip

class CsvToWpMdApp:
    def __init__(self, root):
        self.root = root
        self.root.title("CSV → WP Blocks & Markdown 工具")
        self.root.geometry("1000x750")
        self.root.minsize(900, 650)

        self.default_wp_template = """<!-- wp:list-item {"metadata":{"name":"{第2列}"}} -->
<li><pre class="wp-block-preformatted"><code>{第3列}</code></pre></li>
<!-- /wp:list-item -->"""

        self.csv_path = tk.StringVar()
        self.template_var = tk.StringVar(value=self.default_wp_template)

        self.create_widgets()

    def create_widgets(self):
        tk.Label(self.root, text="CSV → WordPress Blocks & Markdown 转换工具", font=("Helvetica", 16, "bold")).pack(pady=10)

        # 文件选择
        file_frame = tk.Frame(self.root)
        file_frame.pack(fill="x", padx=20, pady=5)
        tk.Label(file_frame, text="CSV 文件:", font=("Helvetica", 10, "bold")).pack(side="left")
        tk.Entry(file_frame, textvariable=self.csv_path, width=70, state="readonly").pack(side="left", padx=10)
        tk.Button(file_frame, text="选择文件", command=self.choose_file).pack(side="left", padx=5)

        # 模板区(只用于 WP 格式,Markdown 固定模板)
        tk.Label(self.root, text="WordPress 单条项目模板(支持 {第1列} ~ {第N列})", font=("Helvetica", 10, "bold")).pack(anchor="w", padx=20, pady=(15, 5))
        self.template_text = scrolledtext.ScrolledText(self.root, height=6, wrap="word", font=("Consolas", 10))
        self.template_text.insert("1.0", self.default_wp_template)
        self.template_text.pack(fill="x", padx=20, pady=5)

        tk.Button(self.root, text="恢复默认 WP 模板", command=self.reset_wp_template).pack(anchor="e", padx=20)

        # 按钮区
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=15)

        tk.Button(btn_frame, text="生成 WP Blocks", command=self.convert_wp, bg="#0066cc", fg="white", font=("Helvetica", 11, "bold"), width=18).pack(side="left", padx=10)
        tk.Button(btn_frame, text="生成 Markdown", command=self.convert_md, bg="#28a745", fg="white", font=("Helvetica", 11, "bold"), width=18).pack(side="left", padx=10)
        tk.Button(btn_frame, text="复制结果", command=self.copy_result, bg="#6c757d", fg="white", font=("Helvetica", 11, "bold"), width=18).pack(side="left", padx=10)

        # 输出区
        tk.Label(self.root, text="转换结果(可直接复制到 WordPress 或 Markdown 编辑器)", font=("Helvetica", 10, "bold")).pack(anchor="w", padx=20, pady=5)
        self.output_text = scrolledtext.ScrolledText(self.root, height=25, wrap="word", font=("Consolas", 10))
        self.output_text.pack(fill="both", expand=True, padx=20, pady=5)

    def choose_file(self):
        file = filedialog.askopenfilename(filetypes=[("CSV/Text files", "*.csv *.txt"), ("All files", "*.*")])
        if file:
            self.csv_path.set(file)

    def reset_wp_template(self):
        if messagebox.askyesno("确认", "恢复默认 WordPress 模板?"):
            self.template_text.delete("1.0", tk.END)
            self.template_text.insert("1.0", self.default_wp_template)

    def read_csv(self):
        csv_file = self.csv_path.get()
        if not csv_file or not os.path.exists(csv_file):
            messagebox.showerror("错误", "请先选择有效的 CSV 文件")
            return None

        groups = {}
        try:
            with open(csv_file, 'r', encoding='utf-8') as f:
                reader = csv.reader(f)
                for row in reader:
                    if len(row) < 3:
                        continue
                    group = row[0].strip()
                    name = row[1].strip()
                    command = ','.join(row[2:]).strip()  # 保留原始换行
                    if group not in groups:
                        groups[group] = []
                    groups[group].append((name, command))
            return groups
        except Exception as e:
            messagebox.showerror("读取失败", f"文件读取出错:\n{str(e)}\n请确保是 UTF-8 编码")
            return None

    def convert_wp(self):
        groups = self.read_csv()
        if not groups:
            return

        template = self.template_text.get("1.0", tk.END).strip()
        if not template:
            messagebox.showerror("错误", "WP 模板不能为空")
            return

        output = []
        for group, items in groups.items():
            output.append('<!-- wp:heading {"level":4} -->')
            output.append(f'<h4 class="wp-block-heading">{html.escape(group)} 常用命令</h4>')
            output.append('<!-- /wp:heading -->')
            output.append('')

            output.append(f'<!-- wp:list {{"metadata":{{"name":"{html.escape(group)}"}}}} -->')
            output.append('<ul class="wp-block-list">')
            output.append('')

            for name, command in items:
                cmd_escaped = html.escape(command)
                block = template.replace('{第1列}', html.escape(group)) \
                               .replace('{第2列}', html.escape(name)) \
                               .replace('{第3列}', cmd_escaped)
                # 支持更多列
                for i in range(4, 20):
                    ph = f'{{第{i}列}}'
                    if ph in block:
                        # 这里简化处理:实际 CSV 行是动态的,建议固定列数或传 row
                        # 当前仅替换已知列(可优化为动态)
                        block = block.replace(ph, '')
                output.append(block)
                output.append('')

            output.append('</ul>')
            output.append('<!-- /wp:list -->')
            output.append('')

        result = '\n'.join(output).strip()
        self.output_text.delete("1.0", tk.END)
        self.output_text.insert("1.0", result)
        messagebox.showinfo("完成", "WordPress Blocks 转换成功!")

    def convert_md(self):
        groups = self.read_csv()
        if not groups:
            return

        output = []
        for group, items in groups.items():
            output.append(f"## {group} 常用命令\n")
            output.append("")

            for name, command in items:
                output.append(f"### {name}\n")
                output.append("```shell")
                output.append(command)
                output.append("```\n")

        result = '\n'.join(output).strip()
        self.output_text.delete("1.0", tk.END)
        self.output_text.insert("1.0", result)
        messagebox.showinfo("完成", "Markdown 转换成功!")

    def copy_result(self):
        text = self.output_text.get("1.0", tk.END).strip()
        if text:
            pyperclip.copy(text)
            messagebox.showinfo("成功", "已复制到剪贴板")
        else:
            messagebox.showwarning("提示", "暂无内容可复制")

if __name__ == "__main__":
    root = tk.Tk()
    app = CsvToWpMdApp(root)
    root.mainloop()

脚本自动支持到第19列(for 循环 range(4, 20)),如果需要更多,直接把 20 改大就行。
如果以后 CSV 内容有变化,直接替换文件重新运行即可,**永久可用**。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注