commit a2165c6934f8a70cd914784d6ff1a4e18612740e Author: ben Date: Sat Sep 6 07:56:24 2025 +0000 Initial commit: WordPress publishing tools diff --git a/.env b/.env new file mode 100644 index 0000000..cbe23d6 --- /dev/null +++ b/.env @@ -0,0 +1,11 @@ +#wordpress 凭据 +WORDPRESS_URL=https://podcaster.seekkey.tech +WORDPRESS_AUTH_METHOD=application_password +WORDPRESS_USERNAME=ben +WORDPRESS_APP_PASSWORD=EZSb Ujzk 80ns 6U1a sATw gPsR + +# judy 用户凭据 +JUDY_USERNAME=judy +JUDY_APP_PASSWORD=EZSb Ujzk 80ns 6U1a sATw gPsR +JUDY_UUID=9b6abf63-1ff2-4c82-8b9c-449a362d1b73 +JUDY_USER_ID=5 \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..4a9e016 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# WordPress 站点配置 +WORDPRESS_URL=https://your-wordpress-site.com +WORDPRESS_USERNAME=your-username +WORDPRESS_APP_PASSWORD=your-app-password + +# 可选:其他用户凭据 +# JUDY_USERNAME=judy +# JUDY_APP_PASSWORD=your-judy-app-password \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f921ec --- /dev/null +++ b/README.md @@ -0,0 +1,144 @@ +# WordPress 远程发布工具 + +这是一个用于远程操作 WordPress 网站的内容发布工具,通过 WordPress REST API 实现文章、分类、标签等内容的自动化管理。 + +## 功能特性 + +- 📝 **文章管理**: 创建、更新、删除文章 +- 📂 **分类管理**: 创建和管理文章分类 +- 🏷️ **标签管理**: 创建和管理文章标签 +- 🖼️ **媒体管理**: 上传和管理媒体文件 +- 🔐 **安全认证**: 使用 WordPress 应用密码进行安全认证 + +## 快速开始 + +### 1. 安装依赖 + +```bash +pip install -r requirements.txt +``` + +### 2. 配置环境变量 + +复制 `.env` 文件并填写你的 WordPress 站点信息: + +```bash +cp .env.example .env +``` + +编辑 `.env` 文件: + +```env +# WordPress 站点配置 +WORDPRESS_URL=https://your-wordpress-site.com +WORDPRESS_USERNAME=your-username +WORDPRESS_APP_PASSWORD=your-app-password +``` + +### 3. 测试连接 + +```bash +python test_wp_api.py +``` + +### 4. 发布内容 + +```bash +python publish_post.py +``` + +## 文件说明 + +- **`test_wp_api.py`**: API 连接测试脚本 +- **`wp_api_examples.py`**: 完整的 API 操作示例 +- **`publish_post.py`**: 简化的内容发布工具 +- **`.env`**: 环境配置文件 +- **`requirements.txt`**: Python 依赖包 + +## 使用示例 + +### 发布文章 + +```python +from publish_post import WordPressPublisher + +wp = WordPressPublisher() + +# 发布文章 +result = wp.publish_post( + title="我的新文章", + content="

这是文章内容

", + excerpt="文章摘要", + status="publish" # 或 "draft" 保存为草稿 +) +``` + +### 创建分类和标签 + +```python +# 创建分类 +category = wp.create_category("技术分享", "技术相关的文章分类") + +# 创建标签 +tag = wp.create_tag("Python", "Python 编程相关") + +# 发布文章时指定分类和标签 +wp.publish_post( + title="Python 教程", + content="

Python 编程教程内容

", + categories=[category['id']], + tags=[tag['id']] +) +``` + +## WordPress 应用密码设置 + +1. 登录 WordPress 后台 +2. 进入 **用户 -> 个人资料** +3. 滚动到 **应用密码** 部分 +4. 输入应用名称(如 "API 工具") +5. 点击 **添加新应用密码** +6. 复制生成的密码到 `.env` 文件中 + +## API 权限要求 + +确保你的 WordPress 用户具有以下权限: +- 发布文章 +- 编辑文章 +- 删除文章 +- 管理分类和标签 +- 上传媒体文件 + +通常需要 **编辑者** 或 **管理员** 角色。 + +## 注意事项 + +1. **HTTPS**: 建议使用 HTTPS 连接以确保安全 +2. **应用密码**: 使用应用密码而非普通登录密码 +3. **权限**: 确保用户具有相应的操作权限 +4. **测试**: 建议先在测试环境中验证功能 + +## 故障排除 + +### 认证失败 +- 检查用户名和应用密码是否正确 +- 确认应用密码格式正确(移除空格) +- 验证用户是否有足够权限 + +### 连接超时 +- 检查网络连接 +- 确认 WordPress 站点是否正常运行 +- 验证 URL 是否正确 + +### 权限不足 +- 确保用户为编辑者或管理员角色 +- 检查 WordPress REST API 是否启用 + +## 相关资源 + +- [WordPress REST API 官方文档](https://developer.wordpress.org/rest-api/) +- [WordPress 应用密码设置指南](https://wordpress.org/support/article/application-passwords/) + +--- + +**项目目标**: 为远程 WordPress 网站提供简单、安全的内容发布解决方案。 \ No newline at end of file diff --git a/proxy_control.sh b/proxy_control.sh new file mode 100755 index 0000000..52fed8f --- /dev/null +++ b/proxy_control.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# 代理控制脚本 + +proxy_on() { + export https_proxy="https://100.86.9.29:7890" + echo "✅ 代理已启用: $https_proxy" +} + +proxy_off() { + unset http_proxy https_proxy all_proxy + echo "✅ 代理已禁用" +} + +proxy_status() { + if [ -n "$https_proxy" ]; then + echo "🔵 代理状态: 启用 - $https_proxy" + else + echo "⚪ 代理状态: 禁用" + fi +} + +# 根据参数执行对应操作 +case "$1" in + "on") + proxy_on + ;; + "off") + proxy_off + ;; + "status") + proxy_status + ;; + *) + echo "用法: source proxy_control.sh [on|off|status]" + echo " on - 启用代理" + echo " off - 禁用代理" + echo " status - 查看代理状态" + ;; +esac \ No newline at end of file diff --git a/publish_post.py b/publish_post.py new file mode 100644 index 0000000..8048247 --- /dev/null +++ b/publish_post.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +WordPress 内容发布工具 +简化的内容发布脚本 +""" + +import os +import requests +from requests.auth import HTTPBasicAuth +from dotenv import load_dotenv +from datetime import datetime + +# 加载环境变量 +load_dotenv() + +class WordPressPublisher: + def __init__(self): + self.wp_url = os.getenv('WORDPRESS_URL') + self.wp_user = os.getenv('WORDPRESS_USERNAME') + self.wp_password = os.getenv('WORDPRESS_APP_PASSWORD') + + if self.wp_password: + self.wp_password = self.wp_password.replace(" ", "") + + if not all([self.wp_url, self.wp_user, self.wp_password]): + raise ValueError("请在 .env 文件中配置 WORDPRESS_URL, WORDPRESS_USERNAME, WORDPRESS_APP_PASSWORD") + + self.api_url = f"{self.wp_url.rstrip('/')}/wp-json/wp/v2" + self.auth = HTTPBasicAuth(self.wp_user, self.wp_password) + + def publish_post(self, title, content, excerpt="", categories=None, tags=None, status="publish"): + """ + 发布文章 + + Args: + title (str): 文章标题 + content (str): 文章内容 (HTML) + excerpt (str): 文章摘要 + categories (list): 分类ID列表 + tags (list): 标签ID列表 + status (str): 文章状态 (draft, publish, private) + + Returns: + dict: 创建的文章信息 + """ + post_data = { + 'title': title, + 'content': content, + 'excerpt': excerpt, + 'status': status + } + + if categories: + post_data['categories'] = categories + if tags: + post_data['tags'] = tags + + response = requests.post( + f"{self.api_url}/posts", + json=post_data, + auth=self.auth + ) + + if response.status_code == 201: + post = response.json() + print(f"✅ 文章发布成功!") + print(f" 标题: {post['title']['rendered']}") + print(f" 链接: {post['link']}") + print(f" 状态: {post['status']}") + return post + else: + print(f"❌ 文章发布失败: {response.status_code}") + print(f" 错误信息: {response.text}") + return None + + def get_categories(self): + """获取所有分类""" + response = requests.get(f"{self.api_url}/categories") + if response.status_code == 200: + return response.json() + return [] + + def get_tags(self): + """获取所有标签""" + response = requests.get(f"{self.api_url}/tags") + if response.status_code == 200: + return response.json() + return [] + + def create_category(self, name, description=""): + """创建新分类""" + category_data = { + 'name': name, + 'description': description + } + + response = requests.post( + f"{self.api_url}/categories", + json=category_data, + auth=self.auth + ) + + if response.status_code == 201: + category = response.json() + print(f"✅ 分类创建成功: {category['name']} (ID: {category['id']})") + return category + else: + print(f"❌ 分类创建失败: {response.status_code}") + return None + + def create_tag(self, name, description=""): + """创建新标签""" + tag_data = { + 'name': name, + 'description': description + } + + response = requests.post( + f"{self.api_url}/tags", + json=tag_data, + auth=self.auth + ) + + if response.status_code == 201: + tag = response.json() + print(f"✅ 标签创建成功: {tag['name']} (ID: {tag['id']})") + return tag + else: + print(f"❌ 标签创建失败: {response.status_code}") + return None + +def main(): + """示例用法""" + try: + wp = WordPressPublisher() + + # 示例:发布一篇文章 + title = f"测试文章 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" + content = """ +

这是一个测试文章

+

这是文章的内容。你可以使用 HTML 标签来格式化内容。

+ + """ + excerpt = "这是一个通过 API 发布的测试文章" + + # 发布为草稿,避免直接发布到生产环境 + result = wp.publish_post( + title=title, + content=content, + excerpt=excerpt, + status="draft" # 使用 "publish" 来直接发布 + ) + + if result: + print(f"\n📝 文章ID: {result['id']}") + print(f"🔗 编辑链接: {result['link'].replace('?preview=true', '')}") + + except Exception as e: + print(f"❌ 错误: {e}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..dff5783 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +requests>=2.31.0 +python-dotenv>=1.0.0 \ No newline at end of file diff --git a/test_wp_api.py b/test_wp_api.py new file mode 100644 index 0000000..ff2bb79 --- /dev/null +++ b/test_wp_api.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +WordPress REST API 测试脚本 +""" + +import os +import requests +import json +from requests.auth import HTTPBasicAuth +from dotenv import load_dotenv + +# 加载环境变量 +load_dotenv() + +# WordPress 配置信息 +WP_URL = os.getenv('WORDPRESS_URL') +WP_USER = os.getenv('WORDPRESS_USERNAME') +WP_APP_PASSWORD = os.getenv('WORDPRESS_APP_PASSWORD') + +# 移除密码中的空格 +if WP_APP_PASSWORD: + WP_APP_PASSWORD = WP_APP_PASSWORD.replace(" ", "") + +# 检查必需的环境变量 +if not all([WP_URL, WP_USER, WP_APP_PASSWORD]): + print("❌ 错误: 请在 .env 文件中配置 WORDPRESS_URL, WORDPRESS_USERNAME, WORDPRESS_APP_PASSWORD") + exit(1) + +class WordPressAPITester: + def __init__(self, url, username, app_password): + self.base_url = url.rstrip('/') + self.api_url = f"{self.base_url}/wp-json/wp/v2" + self.username = username + self.app_password = app_password + self.auth = HTTPBasicAuth(username, app_password) + + def test_connection(self): + """测试基本连接""" + print("🔍 测试 WordPress REST API 连接...") + try: + response = requests.get(f"{self.base_url}/wp-json", timeout=10) + if response.status_code == 200: + data = response.json() + print(f"✅ 连接成功!") + print(f" 站点名称: {data.get('name', 'N/A')}") + print(f" 描述: {data.get('description', 'N/A')}") + print(f" URL: {data.get('url', 'N/A')}") + print(f" WordPress版本: {data.get('gmt_offset', 'N/A')}") + return True + else: + print(f"❌ 连接失败: HTTP {response.status_code}") + return False + except requests.exceptions.RequestException as e: + print(f"❌ 连接错误: {e}") + return False + + def test_authentication(self): + """测试认证""" + print("\n🔐 测试用户认证...") + try: + response = requests.get(f"{self.api_url}/users/me", auth=self.auth, timeout=10) + if response.status_code == 200: + user_data = response.json() + print(f"✅ 认证成功!") + print(f" 用户ID: {user_data.get('id')}") + print(f" 用户名: {user_data.get('username')}") + print(f" 显示名称: {user_data.get('name')}") + print(f" 邮箱: {user_data.get('email')}") + print(f" 角色: {', '.join(user_data.get('roles', []))}") + return True + else: + print(f"❌ 认证失败: HTTP {response.status_code}") + if response.status_code == 401: + print(" 可能的原因: 用户名或应用密码错误") + elif response.status_code == 403: + print(" 可能的原因: 用户权限不足") + return False + except requests.exceptions.RequestException as e: + print(f"❌ 认证错误: {e}") + return False + + def test_posts_endpoint(self): + """测试文章端点""" + print("\n📝 测试文章端点...") + try: + # 获取文章列表 + response = requests.get(f"{self.api_url}/posts?per_page=5", timeout=10) + if response.status_code == 200: + posts = response.json() + print(f"✅ 文章端点正常! 找到 {len(posts)} 篇文章") + for i, post in enumerate(posts[:3], 1): + print(f" {i}. {post.get('title', {}).get('rendered', 'N/A')} (ID: {post.get('id')})") + return True + else: + print(f"❌ 文章端点失败: HTTP {response.status_code}") + return False + except requests.exceptions.RequestException as e: + print(f"❌ 文章端点错误: {e}") + return False + + def test_categories_endpoint(self): + """测试分类端点""" + print("\n📂 测试分类端点...") + try: + response = requests.get(f"{self.api_url}/categories", timeout=10) + if response.status_code == 200: + categories = response.json() + print(f"✅ 分类端点正常! 找到 {len(categories)} 个分类") + for i, cat in enumerate(categories[:3], 1): + print(f" {i}. {cat.get('name')} (ID: {cat.get('id')}, 文章数: {cat.get('count')})") + return True + else: + print(f"❌ 分类端点失败: HTTP {response.status_code}") + return False + except requests.exceptions.RequestException as e: + print(f"❌ 分类端点错误: {e}") + return False + + def test_media_endpoint(self): + """测试媒体端点""" + print("\n🖼️ 测试媒体端点...") + try: + response = requests.get(f"{self.api_url}/media?per_page=5", timeout=10) + if response.status_code == 200: + media = response.json() + print(f"✅ 媒体端点正常! 找到 {len(media)} 个媒体文件") + for i, item in enumerate(media[:3], 1): + print(f" {i}. {item.get('title', {}).get('rendered', 'N/A')} (类型: {item.get('media_type')})") + return True + else: + print(f"❌ 媒体端点失败: HTTP {response.status_code}") + return False + except requests.exceptions.RequestException as e: + print(f"❌ 媒体端点错误: {e}") + return False + + def test_write_permissions(self): + """测试写入权限""" + print("\n✏️ 测试写入权限...") + try: + # 尝试创建一个测试文章草稿 + test_post = { + 'title': 'API测试文章 - 请删除', + 'content': '这是一个API测试文章,可以安全删除。', + 'status': 'draft' # 草稿状态,不会公开发布 + } + + response = requests.post( + f"{self.api_url}/posts", + json=test_post, + auth=self.auth, + timeout=10 + ) + + if response.status_code == 201: + created_post = response.json() + post_id = created_post.get('id') + print(f"✅ 写入权限正常! 创建了测试文章 (ID: {post_id})") + + # 立即删除测试文章 + delete_response = requests.delete( + f"{self.api_url}/posts/{post_id}?force=true", + auth=self.auth, + timeout=10 + ) + + if delete_response.status_code == 200: + print(f"✅ 测试文章已清理 (ID: {post_id})") + else: + print(f"⚠️ 测试文章创建成功但清理失败 (ID: {post_id}),请手动删除") + + return True + else: + print(f"❌ 写入权限测试失败: HTTP {response.status_code}") + if response.status_code == 401: + print(" 可能的原因: 认证失败") + elif response.status_code == 403: + print(" 可能的原因: 用户没有发布文章的权限") + return False + + except requests.exceptions.RequestException as e: + print(f"❌ 写入权限测试错误: {e}") + return False + + def run_all_tests(self): + """运行所有测试""" + print("🚀 开始 WordPress REST API 全面测试\n") + print(f"测试目标: {self.base_url}") + print(f"用户: {self.username}") + print("=" * 50) + + tests = [ + self.test_connection, + self.test_authentication, + self.test_posts_endpoint, + self.test_categories_endpoint, + self.test_media_endpoint, + self.test_write_permissions + ] + + passed = 0 + total = len(tests) + + for test in tests: + if test(): + passed += 1 + + print("\n" + "=" * 50) + print(f"📊 测试结果: {passed}/{total} 项测试通过") + + if passed == total: + print("🎉 所有测试通过! WordPress REST API 工作正常") + elif passed >= total * 0.8: + print("⚠️ 大部分测试通过,但有一些问题需要注意") + else: + print("❌ 多项测试失败,请检查配置和权限") + + return passed, total + +def main(): + """主函数""" + tester = WordPressAPITester(WP_URL, WP_USER, WP_APP_PASSWORD) + tester.run_all_tests() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/wp_api_examples.py b/wp_api_examples.py new file mode 100644 index 0000000..1067052 --- /dev/null +++ b/wp_api_examples.py @@ -0,0 +1,374 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +WordPress REST API 使用示例 +演示常见的WordPress操作 +""" + +import os +import requests +import json +from requests.auth import HTTPBasicAuth +from datetime import datetime +from dotenv import load_dotenv + +# 加载环境变量 +load_dotenv() + +# WordPress 配置信息 +WP_URL = os.getenv('WORDPRESS_URL') +WP_USER = os.getenv('WORDPRESS_USERNAME') +WP_APP_PASSWORD = os.getenv('WORDPRESS_APP_PASSWORD') + +# 移除密码中的空格 +if WP_APP_PASSWORD: + WP_APP_PASSWORD = WP_APP_PASSWORD.replace(" ", "") + +# 检查必需的环境变量 +if not all([WP_URL, WP_USER, WP_APP_PASSWORD]): + print("❌ 错误: 请在 .env 文件中配置 WORDPRESS_URL, WORDPRESS_USERNAME, WORDPRESS_APP_PASSWORD") + exit(1) + +class WordPressAPI: + def __init__(self, url, username, app_password): + self.base_url = url.rstrip('/') + self.api_url = f"{self.base_url}/wp-json/wp/v2" + self.username = username + self.app_password = app_password + self.auth = HTTPBasicAuth(username, app_password) + + def get_posts(self, per_page=10, status='publish'): + """获取文章列表""" + params = { + 'per_page': per_page, + 'status': status + } + response = requests.get(f"{self.api_url}/posts", params=params) + if response.status_code == 200: + return response.json() + else: + print(f"获取文章失败: {response.status_code}") + return None + + def get_post_by_id(self, post_id): + """根据ID获取特定文章""" + response = requests.get(f"{self.api_url}/posts/{post_id}") + if response.status_code == 200: + return response.json() + else: + print(f"获取文章失败: {response.status_code}") + return None + + def create_post(self, title, content, status='draft', categories=None, tags=None): + """创建新文章""" + post_data = { + 'title': title, + 'content': content, + 'status': status + } + + if categories: + post_data['categories'] = categories + if tags: + post_data['tags'] = tags + + response = requests.post( + f"{self.api_url}/posts", + json=post_data, + auth=self.auth + ) + + if response.status_code == 201: + return response.json() + else: + print(f"创建文章失败: {response.status_code}") + print(response.text) + return None + + def update_post(self, post_id, title=None, content=None, status=None): + """更新文章""" + update_data = {} + if title: + update_data['title'] = title + if content: + update_data['content'] = content + if status: + update_data['status'] = status + + response = requests.post( + f"{self.api_url}/posts/{post_id}", + json=update_data, + auth=self.auth + ) + + if response.status_code == 200: + return response.json() + else: + print(f"更新文章失败: {response.status_code}") + return None + + def delete_post(self, post_id, force=False): + """删除文章""" + params = {'force': 'true'} if force else {} + response = requests.delete( + f"{self.api_url}/posts/{post_id}", + params=params, + auth=self.auth + ) + + if response.status_code == 200: + return response.json() + else: + print(f"删除文章失败: {response.status_code}") + return None + + def get_categories(self): + """获取分类列表""" + response = requests.get(f"{self.api_url}/categories") + if response.status_code == 200: + return response.json() + else: + print(f"获取分类失败: {response.status_code}") + return None + + def create_category(self, name, description="", parent=0): + """创建新分类""" + category_data = { + 'name': name, + 'description': description, + 'parent': parent + } + + response = requests.post( + f"{self.api_url}/categories", + json=category_data, + auth=self.auth + ) + + if response.status_code == 201: + return response.json() + else: + print(f"创建分类失败: {response.status_code}") + return None + + def get_tags(self): + """获取标签列表""" + response = requests.get(f"{self.api_url}/tags") + if response.status_code == 200: + return response.json() + else: + print(f"获取标签失败: {response.status_code}") + return None + + def create_tag(self, name, description=""): + """创建新标签""" + tag_data = { + 'name': name, + 'description': description + } + + response = requests.post( + f"{self.api_url}/tags", + json=tag_data, + auth=self.auth + ) + + if response.status_code == 201: + return response.json() + else: + print(f"创建标签失败: {response.status_code}") + return None + + def upload_media(self, file_path, title=None, alt_text=None): + """上传媒体文件""" + if not os.path.exists(file_path): + print(f"文件不存在: {file_path}") + return None + + filename = os.path.basename(file_path) + + with open(file_path, 'rb') as f: + files = { + 'file': (filename, f, 'application/octet-stream') + } + + data = {} + if title: + data['title'] = title + if alt_text: + data['alt_text'] = alt_text + + response = requests.post( + f"{self.api_url}/media", + files=files, + data=data, + auth=self.auth + ) + + if response.status_code == 201: + return response.json() + else: + print(f"上传媒体失败: {response.status_code}") + return None + + def get_media(self, per_page=10): + """获取媒体列表""" + params = {'per_page': per_page} + response = requests.get(f"{self.api_url}/media", params=params) + if response.status_code == 200: + return response.json() + else: + print(f"获取媒体失败: {response.status_code}") + return None + + def search_posts(self, search_term, per_page=10): + """搜索文章""" + params = { + 'search': search_term, + 'per_page': per_page + } + response = requests.get(f"{self.api_url}/posts", params=params) + if response.status_code == 200: + return response.json() + else: + print(f"搜索文章失败: {response.status_code}") + return None + +def demo_basic_operations(): + """演示基本操作""" + print("🚀 WordPress REST API 基本操作演示\n") + + wp = WordPressAPI(WP_URL, WP_USER, WP_APP_PASSWORD) + + # 1. 获取现有文章 + print("📝 获取现有文章...") + posts = wp.get_posts(per_page=5) + if posts: + print(f"找到 {len(posts)} 篇文章:") + for post in posts: + print(f" - {post['title']['rendered']} (ID: {post['id']})") + else: + print("没有找到文章") + + # 2. 获取分类 + print("\n📂 获取分类...") + categories = wp.get_categories() + if categories: + print(f"找到 {len(categories)} 个分类:") + for cat in categories: + print(f" - {cat['name']} (ID: {cat['id']}, 文章数: {cat['count']})") + + # 3. 获取标签 + print("\n🏷️ 获取标签...") + tags = wp.get_tags() + if tags: + print(f"找到 {len(tags)} 个标签:") + for tag in tags[:5]: # 只显示前5个 + print(f" - {tag['name']} (ID: {tag['id']}, 使用次数: {tag['count']})") + else: + print("没有找到标签") + + # 4. 获取媒体文件 + print("\n🖼️ 获取媒体文件...") + media = wp.get_media(per_page=5) + if media: + print(f"找到 {len(media)} 个媒体文件:") + for item in media: + print(f" - {item['title']['rendered']} (类型: {item['media_type']})") + + print("\n✅ 基本操作演示完成!") + +def demo_create_content(): + """演示内容创建""" + print("\n🎨 WordPress 内容创建演示\n") + + wp = WordPressAPI(WP_URL, WP_USER, WP_APP_PASSWORD) + + # 创建测试分类 + print("📂 创建测试分类...") + test_category = wp.create_category( + name="API测试分类", + description="这是通过API创建的测试分类" + ) + + if test_category: + category_id = test_category['id'] + print(f"✅ 分类创建成功 (ID: {category_id})") + + # 创建测试标签 + print("\n🏷️ 创建测试标签...") + test_tag = wp.create_tag( + name="API测试", + description="API测试标签" + ) + + if test_tag: + tag_id = test_tag['id'] + print(f"✅ 标签创建成功 (ID: {tag_id})") + + # 创建测试文章 + print("\n📝 创建测试文章...") + current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + test_post = wp.create_post( + title=f"API测试文章 - {current_time}", + content=f""" +

这是通过WordPress REST API创建的测试文章

+

创建时间: {current_time}

+

这篇文章演示了如何使用WordPress REST API进行内容管理:

+ +

注意: 这是一个测试文章,可以安全删除。

+ """, + status='draft', # 草稿状态 + categories=[category_id], + tags=[tag_id] + ) + + if test_post: + post_id = test_post['id'] + print(f"✅ 文章创建成功 (ID: {post_id})") + print(f" 标题: {test_post['title']['rendered']}") + print(f" 状态: {test_post['status']}") + print(f" 链接: {test_post['link']}") + + # 询问是否删除测试内容 + print("\n🗑️ 清理测试内容...") + + # 删除测试文章 + if wp.delete_post(post_id, force=True): + print(f"✅ 测试文章已删除 (ID: {post_id})") + + # 删除测试分类和标签需要小心,因为可能有其他内容在使用 + print("⚠️ 测试分类和标签保留,请手动删除如果不需要") + + else: + print("❌ 文章创建失败") + else: + print("❌ 标签创建失败") + else: + print("❌ 分类创建失败") + + print("\n✅ 内容创建演示完成!") + +def main(): + """主函数""" + print("WordPress REST API 使用示例") + print("=" * 40) + + # 基本操作演示 + demo_basic_operations() + + # 内容创建演示 + demo_create_content() + + print("\n🎉 所有演示完成!") + print("\n💡 提示:") + print("- 所有创建的测试内容都已清理") + print("- 你可以修改这个脚本来适应你的具体需求") + print("- 更多API文档: https://developer.wordpress.org/rest-api/") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/wp_publish.sh b/wp_publish.sh new file mode 100755 index 0000000..b43f459 --- /dev/null +++ b/wp_publish.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# WordPress 发布脚本 - 无代理环境 + +# 临时禁用代理 +unset http_proxy https_proxy all_proxy + +echo "🚀 WordPress 内容发布工具" +echo "==================================" + +# 检查参数 +if [ "$1" = "test" ]; then + echo "📋 执行 API 连接测试..." + python3 test_wp_api.py +elif [ "$1" = "publish" ]; then + echo "📝 执行内容发布..." + python3 publish_post.py +elif [ "$1" = "examples" ]; then + echo "📚 执行 API 示例..." + python3 wp_api_examples.py +else + echo "用法: ./wp_publish.sh [test|publish|examples]" + echo " test - 测试 API 连接" + echo " publish - 发布内容" + echo " examples - 运行 API 示例" +fi \ No newline at end of file