吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 268|回复: 4
上一主题 下一主题
收起左侧

[Python 原创] 微信公众号付费模板提取升级版

  [复制链接]
跳转到指定楼层
楼主
GUoOoOoOoOD 发表于 2026-4-14 14:15 回帖奖励
声明:本帖子思路是基于论坛另外一个铁子发布的公众号模板提取而来。再次基础上额外新增了一个html预览、模板实时预览的功能。
下方是公开的完整源码,方便与大家提取时能实时预览效果。
用AI写的GUI界面~
源码在下方直接复制粘贴就可以运行。
版本:3.12


教程还是一样的
公众号模板提取器使用说明:1. 选择编辑器类型(135编辑器 或 壹伴助手)2. 输入对应的模板ID3. 点击"开始提取"按钮4. 提取成功后,HTML代码会自动复制到剪贴板5. 打开微信公众号编辑器6. 切换到HTML代码模式7. 粘贴代码即可看到模板效果

预览图效果

ID提取教程:




[Python] 纯文本查看 复制代码
import re
import sys
import requests
from bs4 import BeautifulSoup
import pyperclip
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                             QHBoxLayout, QLabel, QLineEdit, QPushButton,
                             QRadioButton, QButtonGroup, QMessageBox, QFrame,
                             QTextEdit, QProgressBar)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QFont, QIcon
from PyQt5.QtWebEngineWidgets import QWebEngineView


class ExtractThread(QThread):
    """提取线程"""
    finished = pyqtSignal(str, str)  # (status, content/message)

    def __init__(self, editor_type, tid):
        super().__init__()
        self.editor_type = editor_type
        self.tid = tid

    def run(self):
        try:
            if self.editor_type == '135':
                content = self.get_135_html(self.tid)
            else:
                content = self.get_yiban_html(self.tid)

            # 复制到剪贴板
            pyperclip.copy(content)
            self.finished.emit('success', content)

        except Exception as e:
            self.finished.emit('error', str(e))

    def get_135_html(self, tid):
        """从135编辑器获取模板HTML"""
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36'
        }
        url = f'https://www.135editor.com/editor_styles/{tid}.html'
        resp = requests.get(url, headers=headers, timeout=10)
        resp.raise_for_status()

        com = re.compile('<div class=\"l-img\">.*?</div>', re.S)
        res = com.findall(resp.text)

        if res:
            return res[0]
        else:
            raise ValueError('模板ID错误,无法获取数据')

    def get_yiban_html(self, tid):
        """从壹伴助手获取模板HTML"""
        try:
            return self.yiban_template_api(tid)
        except Exception as e:
            print(f'模板接口失败尝试样式接口: {e}')
            try:
                return self.yiban_style_api(tid)
            except Exception as e2:
                raise ValueError('ID错误,无法获取数据')

    def yiban_template_api(self, tid):
        """壹伴模板API"""
        url = f'https://yiban.io/api/style_template/system/one?style_template_id={tid}'
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Accept': 'application/json, text/plain, */*',
            'Referer': 'https://yiban.io/',
            'Origin': 'https://yiban.io'
        }
        resp = requests.get(url, headers=headers, timeout=10)
        resp.raise_for_status()

        data = resp.json()
        if not data.get('success'):
            raise ValueError(data.get('status_message', '接口返回错误'))

        html = data['style_template']['total']
        if not html:
            raise ValueError('模板内容为空')

        return html

    def yiban_style_api(self, sid):
        """壹伴样式API"""
        url = f'https://yiban.io/api/article_editor/material/one?material_id={sid}'
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Accept': 'application/json, text/plain, */*',
            'Referer': 'https://yiban.io/',
            'Origin': 'https://yiban.io'
        }
        resp = requests.get(url, headers=headers, timeout=10)
        resp.raise_for_status()

        data = resp.json()
        if not data.get('success'):
            raise ValueError(data.get('status_message', '接口返回错误'))

        html = data['material']['detail']
        soup = BeautifulSoup(html, 'html.parser')
        sections = soup.find_all('section')

        for s in sections:
            if s.get('data-role') == 'paragraph' and (not s.get_text(strip=True)):
                continue
            if s.get('style') or s.find('img') or s.get_text(strip=True) or s.get('data-id'):
                return str(s)

        return html


class TemplateExtractor(QMainWindow):
    """模板提取助手主窗口"""

    def __init__(self):
        super().__init__()
        self.current_html = ""
        self.init_ui()
        self.set_default_values()

    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle('模板提取助手')
        self.resize(1400, 800)

        # 设置窗口样式
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f7fa;
            }
            QLabel {
                color: #333333;
                font-family: "Microsoft YaHei", "微软雅黑";
            }
            QRadioButton {
                font-family: "Microsoft YaHei", "微软雅黑";
                font-size: 12px;
                color: #333333;
                spacing: 8px;
            }
            QRadioButton::indicator {
                width: 15px;
                height: 15px;
            }
            QLineEdit {
                font-family: "Microsoft YaHei", "微软雅黑";
                font-size: 12px;
                padding: 5px;
                border: 1px solid #dcdcdc;
                border-radius: 3px;
                background-color: white;
            }
            QLineEdit:focus {
                border-color: #4CAF50;
            }
            QPushButton {
                font-family: "Microsoft YaHei", "微软雅黑";
                font-size: 12px;
                font-weight: bold;
                padding: 8px 20px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
            }
            QPushButton:hover {
                opacity: 0.9;
            }
            QPushButton:pressed {
                opacity: 0.8;
            }
            QPushButton:disabled {
                opacity: 0.5;
                cursor: not-allowed;
            }
            QTextEdit {
                border: 1px solid #dcdcdc;
                border-radius: 4px;
                font-family: "Consolas", "Monaco", monospace;
                font-size: 11px;
            }
        """)

        # 中央窗口部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局(水平布局:左侧控制区+代码区,右侧预览区)
        main_layout = QHBoxLayout(central_widget)
        main_layout.setSpacing(10)
        main_layout.setContentsMargins(10, 10, 10, 10)

        # ========== 左侧区域(控制区 + 代码区) ==========
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        left_layout.setSpacing(10)
        left_layout.setContentsMargins(0, 0, 0, 0)

        # 控制区域
        control_frame = QFrame()
        control_frame.setStyleSheet("""
            QFrame {
                background-color: white;
                border-radius: 8px;
                padding: 10px;
            }
        """)
        control_layout = QVBoxLayout(control_frame)
        control_layout.setSpacing(8)  # 减少间距

        # 标题
        title_label = QLabel('&#128221; 模板提取助手')
        title_font = QFont('Microsoft YaHei', 16, QFont.Bold)
        title_label.setFont(title_font)
        title_label.setAlignment(Qt.AlignCenter)
        title_label.setStyleSheet('color: #333333; margin-bottom: 5px;')
        control_layout.addWidget(title_label)

        # 编辑器选择区域
        selection_layout = QHBoxLayout()
        selection_layout.setSpacing(20)
        self.radio_135 = QRadioButton('&#128313; 135编辑器')
        self.radio_yiban = QRadioButton('&#128312; 壹伴助手')
        self.radio_135.setChecked(True)

        # 设置单选按钮组
        self.button_group = QButtonGroup()
        self.button_group.addButton(self.radio_135, 1)
        self.button_group.addButton(self.radio_yiban, 2)

        # 连接信号
        self.radio_135.toggled.connect(self.on_editor_change)
        self.radio_yiban.toggled.connect(self.on_editor_change)

        selection_layout.addWidget(self.radio_135)
        selection_layout.addWidget(self.radio_yiban)
        selection_layout.addStretch()
        control_layout.addLayout(selection_layout)

        # 输入和操作区域
        action_layout = QHBoxLayout()
        action_layout.setSpacing(10)

        action_layout = QHBoxLayout()
        action_layout.setSpacing(10)

        tip_label = QLabel('模板ID:')
        tip_label.setStyleSheet('font-size: 12px; font-weight: bold;')
        action_layout.addWidget(tip_label)

        self.id_input = QLineEdit()
        self.id_input.setFixedWidth(150)
        self.id_input.setPlaceholderText('请输入模板ID')
        self.id_input.returnPressed.connect(self.start_extract)
        action_layout.addWidget(self.id_input)

        # 左侧弹簧
        action_layout.addStretch()

        # 提取按钮
        self.extract_btn = QPushButton('开始提取')
        self.extract_btn.setFixedSize(120, 35)
        self.extract_btn.setStyleSheet("""
            QPushButton {
                background-color: #4CAF50;
                color: white;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
        """)
        self.extract_btn.clicked.connect(self.start_extract)
        action_layout.addWidget(self.extract_btn)

        # 复制按钮
        self.copy_btn = QPushButton('复制代码')
        self.copy_btn.setFixedSize(100, 35)
        self.copy_btn.setEnabled(False)
        self.copy_btn.setStyleSheet("""
            QPushButton {
                background-color: #2196F3;
                color: white;
            }
            QPushButton:hover {
                background-color: #1976D2;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
        """)
        self.copy_btn.clicked.connect(self.copy_html)
        action_layout.addWidget(self.copy_btn)

        # 使用教程按钮
        self.tutorial_btn = QPushButton('使用教程')
        self.tutorial_btn.setFixedSize(100, 35)
        self.tutorial_btn.setStyleSheet("""
            QPushButton {
                background-color: #FF9800;
                color: white;
            }
            QPushButton:hover {
                background-color: #F57C00;
            }
        """)
        self.tutorial_btn.clicked.connect(self.show_tutorial)
        action_layout.addWidget(self.tutorial_btn)

        # 右侧弹簧
        action_layout.addStretch()

        # 状态标签
        self.status_label = QLabel('')
        self.status_label.setStyleSheet('color: #888888; font-size: 10px;')
        action_layout.addWidget(self.status_label)

        control_layout.addLayout(action_layout)

        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        self.progress_bar.setFixedHeight(3)
        self.progress_bar.setStyleSheet("""
            QProgressBar {
                border: none;
                background-color: #e0e0e0;
                border-radius: 2px;
            }
            QProgressBar::chunk {
                background-color: #4CAF50;
                border-radius: 2px;
            }
        """)
        control_layout.addWidget(self.progress_bar)

        left_layout.addWidget(control_frame)

        # HTML代码显示区域(纯文本,自适应伸缩)
        code_frame = QFrame()
        code_frame.setStyleSheet("""
            QFrame {
                background-color: white;
                border-radius: 8px;
                padding: 5px;
            }
        """)
        code_layout = QVBoxLayout(code_frame)
        code_layout.setSpacing(5)
        code_layout.setContentsMargins(10, 5, 10, 10)

        code_label = QLabel('&#128196; HTML代码')
        code_label.setStyleSheet('font-weight: bold; font-size: 12px; padding: 0px;')
        code_layout.addWidget(code_label)

        # 使用QTextEdit显示纯文本HTML代码(不会渲染)
        self.code_editor = QTextEdit()
        self.code_editor.setFont(QFont('Consolas', 10))
        self.code_editor.setPlainText('')  # 设置为纯文本模式
        self.code_editor.setStyleSheet("""
            QTextEdit {
                background-color: #1e1e1e;
                color: #d4d4d4;
                border: none;
                font-family: "Consolas", "Monaco", monospace;
                font-size: 11px;
            }
        """)
        code_layout.addWidget(self.code_editor)

        left_layout.addWidget(code_frame, 1)  # 设置拉伸因子为1,让代码区自适应伸缩

        # ========== 右侧区域(实时预览) ==========
        right_widget = QWidget()
        right_widget.setFixedWidth(800)  # 添加这一行,固定宽度800
        right_layout = QVBoxLayout(right_widget)
        right_layout.setSpacing(5)
        right_layout.setContentsMargins(0, 0, 0, 0)

        preview_frame = QFrame()
        preview_frame.setStyleSheet("""
            QFrame {
                background-color: white;
                border-radius: 8px;
                padding: 5px;
            }
        """)
        preview_layout = QVBoxLayout(preview_frame)
        preview_layout.setSpacing(5)  # 减少标签和内容之间的间距
        preview_layout.setContentsMargins(10, 5, 10, 10)

        preview_label = QLabel('&#127760; 实时预览')
        preview_label.setStyleSheet('font-weight: bold; font-size: 12px; padding: 0px;')
        preview_layout.addWidget(preview_label)

        # 预览区域自适应高度
        self.web_view = QWebEngineView()
        self.web_view.setStyleSheet("border: none; border-radius: 4px;")
        preview_layout.addWidget(self.web_view, 1)  # 设置拉伸因子,让预览区自适应伸缩

        right_layout.addWidget(preview_frame, 1)  # 整个右侧区域自适应伸缩

        # 将左右区域添加到主布局
        main_layout.addWidget(left_widget, 1)
        main_layout.addWidget(right_widget)  # 右侧占1份宽度

    def show_tutorial(self):
        """显示使用教程"""
        tutorial_text = """使用教程

    公众号模板提取器使用说明:

    1. 选择编辑器类型(135编辑器 或 壹伴助手)
    2. 输入对应的模板ID
    3. 点击"开始提取"按钮
    4. 提取成功后,HTML代码会自动复制到剪贴板
    5. 打开微信公众号编辑器
    6. 切换到HTML代码模式
    7. 粘贴代码即可看到模板效果

    温馨提示:
    &#8226; 135编辑器默认ID:137387
    &#8226; 壹伴助手默认ID:24190
    &#8226; 提取的代码已自动复制,直接粘贴使用"""

        QMessageBox.information(self, '使用教程', tutorial_text)

    def set_default_values(self):
        """设置默认值"""
        self.id_input.setText('137387')

    def on_editor_change(self):
        """切换编辑器类型时更新界面"""
        if self.radio_135.isChecked():
            self.setWindowTitle('135收费模板提取助手 - 带预览')
            self.id_input.setText('137387')
            self.extract_btn.setStyleSheet("""
                QPushButton {
                    background-color: #4CAF50;
                    color: white;
                }
                QPushButton:hover {
                    background-color: #45a049;
                }
            """)
        else:
            self.setWindowTitle('壹伴样式提取助手 - 带预览')
            self.id_input.setText('24190')
            self.extract_btn.setStyleSheet("""
                QPushButton {
                    background-color: #FF9800;
                    color: white;
                }
                QPushButton:hover {
                    background-color: #F57C00;
                }
            """)
        self.id_input.setFocus()

    def start_extract(self):
        """启动提取任务"""
        tid = self.id_input.text().strip()
        if not tid:
            QMessageBox.warning(self, '&#9888;&#65039; 提示', '请输入模板ID')
            return

        # 获取编辑器类型
        editor_type = '135' if self.radio_135.isChecked() else 'yiban'

        # 禁用按钮并更新状态
        self.extract_btn.setEnabled(False)
        self.extract_btn.setText('提取中...')
        self.copy_btn.setEnabled(False)
        self.status_label.setText('正在获取模板,请稍候...')
        self.progress_bar.setVisible(True)
        self.progress_bar.setRange(0, 0)  # 无限进度

        # 清空之前的内容
        self.code_editor.clear()
        self.web_view.setHtml(
            '<html><body style="background-color:#f5f7fa; display:flex; align-items:center; justify-content:center; height:100vh; margin:0;"><p style="color:#999; font-family:Arial;">加载中...</p></body></html>')

        # 创建并启动提取线程
        self.extract_thread = ExtractThread(editor_type, tid)
        self.extract_thread.finished.connect(self.on_extract_finished)
        self.extract_thread.start()

    def on_extract_finished(self, status, content):
        """提取完成回调"""
        # 恢复按钮状态
        self.extract_btn.setEnabled(True)
        self.extract_btn.setText('开始提取')
        self.status_label.setText('')
        self.progress_bar.setVisible(False)

        # 显示结果
        if status == 'success':
            self.current_html = content

            # 在代码编辑器中显示纯HTML代码(使用setPlainText确保显示原始代码)
            self.code_editor.setPlainText(content)

            # 在Web视图中预览渲染效果
            self.web_view.setHtml(content)

            # 启用复制按钮
            self.copy_btn.setEnabled(True)

            # 显示成功消息
            QMessageBox.information(self, '&#9989; 成功', '模板提取成功!\n已复制到剪贴板,并显示在下方预览区。')
        else:
            self.web_view.setHtml(
                f'<html><body style="background-color:#f5f7fa; display:flex; align-items:center; justify-content:center; height:100vh; margin:0;"><p style="color:#f44336; font-family:Arial;">提取失败:{content}</p></body></html>')
            QMessageBox.critical(self, '&#10060; 错误', f'提取失败:{content}')

    def copy_html(self):
        """复制HTML代码到剪贴板"""
        if self.current_html:
            pyperclip.copy(self.current_html)
            QMessageBox.information(self, '&#9989; 成功', 'HTML代码已复制到剪贴板!')
        else:
            QMessageBox.warning(self, '&#9888;&#65039; 提示', '没有可复制的HTML代码')


def main():
    """主函数"""
    app = QApplication(sys.argv)

    # 设置应用程序图标
    try:
        app.setWindowIcon(QIcon('icon.ico'))
    except:
        pass

    window = TemplateExtractor()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

免费评分

参与人数 2吾爱币 +8 热心值 +2 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Hy2022 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
xiaobai 发表于 2026-4-14 19:56
越来越像以前的新浪博客了……
3#
MRBANK 发表于 2026-4-14 20:18
4#
yycvip 发表于 2026-4-14 20:40
可以回归到QQ空间了
以前的QQ空间就是可以使用html代码的
因为挂码的太多了,后来就封了
5#
liuxi 发表于 2026-4-14 21:30
这个确实很有用,试试看能不能搞定
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-4-15 05:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表