🚀 项目概述
这是一个基于PHP开发的全自动新闻采集、AI解析与WordPress发布系统,能够智能获取最新新闻、通过DeepSeek AI进行深度分析,并自动发布到WordPress网站。
📊 系统架构
🏗️ 核心组件
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);
🚀 使用指南
📥 安装步骤
- 下载所有PHP文件到您的服务器
- 配置API密钥在
SendPost.php中 - 确保目录可写用于SQLite数据库
- 设置WordPress应用密码
- 运行脚本测试功能
⚡ 执行方式
🔧 命令行执行
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>
🔮 扩展可能性
🎯 功能扩展建议
- 🌐 多新闻源支持 – 集成更多新闻API
- 🎭 内容风格定制 – 不同主题使用不同AI角色
- 📱 多渠道发布 – 同步到社交媒体平台
- 📈 数据分析 – 内容效果统计和分析
- 🔄 实时监控 – 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);
🎯 快速开始
- 下载所有PHP文件到同一目录
- 创建SQLite数据库并执行上述SQL语句
- 注册各API服务获取密钥
- 配置SendPost.php中的API密钥信息
- 运行脚本开始自动化内容创作
🚀 祝您使用愉快!如有问题,请参考故障排除部分或查看详细日志输出。
↓↓↓↓↓↓↓原创不易点击下面给点打赏吧↓↓↓↓↓↓↓
兄弟们,原创不易,给点打赏呗…….
有问题可以留言 随时解答