首页 > 编程语言 >python编写使用xmlrpc上传wordpress网站文章的程序

python编写使用xmlrpc上传wordpress网站文章的程序

时间:2024-07-03 16:29:13浏览次数:3  
标签:xmlrpc python text column wordpress tk file line row

1、安装库

        pip install python-wordpress-xmlrpc,tkinter,xmlrpc,json

2、发布文章

    url = "http://域名/xmlrpc.php"
    username = 用户名
    password = 密码
    title = 标题
    content = 内容
    tags = 标签
    categories = 分类
    client = Client(url, username, password)#登录
    post = WordPressPost()
    post.title = title
    post.content = content
    post.post_status = 'publish'#文章状态,publish表示发布,private表示私密的,draft表示草稿
    post.terms_names = {
        'post_tag': tags,
        'category': categories
    }
    client.call(posts.NewPost(post))#发布文章

3、增加功能

        因为需要给同事使用,除了基本的发布文章,增加了其他功能:交互界面、保存账号密码、上传文件,以PDF文件直接发布文章、设置特色图片、文件做为下载链接转换到文章内容等。可直接编译使用。

4、整体程序代码

import tkinter as tk
from tkinter import filedialog, messagebox, Toplevel
from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods import posts
from wordpress_xmlrpc.methods.media import UploadFile
import xmlrpc.client
from os.path import splitext, exists
import json

file_path = None
attachment_url = None
attachment_id=None
config_file = "config.json"

def save_credentials(username, password):
    credentials = {"username": username, "password": password}
    with open(config_file, "w") as f:
        json.dump(credentials, f)

def load_credentials():
    if exists(config_file):
        with open(config_file, "r") as f:
            return json.load(f)
    return {}

def upload_file():#上传文件
    global attachment_url, file_path, attachment_id
    if file_path:
        try:
            url = "http://域名/xmlrpc.php"
            username = username_entry.get()
            password = password_entry.get()
            client = Client(url, username, password)
            
            mime_types = {
                '.jpg': 'image/jpeg',
                '.jpeg': 'image/jpeg',
                '.png': 'image/png',
                '.gif': 'image/gif',
                '.bmp': 'image/bmp',
                '.pdf': 'application/pdf',
                '.doc': 'application/msword',
                '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                '.xls': 'application/vnd.ms-excel',
                '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                '.ppt': 'application/vnd.ms-powerpoint',
                '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
                '.txt': 'text/plain',
                '.zip': 'application/zip',
                '.rar': 'application/x-rar-compressed'
            }
            # 获取文件后缀名
            file_extension = splitext(file_path)[1].lower()
            mime_type = mime_types.get(file_extension, 'application/octet-stream')
            data = {
                'name': file_path,
                'type': mime_type
            }
            # 显示上传进度
            file_link_label.config(text="文件正在上传,请稍等!!!", fg="red", cursor="hand2")
            # 上传文件
            with open(file_path, 'rb') as f:
                data['bits'] = xmlrpc.client.Binary(f.read())
            print(data)
            response = client.call(UploadFile(data))
            attachment_id = response['id']
            attachment_url = response['url']
            file_link_label.config(text=f"文件链接: {attachment_url}", fg="blue", cursor="hand2")
            file_link_label.bind("<Button-1>", lambda e: open_link(attachment_url))
            print(f"特色图片: {attachment_id}")
            messagebox.showinfo("成功", "文件上传成功!")

        except Exception as e:
            messagebox.showerror("错误", f"文件上传失败: {e}")
    else:
        messagebox.showwarning("警告", "请选择一个文件进行上传。")


def pdf_file_button():
    global attachment_url
    # 如果选中了PDF文件发布选项,则将链接添加到文章内容中
    if attachment_url:
        # 提取文件名作为标题
        title = attachment_url.split('/')[-1].replace('-', ' ').split('.')[0]
        # 生成嵌入 PDF 的短代码
        shortcode = f'[pdf-embedder url="{attachment_url}" title="{title}"]'
        current_content = content_text.get("1.0", tk.END)
        if shortcode in current_content:
            messagebox.showwarning("警告", "文章内容中已存在PDF链接,请勿重复添加。")
            return
        content_text.delete("1.0", tk.END)
        content_text.insert(tk.END, shortcode)
    else:
        messagebox.showwarning("警告", "请先上传文件。")

def File_link_download():
    global attachment_url
    if attachment_url:
        # 生成HTML a标签
        link_text = "下载文件请点我!!!"
        shortcode = f'<a href="{attachment_url}">{link_text}</a>'
        current_content = content_text.get("1.0", tk.END)
        if shortcode in current_content:
            messagebox.showwarning("警告", "文章内容中已存在下载链接,请勿重复添加。")
            return
        content_text.insert(tk.END, shortcode)
    else:
        messagebox.showwarning("警告", "请先上传文件。")


def fetch_all_post_titles(client):
    offset = 0
    post_titles = []
    while True:
        posts_batch = client.call(posts.GetPosts({'number': 100, 'offset': offset}))
        if not posts_batch:
            break
        post_titles.extend(post.title for post in posts_batch)
        offset += 100
    return post_titles

def publish_post():#上传文章
    global attachment_url, attachment_id
    url = "http://域名/xmlrpc.php"
    username = username_entry.get()
    password = password_entry.get()
    title = title_entry.get()
    content = content_text.get("1.0", tk.END).strip()
    tags = tags_entry.get().split(',')
    if not tags or tags == ['']:
        tags = ['其他']

    # 获取选择的分类
    categories = [cat for cat, var in category_vars.items() if var.get()]
    if not categories:
        categories.append('其他')
    client = Client(url, username, password)
    post = WordPressPost()
    post.title = title
    post.content = content
    post.post_status = 'publish'#文章状态,不写默认是草稿,private表示私密的,draft表示草稿,publish表示发布
    post.terms_names = {
        'post_tag': tags,
        'category': categories
    }
    if  attachment_id and featured_images_var.get():
        post.thumbnail = attachment_id  # 设置特色图片
        print(f"特色图片: {attachment_id}")
    try:
        # 获取所有文章标题并检查是否重复
        all_post_titles = fetch_all_post_titles(client)
        if title in all_post_titles:
            messagebox.showwarning("警告", "文章标题已存在,请更换标题。")
            return

        # 如果选择了文件但没有上传文件,先上传文件
        if file_path and not attachment_url:
            upload_file()
            if  attachment_id and featured_images_var.get():
                post.thumbnail = attachment_id  # 设置特色图片
                print(f"特色图片: {attachment_id}")
        # 如果有上传的文件,添加附件信息
        #if attachment_url:
            
        
        # 发布文章
        client.call(posts.NewPost(post))
        messagebox.showinfo("成功", "文章发布成功!")
        
        # 保存用户名和密码
        if save_credentials_var.get():
            save_credentials(username, password)
    except Exception as e:
        messagebox.showerror("错误", f"发布失败: {e}")
        print(f"Exception: {e}")
        import traceback
        traceback.print_exc()

def select_file():
    global file_path, attachment_url
    file_path = filedialog.askopenfilename(filetypes=[("JPEG files", "*.jpg"), ("Word files", "*.docx"), ("pdf files", "*.pdf")])
    attachment_url = None
    if file_path:
        file_label.config(text=f"已选择文件: {file_path.split('/')[-1]}")
        print(f"选择的文件: {file_path}")

def open_link(url):
    import webbrowser
    webbrowser.open_new(url)


def show_instructions():
    # 创建新窗口
    instructions_window = Toplevel(root)
    instructions_window.title("软件使用说明")

    # 设置窗口大小和位置
    instructions_window.geometry("400x320")

    # 使用说明文本
    instructions_text = (
        "这是一个WordPress站点的文章发布软件。\n\n"
        "使用步骤:\n"
        "1. 输入用户名和密码。\n"
        "2. 输入文章标题和内容。\n"
        "3. 选择文章的标签和分类。(不填默认是'其他')\n"
        "4. 可选:选择并上传附件。 \n"
        "5. 可选:PDF文件可以获取到内容中直接发布。\n"
        "6. 可选:图片可以勾选作为特色图片。\n"
        "7. 可选:其他文件可以做为下载链接获取到内容中。\n"
        "8. 点击“发布文章”按钮,发布文章到WordPress站点。\n\n"
        "您还可以选择保存用户名和密码以便下次自动填充。\n"
    )

    # 在窗口中添加说明文本
    instructions_label = tk.Label(instructions_window, text=instructions_text, justify=tk.LEFT, wraplength=380)
    instructions_label.pack(pady=10, padx=10)

    # 添加关闭按钮
    close_button = tk.Button(instructions_window, text="关闭", command=instructions_window.destroy)
    close_button.pack(pady=5)



# 创建主窗口
root = tk.Tk()
root.title("WordPress 文章发布器")

# 组件标题
labels = ["用户名:", "密码:", "文章标题:", "文章内容:", "标签 (逗号分隔):", "分类 (多选):"]
max_label_len = max([len(label) for label in labels])

line_row = 0
column_number=6
# 用户名输入
tk.Label(root, text="用户名:").grid(row=line_row, column=0, sticky=tk.W, pady=5, padx=5)
username_entry = tk.Entry(root, width=50)
username_entry.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5)
line_row += 1

# 密码输入
tk.Label(root, text="密码:").grid(row=line_row, column=0, sticky=tk.W, pady=5, padx=5)
password_entry = tk.Entry(root, show="*", width=50)
password_entry.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5)
line_row += 1
# 文章标题输入
tk.Label(root, text="文章标题:").grid(row=line_row, column=0, sticky=tk.W, pady=5, padx=5)
title_entry = tk.Entry(root, width=50)
title_entry.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5)
line_row += 1
# 文章内容输入
tk.Label(root, text="文章内容:").grid(row=line_row, column=0, sticky=tk.NW, pady=5, padx=5)
content_text = tk.Text(root, height=10, width=50)
content_text.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5)
line_row += 1
# 文章标签输入
tk.Label(root, text="标签 (逗号分隔):").grid(row=line_row, column=0, sticky=tk.W, pady=5, padx=5)
tags_entry = tk.Entry(root, width=50)
tags_entry.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5)
line_row += 1
# 文章分类选择
tk.Label(root, text="分类 (多选):").grid(row=line_row, column=0, sticky=tk.NW, pady=5, padx=5)

# 用于保存分类选择状态的变量
category_vars = {}
categories = ['其他', '11'] # 可根据需要添加更多分类


category_vars = {}

# 计算每行应该显示的复选框数量
num_columns = 5
# 计算总行数
num_rows = (len(categories) + num_columns - 1) // num_columns
# 创建并布局分类项复选框
for index, category in enumerate(categories):
    var = tk.BooleanVar()
    category_vars[category] = var
    
    # 计算当前复选框应该放置的位置
    row = index // num_columns + line_row
    column = index % num_columns
    
    # 使用grid布局放置复选框,并使其在每个单元格居中对齐
    tk.Checkbutton(root, text=category, variable=var).grid(row=row + 1, column=column + 1, sticky=tk.W, pady=2, padx=5)



line_row += 6
# 文件选择按钮
tk.Label(root, text="附件:").grid(row=line_row, column=0, sticky=tk.W, pady=5, padx=5)
line_row += 1
file_btn = tk.Button(root, text="选择文件", command=select_file)
file_btn.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.W)
line_row += 1
file_label = tk.Label(root, text="未选择文件")
file_label.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.W)
line_row += 1
# 上传文件按钮
upload_btn = tk.Button(root, text="上传文件", command=upload_file)
upload_btn.grid(row=line_row, column=1, pady=5, padx=5, sticky=tk.W)
line_row += 1
# 文件链接标签
file_link_label = tk.Label(root, text="")
file_link_label.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.W)
line_row += 1
# 上传文件为特色图片
featured_images_var = tk.BooleanVar(value=False)  # 默认不勾选
featured_images = tk.Checkbutton(root, text="上传文件为特色图片")
featured_images.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.W)
line_row += 1
# 将PDF文件链接放到文章内容中
pdf_file_button = tk.Button(root, text="PDF文件做为文件内容", command=pdf_file_button)
pdf_file_button.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.W)
line_row += 1
# 将文件链接变成下载链接
download_Link = tk.Button(root, text="文件变成下载链接放文章内容中", command=File_link_download)
download_Link.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.W)
line_row += 1
# 保存用户名和密码复选框
save_credentials_var = tk.BooleanVar(value=True)  # 默认勾选
save_credentials_checkbutton = tk.Checkbutton(root, text="保存用户名和密码", variable=save_credentials_var)
save_credentials_checkbutton.grid(row=line_row, columnspan=column_number, column=1, pady=5, padx=5, sticky=tk.W)
line_row += 1
#软件说明按钮
instructions_button = tk.Button(root, text="使用说明", command=show_instructions)
instructions_button.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.E)
line_row += 1

# 发布按钮
publish_button = tk.Button(root, text="发布文章", command=publish_post)
publish_button.grid(row=line_row, column=1, columnspan=column_number, pady=5, padx=5, sticky=tk.E)
line_row += 1
# 加载保存的用户名和密码
credentials = load_credentials()
if credentials:
    username_entry.insert(0, credentials.get("username", ""))
    password_entry.insert(0, credentials.get("password", ""))



# 运行主循环
root.mainloop()

      

5、注意:

        网站防火墙需要添加白名单。

标签:xmlrpc,python,text,column,wordpress,tk,file,line,row
From: https://blog.csdn.net/weixin_52037378/article/details/140133536

相关文章

  • python钉钉告警脚本
    !/usr/bin/envpython3coding:utf-8importrequests,json,sys,os,datetimewebhook="https://oapi.dingtalk.com/robot/send?access_token=88bddd19055305c4fba1f9698cabe891de279254ed6e331bc6a3005274478b71"user=sys.argv[1]text=sys.argv[3]data={"m......
  • 掌握 Python 中 isinstance 的正确用法
    ......
  • 精准控制:为不同Python包指定个性化源
    精准控制:为不同Python包指定个性化源在Python项目开发中,我们经常使用Pip来安装和管理包。默认情况下,Pip从Python包索引(PyPI)下载包,但有时由于网络问题或地理位置,直接从默认源下载可能会很慢或不可用。此外,某些包可能只在特定的源中可用。本文将详细介绍如何为不同的包指定不......
  • python-进阶2
    三大特征1.继承1.1单继承1.2多继承1.3方法调用顺序1.4调用父类方法1.5super1.6多层继承2封装3多态3.1入门3.2条件3.3优势4抽象5类属性与方法5.1类属性5.2类方法5.3静态方法1.继承面向对象中的继承:指的是多个类之间的所属关系,即子类默认......
  • python操作哨兵、集群、缓存优化
    【python操作哨兵】11redis的主从,一主多从22高可用:sentinal:哨兵3多个哨兵:配置文件---》监控我们主从状态--》当发现主库--》故障转移43python如何操作哨兵567--------------------------------------------------------------------------------......
  • 这份Excel+Python飞速搞定数据分析手册,简直可以让Excel飞起来
    微软在UserVoice上运营着⼀个反馈论坛,每个⼈都可以在这⾥提交新点⼦供他⼈投票。票数最⾼的功能请求是“将Python作为Excel的⼀门脚本语⾔”,其得票数差不多是第⼆名的两倍。尽管⾃2015年这个点⼦发布以来并没有什么实质性进展,但在2020年年末,Python之⽗GuidovanRoss......
  • 使用Python进行开发人工智能
    AI人工智能(AI)是当前科技领域的热门话题使用Python进行AI开发成为许多开发者的首选因为Python语言简单易学庞大的库和框架支持使得AI开发更加高效和便捷本文将为你提供一个使用Python开发人工智能的学习路线并结合一些代码示例帮助你快速入门和掌握这项技术......
  • ESP32 wifi 串口转发数据 UART micropython
    最近有个项目需要远距离读uart串口打印出来的数据,但是淘宝的调试助手太贵了,开源平台找了圈也许是因为功能太简单,好像没怎么找到或者说连接配置的方式很麻烦,所以我花了半天时间写了一个.如果有同样需求的小白可以直接用这个程序跑本方案主要是把esp32配置成AP模式.并且......
  • Python爬虫实战案例——王者荣耀皮肤抓取
    大家好,我是你们的老朋友——南枫,今天我们一起来学习一下该如何抓取大家经常玩的游戏——王者荣耀里面的所有英雄的皮肤。老规矩,直接上代码:导入我们需要使用到的,也是唯一用到的库:我们要抓取皮肤其实就是相当于抓图片,那么像这种大网站,大批量的图片它基本上是在一个文件里......
  • 完美解决stack Error: Can‘t find Python executable “python“, you can set the P
    解决方案:node版本太高了,我同时说他环境是node14的,我就来了个14.18的,结果还是不是,应该是14系列,我的二级版本还是高了。python什么的安装了没什么用!!!一步一步来,先解决第一部分:错误提示的意思是说我没有python,我电脑里确实没有下载python,但实际上不用下载python也能解决这个问题。......