(原创) 📰 自动化新闻解析与发布系统详解

🚀 项目概述

这是一个基于PHP开发的全自动新闻采集、AI解析与WordPress发布系统,能够智能获取最新新闻、通过DeepSeek AI进行深度分析,并自动发布到WordPress网站。

系统架构
PHP版本
数据库

📊 系统架构

🏗️ 核心组件

graph TB
    A[新闻API] --> B[SendPost.php]
    B --> C[DeepSeek解析]
    B --> D[HTML内容提取]
    C --> E[WordPress发布]
    D --> C
    F[SQLite数据库] --> B

📁 文件结构

├── 📄 SendPost.php          # 主入口文件
├── 📄 DeepSeekAPIDemo.php   # DeepSeek API交互类
├── 📄 WordPressPostCreator.php # WordPress发布类
├── 📄 HtmlToText.php        # HTML内容提取类
├── 📄 function.php          # 通用函数库
└── 📁 post.db              # SQLite数据库文件

🔧 安装与配置

📋 环境要求

  • PHP 7.4+ 版本
  • cURL扩展 启用
  • PDO SQLite 支持
  • WordPress REST API 启用

⚙️ 配置步骤

1. 🔑 API密钥配置与注册

🤖 DeepSeek API
  • 注册地址: https://platform.deepseek.com/api_keys
  • 获取方式: 注册DeepSeek账号,进入控制台创建API密钥
  • 费用: 目前提供免费额度
// DeepSeek API配置
$DS_api_url = "https://api.deepseek.com/chat/completions";
$DS_api_key = '您的DeepSeek_API密钥';
📰 新闻API(探索API)
  • 注册地址: https://www.tanshuapi.com/
  • 获取方式: 注册账号,在个人中心获取API密钥
  • 费用: 提供免费和付费套餐
// 新闻API配置
$News_api_key = '您的新闻API密钥';
🌐 WordPress应用密码
  • 设置地址: WordPress后台 → 用户 → 编辑用户 → 应用密码
  • 获取方式: 生成新的应用密码,用于REST API认证
// WordPress配置
$WP_config = [
    'site_url' => 'https://您的网站.com',
    'username' => '用户名',
    'app_password' => '应用密码'
];

2. 🗄️ 数据库初始化

CREATE TABLE IF NOT EXISTS post (
    PID TEXT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

🎯 核心功能详解

1. 📰 新闻采集模块

🔍 新闻源集成

$url = "https://api.tanshuapi.com/api/toutiao/v1/index";
$result = curl_request($url, [
    'data' => [
        "key" => $News_api_key,
        "type" => "",
        "num" => "20",
        "start" => "0"
    ]
]);

功能特点:

  • 📡 支持多新闻源接入
  • 🔄 自动获取最新20条新闻
  • 🎯 可配置新闻类型和数量

2. 🤖 AI内容解析

🧠 DeepSeek智能解析

$DS_prompt = '你是一个专业的中文时事解说解析家。请遵循以下要求:
1. 收到新闻内容后,进行深度解析
2. 必须包含新闻的原文概括
3. 总字数必须严格控制在2000字以上
4. 必须包含丰富的图标符号...';

解析能力:

  • 📝 深度内容分析 – 超越简单摘要
  • 🎨 富文本格式化 – HTML结构化输出
  • 🔖 智能标签生成 – 自动提取关键词
  • 📊 数据可视化 – 图表符号增强可读性

3. 🖥️ WordPress发布

📝 文章创建功能

$post_data = [
    'title'   => $Content->title,
    'content' => $Content->content,
    'excerpt' => $Content->excerpt,
    'status'  => 'publish',
    'tags'    => $Content->tags,
    'featured_image_url' => $value->pic
];

发布特性:

  • 🖼️ 自动特色图片 – 从新闻图片URL下载并设置
  • 🏷️ 智能标签管理 – 自动创建或关联标签
  • 📂 分类支持 – 可配置文章分类
  • 🔄 重复检测 – 基于标题MD5避免重复发布

💡 技术亮点

1. 🛡️ 健壮的错误处理

try {
    $pdo = new PDO('sqlite:post.db');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    logEcho("✅ SQLite 连接成功!");
} catch(PDOException $e) {
    logEcho("❌ 连接失败: " . $e->getMessage());
}

2. 🔄 智能内容去重

$PID = md5($value->title);
$stmt = $pdo->prepare("SELECT count(*) Num FROM post where PID = ?");
// 避免重复处理相同新闻

3. 🎨 内容格式化

// HTML到纯文本转换
$converter = new HtmlToText();
$text = $converter->extractText($value->content);

🚀 使用指南

📥 安装步骤

  1. 下载所有PHP文件到您的服务器
  2. 配置API密钥SendPost.php
  3. 确保目录可写用于SQLite数据库
  4. 设置WordPress应用密码
  5. 运行脚本测试功能

⚡ 执行方式

🔧 命令行执行

php SendPost.php

⏰ 定时任务配置

# 每天上午9点执行
0 9 * * * /usr/bin/php /path/to/SendPost.php >> /path/to/logfile.log

🎛️ 自定义配置

📝 修改AI提示词

// 在$DS_prompt中调整解析要求
$DS_prompt = '您可以根据需求自定义解析风格和要求...';

🎨 调整输出格式

// 修改HTML输出结构
'format' => 'standard' // 可改为 'video', 'audio' 等

🔍 故障排除

🚨 常见问题

问题原因解决方案
❌ API连接失败网络问题或密钥错误检查网络连接和API密钥
🖼️ 图片上传失败图片URL不可访问使用备用图片或跳过
📝 内容解析错误AI响应格式异常检查prompt格式和API限额
🗄️ 数据库错误文件权限问题确保SQLite文件可写

📋 日志监控

function logEcho($Log){
    echo date("Y-m-d H:i:s", time()) . " -> " . $Log . "\r\n";
}
// 所有操作都有详细日志输出

🎉 效果展示

📊 生成内容示例

<h1>📈 经济数据分析报告</h1>
<blockquote>
💡 核心观点:市场呈现稳定增长趋势
</blockquote>

<h2>🔍 关键指标</h2>
<ul>
<li>📊 GDP增长率:5.3%</li>
<li>💹 通货膨胀率:2.1%</li>
<li>👥 就业率:96.7%</li>
</ul>

🔮 扩展可能性

🎯 功能扩展建议

  1. 🌐 多新闻源支持 – 集成更多新闻API
  2. 🎭 内容风格定制 – 不同主题使用不同AI角色
  3. 📱 多渠道发布 – 同步到社交媒体平台
  4. 📈 数据分析 – 内容效果统计和分析
  5. 🔄 实时监控 – Web界面监控运行状态

🔧 技术优化方向

  • ⚡ 性能优化 – 异步处理和队列机制
  • 🔒 安全增强 – API密钥加密存储
  • 📊 监控告警 – 异常状态自动通知
  • 🔧 配置界面 – Web管理后台

💎 总结

这个自动化新闻解析发布系统代表了内容创作自动化的前沿技术,通过AI智能解析和自动化发布,极大提高了内容生产的效率和质量。系统设计健壮、扩展性强,是媒体机构和内容创作者的理想解决方案。

🚀 立即开始使用,让AI为您创造价值!


📁 完整源代码

📄 SendPost.php

<?php
require "DeepSeekAPIDemo.php";
require "WordPressPostCreator.php";
require "HtmlToText.php";
require "function.php";

try {
    // 连接 SQLite 数据库文件
    $pdo = new PDO('sqlite:post.db');

    // 设置错误模式为异常
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    logEcho("✅ SQLite 连接成功!");
} catch(PDOException $e) {
    logEcho("❌ 连接失败: " . $e->getMessage());
}

// DS 配置信息
$DS_api_url = "https://api.deepseek.com/chat/completions";
$DS_api_key = 'sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$DS_prompt = '你是一个专业的中文时事解说解析家。请遵循以下要求:
1. 收到新闻内容后,进行深度解析
2. 必须包含新闻的原文概括
3. 总字数必须严格控制在2000字以上
4. 必须包含丰富的图标符号(如📊🔍💡🚨等)来增强可读性
5. 解析要专业、贴近实际、有深度见解
6. 必须使用HTML格式输出,合理使用h1-h6标签、ul/ol列表、blockquote引用等
7. 生成对应的中文标签
8. 只返回包含title、content、excerpt、tags的JSON数据

新闻内容:{$topic}

请确保:
- 内容分为多个逻辑清晰的章节
- 每个章节都有对应的图标
- 包含具体数据、案例分析和趋势预测
- 避免泛泛而谈,要有实质性内容
';

// WP 配置信息
$WP_config = [
    'site_url' => 'https://XXXXXX.XXX',
    'username' => 'XXXX',
    'app_password' => 'XXXX XXXX XXXX XXXX XXXX XXXX'
];

//News 配置
$News_api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

$url = "https://api.tanshuapi.com/api/toutiao/v1/index";
$result = curl_request($url,[
    'data' => [
        "key" => $News_api_key,
        "type" => "",
        "num" => "20",
        "start" => "0"
    ],
    'headers' => [
        'Content-Type: application/json'
    ],
    'ssl_verify' => false
]);

logEcho("正在获取新闻...");
$NewsList = json_decode($result["data"])->data->list;
logEcho("获取到".count($NewsList)."条新闻");
$demo = new DeepSeekAPIDemo($DS_api_url,$DS_api_key,$DS_prompt);

foreach ($NewsList as $key => $value) {
    logEcho("开始第 " . ($key+1) . " 条文章: " . $value->title . "(" . $value->url . ", " . $value->weburl . ")");
    logEcho("检查是否已存在...");
    $PID = md5($value->title);
    logEcho("PID: $PID");
    // 条件查询
    $stmt = $pdo->prepare("SELECT count(*) Num FROM post where PID = ?");
    $stmt->execute([$PID]);
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    if($results[0]["Num"] == 0){
        $stmt = $pdo->prepare("INSERT INTO post (PID) VALUES (?)");
        $stmt->execute([$PID]);
        logEcho("已记录文章特征...");
        logEcho("正在处理文章...");
        $converter = new HtmlToText();
        $text = $converter->extractText($value->content);
        logEcho("-------------------------文章内容-------------------------");
        logEcho($text);
        logEcho("---------------------------------------------------------");

        logEcho("Deepseek 正在处理...");
        $result1 = $demo->sendMessage(json_encode($value->content));
        logEcho("Deepseek 处理完成");

        if($result1["success"]){
            $pattern = '/```json\s*(.*?)\s*```/s';
            preg_match($pattern, $result1["content"], $matches);
            $Content = json_decode($matches[1]);
            logEcho("标题: $Content->title");
            logEcho("摘要: $Content->excerpt");
            $converter = new HtmlToText();
            $text = $converter->extractText($Content->content);
            logEcho("内容:");
            logEcho("---------------------------------------------------------");
            logEcho($text);
            logEcho("---------------------------------------------------------");
            logEcho("标签: " . implode(', ', $Content->tags));
            // 创建API客户端实例
            $wp_api = new WordPressPostCreator(
                $WP_config['site_url'],
                $WP_config['username'],
                $WP_config['app_password']
            );

            // 文章数据 - 包含文本数组形式的标签
            $post_data = [
                'title'   => $Content->title,
                'content' => $Content->content,
                'excerpt' => $Content->excerpt,
                'status'  => 'publish',
                'author'  => 1,
                'tags' => $Content->tags,

                'slug' => MD5($PID.time()),
                'featured_image_url' => $value->pic, // 直接指定图片URL
                // 'featured_media' => null, // 特色图片ID
                'comment_status' => 'open',
                'ping_status' => 'open',
                'format' => 'standard'
            ];

            logEcho("开始创建文章");

            // 创建文章
            $result = $wp_api->createPost($post_data);

            // 处理结果
            logEcho("HTTP状态码: " . $result['http_code']);

            if ($result['http_code'] === 201) {
                logEcho("✅ 文章创建成功!");
                logEcho("-------------------------文章详情-------------------------");
                logEcho($result['response']['id'] . " -> 标题: " . $result['response']['title']['rendered']);
                logEcho("链接: " . $result['response']['link']);
                logEcho("发布时间: " . $result['response']['date']);
                logEcho("---------------------------------------------------------");

            } else {
                logEcho("❌ 文章创建失败");
                logEcho("-------------------------错误信息-------------------------");
                logEcho("错误信息: " . print_r($result['response'], true));

                if (!empty($result['error'])) {
                logEcho("cURL错误: " . $result['error']);
                }
                logEcho("---------------------------------------------------------");
            }
        }else{
            logEcho("❌ Deepseek Error");
            logEcho("-------------------------错误信息-------------------------");
            print_r($result1);
            logEcho("---------------------------------------------------------");
        }

    }else{
        logEcho("⚠️ 文章已存在 跳过...");
    }

}

📄 function.php

<?php

/**
 * 完整的cURL请求函数
 * @param string $url 请求地址
 * @param array $options 请求选项
 * @return array 返回结果数组
 */
function curl_request($url, $options = []) {
    // 默认配置
    $default_options = [
        'method' => 'GET',           // 请求方法:GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS等
        'data' => null,              // 请求数据:字符串、数组或JSON字符串
        'headers' => [],             // 请求头数组
        'timeout' => 30,             // 超时时间(秒)
        'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', // User-Agent
        'follow_redirects' => true,  // 是否跟随重定向
        'max_redirects' => 10,       // 最大重定向次数
        'ssl_verify' => false,       // 是否验证SSL证书
        'ssl_host' => false,         // 是否验证SSL主机名
        'return_transfer' => true,   // 是否返回传输内容
        'custom_request' => null,    // 自定义请求方法
        'proxy' => null,             // 代理服务器 [host, port, type, auth]
        'cookie' => null,            // Cookie文件路径或Cookie字符串
        'referer' => null,           // 来源页面
        'encoding' => 'gzip, deflate', // 接受编码
        'auth' => null,              // HTTP认证 [username, password, type] type: basic, digest
        'debug' => false,            // 是否调试模式
    ];

    // 合并配置
    $config = array_merge($default_options, $options);

    // 初始化cURL
    $ch = curl_init();

    // 设置基本选项
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, $config['return_transfer']);
    curl_setopt($ch, CURLOPT_TIMEOUT, $config['timeout']);
    curl_setopt($ch, CURLOPT_USERAGENT, $config['user_agent']);

    // 设置SSL相关选项
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $config['ssl_verify']);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $config['ssl_host'] ? 2 : 0);

    // 设置重定向
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $config['follow_redirects']);
    curl_setopt($ch, CURLOPT_MAXREDIRS, $config['max_redirects']);

    // 设置请求方法
    $method = strtoupper($config['custom_request'] ?: $config['method']);
    switch ($method) {
        case 'GET':
            curl_setopt($ch, CURLOPT_HTTPGET, true);
            // 如果是GET请求且data是数组,将参数拼接到URL
            if (is_array($config['data']) && !empty($config['data'])) {
                $query_string = http_build_query($config['data']);
                $url .= (strpos($url, '?') === false ? '?' : '&') . $query_string;
                curl_setopt($ch, CURLOPT_URL, $url);
            }
            break;

        case 'POST':
            curl_setopt($ch, CURLOPT_POST, true);
            break;

        case 'PUT':
        case 'DELETE':
        case 'PATCH':
        case 'HEAD':
        case 'OPTIONS':
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
            break;
    }

    // 设置请求数据(非GET请求)
    if ($method !== 'GET' && !is_null($config['data'])) {
        if (is_array($config['data']) || is_object($config['data'])) {
            // 检查Content-Type,如果是application/json则发送JSON数据
            $is_json = false;
            foreach ($config['headers'] as $header) {
                if (stripos($header, 'Content-Type: application/json') !== false) {
                    $config['data'] = json_encode($config['data']);
                    $is_json = true;
                    break;
                }
            }
            if (!$is_json) {
                $config['data'] = http_build_query($config['data']);
            }
        }
        curl_setopt($ch, CURLOPT_POSTFIELDS, $config['data']);
    }

    // 设置请求头
    if (!empty($config['headers'])) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $config['headers']);
    }

    // 设置代理
    if (!empty($config['proxy'])) {
        if (is_array($config['proxy'])) {
            curl_setopt($ch, CURLOPT_PROXY, $config['proxy']['host']);
            curl_setopt($ch, CURLOPT_PROXYPORT, $config['proxy']['port'] ?? 8080);
            if (isset($config['proxy']['type'])) {
                curl_setopt($ch, CURLOPT_PROXYTYPE, $config['proxy']['type']);
            }
            if (isset($config['proxy']['auth'])) {
                curl_setopt($ch, CURLOPT_PROXYUSERPWD, $config['proxy']['auth']);
            }
        } else {
            curl_setopt($ch, CURLOPT_PROXY, $config['proxy']);
        }
    }

    // 设置Cookie
    if (!empty($config['cookie'])) {
        if (file_exists($config['cookie'])) {
            curl_setopt($ch, CURLOPT_COOKIEFILE, $config['cookie']);
            curl_setopt($ch, CURLOPT_COOKIEJAR, $config['cookie']);
        } else {
            curl_setopt($ch, CURLOPT_COOKIE, $config['cookie']);
        }
    }

    // 设置来源页面
    if (!empty($config['referer'])) {
        curl_setopt($ch, CURLOPT_REFERER, $config['referer']);
    }

    // 设置编码
    if (!empty($config['encoding'])) {
        curl_setopt($ch, CURLOPT_ENCODING, $config['encoding']);
    }

    // 设置HTTP认证
    if (!empty($config['auth']) && is_array($config['auth'])) {
        $auth_type = strtoupper($config['auth']['type'] ?? 'basic');
        $auth_constant = 'CURLAUTH_' . $auth_type;
        if (defined($auth_constant)) {
            curl_setopt($ch, CURLOPT_HTTPAUTH, constant($auth_constant));
        } else {
            curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        }
        curl_setopt($ch, CURLOPT_USERPWD, $config['auth']['username'] . ':' . $config['auth']['password']);
    }

    // 调试模式
    if ($config['debug']) {
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        $verbose = fopen('php://temp', 'w+');
        curl_setopt($ch, CURLOPT_STDERR, $verbose);
    }

    // 获取响应头
    curl_setopt($ch, CURLOPT_HEADER, true);

    // 执行请求
    $response = curl_exec($ch);

    // 获取错误信息
    $error_number = curl_errno($ch);
    $error_message = curl_error($ch);

    // 获取请求信息
    $info = curl_getinfo($ch);

    // 分离响应头和响应体
    $header_size = $info['header_size'];
    $response_headers = substr($response, 0, $header_size);
    $response_body = substr($response, $header_size);

    // 关闭cURL资源
    curl_close($ch);

    // 构建返回结果
    $result = [
        'success' => $error_number === 0,
        'data' => $response_body,
        'http_code' => $info['http_code'],
        'info' => $info,
        'error' => $error_number !== 0 ? [
            'code' => $error_number,
            'message' => $error_message
        ] : null,
        'headers' => parse_headers($response_headers)  // 修复:移除 $this->
    ];

    // 调试信息
    if ($config['debug'] && isset($verbose)) {
        rewind($verbose);
        $result['debug'] = stream_get_contents($verbose);
        fclose($verbose);
    }

    return $result;
}

/**
 * 解析响应头
 * @param string $header_string 响应头字符串
 * @return array 解析后的头信息数组
 */
function parse_headers($header_string) {
    $headers = [];
    $lines = explode("\r\n", $header_string);

    foreach ($lines as $line) {
        if (strpos($line, ':') !== false) {
            list($key, $value) = explode(':', $line, 2);
            $headers[trim($key)] = trim($value);
        } elseif (preg_match('/HTTP\/(\d\.\d)\s+(\d+)/', $line, $matches)) {
            $headers['HTTP-Version'] = $matches[1];
            $headers['Status-Code'] = $matches[2];
        }
    }

    return $headers;
}

function logEcho($Log){
    echo date("Y-m-d H:i:s", time()) . " -> " . $Log . "\r\n";
}

📄 WordPressPostCreator.php

<?php
class WordPressPostCreator {
    private $api_url;
    private $username;
    private $app_password;

    public function __construct($site_url, $username, $app_password) {
        $this->api_url = rtrim($site_url, '/') . '/wp-json/wp/v2';
        $this->username = $username;
        $this->app_password = $app_password;
    }

    /**
     * 发送API请求
     */
    private function sendRequest($endpoint, $method = 'GET', $data = []) {
        $url = $this->api_url . $endpoint;

        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_USERPWD => $this->username . ':' . $this->app_password,
            CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
            ]
        ]);

        if (!empty($data) && in_array($method, ['POST', 'PUT'])) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        return [
            'http_code' => $http_code,
            'response' => json_decode($response, true),
            'error' => $error
        ];
    }

    /**
     * 上传URL图片并返回媒体ID
     */
    public function uploadImageFromUrl($image_url, $title = '', $alt_text = '') {
        echo "开始下载图片: " . $image_url . "\n";

        // 下载图片到临时文件
        $temp_filename = 'temp_image_' . md5($image_url) . '.jpg';
        $temp_filepath = __DIR__ . '/' . $temp_filename;

        $download_result = $this->downloadImage($image_url, $temp_filepath);
        if (!$download_result['success']) {
            return [
                'success' => false,
                'error' => '图片下载失败: ' . $download_result['error']
            ];
        }

        echo "图片下载成功,开始上传到WordPress...\n";

        // 上传图片到WordPress
        $upload_result = $this->uploadImageFile($temp_filepath, $title, $alt_text);

        // 删除临时文件
        if (file_exists($temp_filepath)) {
            unlink($temp_filepath);
            echo "临时文件已清理\n";
        }

        return $upload_result;
    }

    /**
     * 下载网络图片到本地
     */
    private function downloadImage($image_url, $save_path) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $image_url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        ]);

        $image_data = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($http_code !== 200 || !$image_data) {
            return [
                'success' => false,
                'error' => 'HTTP ' . $http_code . ' - ' . $error
            ];
        }

        // 保存图片到临时文件
        $bytes_written = file_put_contents($save_path, $image_data);
        if ($bytes_written === false) {
            return [
                'success' => false,
                'error' => '无法保存临时文件'
            ];
        }

        return [
            'success' => true,
            'file_size' => $bytes_written,
            'file_path' => $save_path
        ];
    }

    /**
     * 上传本地图片文件到WordPress
     */
    private function uploadImageFile($file_path, $title = '', $alt_text = '') {
        if (!file_exists($file_path)) {
            return [
                'success' => false,
                'error' => '图片文件不存在: ' . $file_path
            ];
        }

        $file_name = basename($file_path);
        $mime_type = $this->getMimeType($file_path);

        // 准备上传数据
        $post_data = [
            'file' => new CURLFile($file_path, $mime_type, $file_name),
            'title' => $title ?: pathinfo($file_name, PATHINFO_FILENAME),
            'alt_text' => $alt_text,
            'caption' => '',
            'description' => ''
        ];
        // 发送上传请求
        $url = $this->api_url . '/media';
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_USERPWD => $this->username . ':' . $this->app_password,
            CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $post_data,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_HTTPHEADER => [
                'Content-Type: multipart/form-data',
            ]
        ]);

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        $response_data = json_decode($response, true);

        if ($http_code === 201) {
            return [
                'success' => true,
                'media_id' => $response_data['id'],
                'url' => $response_data['source_url'],
                'title' => $response_data['title']['raw'],
                'data' => $response_data
            ];
        } else {
            return [
                'success' => false,
                'error' => '上传失败: HTTP ' . $http_code,
                'response' => $response_data
            ];
        }
    }

    /**
     * 获取文件的MIME类型
     */
    private function getMimeType($file_path) {
        $extension = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
        $mime_types = [
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
            'webp' => 'image/webp',
            'svg' => 'image/svg+xml',
            'bmp' => 'image/bmp'
        ];

        return $mime_types[$extension] ?? 'image/jpeg';
    }

    /**
     * 根据标签名称获取或创建标签ID
     */
    public function getOrCreateTag($tag_name) {
        // 首先搜索是否已存在该标签
        $search_result = $this->sendRequest('/tags?search=' . urlencode($tag_name));

        if ($search_result['http_code'] === 200 && !empty($search_result['response'])) {
            // 找到现有标签
            foreach ($search_result['response'] as $tag) {
                if ($tag['name'] === $tag_name) {
                    return $tag['id'];
                }
            }
        }

        // 创建新标签
        $create_result = $this->sendRequest('/tags', 'POST', [
            'name' => $tag_name,
            'description' => '通过API创建的标签: ' . $tag_name
        ]);

        if ($create_result['http_code'] === 201) {
            return $create_result['response']['id'];
        } else {
            error_log("创建标签失败: " . print_r($create_result, true));
            return null;
        }
    }

    /**
     * 根据分类名称获取或创建分类ID
     */
    public function getOrCreateCategory($category_name) {
        // 搜索是否已存在该分类
        $search_result = $this->sendRequest('/categories?search=' . urlencode($category_name));

        if ($search_result['http_code'] === 200 && !empty($search_result['response'])) {
            foreach ($search_result['response'] as $category) {
                if ($category['name'] === $category_name) {
                    return $category['id'];
                }
            }
        }

        // 创建新分类
        $create_result = $this->sendRequest('/categories', 'POST', [
            'name' => $category_name,
            'description' => '通过API创建的分类: ' . $category_name
        ]);

        if ($create_result['http_code'] === 201) {
            return $create_result['response']['id'];
        } else {
            error_log("创建分类失败: " . print_r($create_result, true));
            return null;
        }
    }

    /**
     * 创建文章(增强版,支持特色图片URL)
     */
    public function createPost($post_data) {
        // 处理特色图片URL
        if (!empty($post_data['featured_image_url'])) {
            echo "处理特色图片...\n";
            $image_title = $post_data['title'] . ' - 特色图片';
            $upload_result = $this->uploadImageFromUrl(
                $post_data['featured_image_url'],
                $image_title,
                $post_data['title']
            );

            if ($upload_result['success']) {
                $post_data['featured_media'] = $upload_result['media_id'];
            } else {
                echo "⚠️ 特色图片上传失败: " . $upload_result['error'] . "\n";
            }
            unset($post_data['featured_image_url']);
        }

        // 处理标签 - 将标签名称数组转换为ID数组
        if (!empty($post_data['tags']) && is_array($post_data['tags'])) {
            $tag_ids = [];
            foreach ($post_data['tags'] as $tag_name) {
                $tag_id = $this->getOrCreateTag(trim($tag_name));
                if ($tag_id) {
                    $tag_ids[] = $tag_id;
                }
            }
            $post_data['tags'] = $tag_ids;
        }

        // 处理分类 - 将分类名称数组转换为ID数组
        if (!empty($post_data['categories']) && is_array($post_data['categories'])) {
            $category_ids = [];
            foreach ($post_data['categories'] as $category_name) {
                $category_id = $this->getOrCreateCategory(trim($category_name));
                if ($category_id) {
                    $category_ids[] = $category_id;
                }
            }
            $post_data['categories'] = $category_ids;
        }

        // 发送创建文章的请求
        return $this->sendRequest('/posts', 'POST', $post_data);
    }

    /**
     * 批量上传多张图片并返回ID数组
     */
    public function uploadMultipleImages($image_urls, $title_prefix = '图片') {
        $media_ids = [];

        foreach ($image_urls as $index => $image_url) {
            echo "处理第 " . ($index + 1) . " 张图片: " . $image_url . "\n";

            $title = $title_prefix . ' ' . ($index + 1);
            $upload_result = $this->uploadImageFromUrl($image_url, $title);

            if ($upload_result['success']) {
                $media_ids[] = $upload_result['media_id'];
                echo "✅ 图片上传成功,ID: " . $upload_result['media_id'] . "\n";
            } else {
                echo "❌ 图片上传失败: " . $upload_result['error'] . "\n";
            }

            // 避免请求过于频繁
            sleep(1);
        }

        return $media_ids;
    }
}
?>

📄 DeepSeekAPIDemo.php

<?php
class DeepSeekAPIDemo {
    private $api_url;
    private $api_key;
    private $prompt;

    public function __construct($api_url,$api_key,$prompt) {
        $this->api_url = $api_url;
        $this->api_key = $api_key;
        $this->prompt = $prompt;
    }

    /**
     * 发送消息到DeepSeek API
     */
    public function sendMessage($message) {
        // 准备请求数据
        $data = [
            'model' => 'deepseek-chat',
            'messages' => [
                [
                    "role" => "system",
                    "content" => $this->prompt
                ],
                [
                    'role' => 'user',
                    'content' => $message
                ]
            ],
            'temperature' => 0.7,
            'stream' => false
        ];
        // 准备cURL请求
        $ch = curl_init();

        curl_setopt_array($ch, [
            CURLOPT_URL => $this->api_url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $this->api_key
            ],
            CURLOPT_TIMEOUT => 180
        ]);

        // 执行请求
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        // 处理响应
        if ($http_code !== 200) {
            return [
                'success' => false,
                'error' => 'HTTP错误: ' . $http_code,
                'response' => $response
            ];
        }
        $result = json_decode($response, true);
        if (isset($result['choices'][0]['message']['content'])) {
            return [
                'success' => true,
                'content' => $result['choices'][0]['message']['content']
            ];
        } else {
            return [
                'success' => false,
                'error' => 'API响应格式错误',
                'response' => $response
            ];
        }
    }
}
?>

📄 HtmlToText.php

<?php

class HtmlToText
{
    private $dom;
    private $xpath;

    public function __construct()
    {
        $this->dom = new DOMDocument();
        $this->dom->preserveWhiteSpace = false;
    }

    /**
     * 从HTML源代码中提取纯文本
     * 
     * @param string $html 网页HTML源代码
     * @param bool $removeExtraSpaces 是否移除多余的空格和换行
     * @return string 提取的纯文本内容
     */
    public function extractText($html, $removeExtraSpaces = true)
    {
        // 抑制HTML解析错误警告
        libxml_use_internal_errors(true);

        // 加载HTML内容
        $this->dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));

        // 创建XPath对象
        $this->xpath = new DOMXPath($this->dom);

        // 移除不需要的元素(脚本、样式、注释等)
        $this->removeUnwantedElements();

        // 获取body内容
        $body = $this->dom->getElementsByTagName('body')->item(0);

        if ($body) {
            $text = $this->getNodeText($body);
        } else {
            $text = $this->getNodeText($this->dom->documentElement);
        }

        // 清理文本
        $text = $this->cleanText($text, $removeExtraSpaces);

        return $text;
    }

    /**
     * 移除不需要的HTML元素
     */
    private function removeUnwantedElements()
    {
        $tagsToRemove = [
            'script', 'style', 'noscript', 'iframe', 'object', 'embed',
            'header', 'footer', 'nav', 'aside', 'form', 'button'
        ];

        foreach ($tagsToRemove as $tag) {
            $elements = $this->dom->getElementsByTagName($tag);
            foreach ($elements as $element) {
                $element->parentNode->removeChild($element);
            }
        }

        // 移除注释
        $xpath = new DOMXPath($this->dom);
        $comments = $xpath->query('//comment()');
        foreach ($comments as $comment) {
            $comment->parentNode->removeChild($comment);
        }
    }

    /**
     * 递归获取节点的文本内容
     */
    private function getNodeText($node)
    {
        if ($node->nodeType === XML_TEXT_NODE) {
            return $node->textContent;
        }

        $text = '';

        // 处理特定标签的换行
        $blockTags = ['p', 'div', 'br', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];

        if (in_array($node->nodeName, $blockTags)) {
            $text .= "\n";
        }

        foreach ($node->childNodes as $child) {
            $text .= $this->getNodeText($child);
        }

        // 在表格单元格后添加空格
        if ($node->nodeName === 'td') {
            $text .= ' ';
        }

        return $text;
    }

    /**
     * 清理文本内容
     */
    private function cleanText($text, $removeExtraSpaces)
    {
        // 解码HTML实体
        $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');

        // 移除不可见字符
        $text = preg_replace('/\s+/u', ' ', $text);

        if ($removeExtraSpaces) {
            // 移除多余的空格和换行
            $text = preg_replace('/[ \t]+/', ' ', $text);
            $text = preg_replace('/\n\s*\n+/', "\n\n", $text);
            $text = trim($text);
        }

        return $text;
    }

    /**
     * 静态方法方便快速使用
     */
    public static function convert($html, $removeExtraSpaces = true)
    {
        $converter = new self();
        return $converter->extractText($html, $removeExtraSpaces);
    }
}
?>

🗄️ 数据库SQL代码

-- 创建post数据库表
CREATE TABLE IF NOT EXISTS post (
    PID TEXT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 创建索引以提高查询性能
CREATE INDEX IF NOT EXISTS idx_pid ON post (PID);
CREATE INDEX IF NOT EXISTS idx_created_at ON post (created_at);

🎯 快速开始

  1. 下载所有PHP文件到同一目录
  2. 创建SQLite数据库并执行上述SQL语句
  3. 注册各API服务获取密钥
  4. 配置SendPost.php中的API密钥信息
  5. 运行脚本开始自动化内容创作

🚀 祝您使用愉快!如有问题,请参考故障排除部分或查看详细日志输出。

↓↓↓↓↓↓↓原创不易点击下面给点打赏吧↓↓↓↓↓↓↓

评论

  1. 博主
    1 月前
    2025-10-30 17:40:45

    兄弟们,原创不易,给点打赏呗…….
    有问题可以留言 随时解答

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇