PHP 协同 n8n 实现跨平台分发:从 50万+ 文章库到 TikTok/YouTube 的自动化内容流转

各位好,欢迎来到今天的“代码即魔法”专场。今天我们不聊虚无缥缈的架构图,也不整那些听着像在念经的 996 话术,我们直接上干货——如何用 PHP 这个“老古董”配上 n8n 这个“自动化猛兽”,把你的 50万+ 文章库变成自动喂给 TikTok 和 YouTube 的饲料。

听我说,很多人看到 50万篇文章,第一反应是头皮发麻,第二反应是想找根绳子把自己挂在服务器机架旁。但今天,我们要把这个庞然大物变成一只听话的绵羊,通过自动化工作流,让它主动走到 TikTok 和 YouTube 的舞台中央跳舞。

准备好了吗?我们要开始“肢解”这个工程了。

第一部分:PHP 不是老古董,它是数据库里的“老司机”

首先,咱们得正视一下 PHP。别老是用那种“PHP 已死”的陈词滥调来嘲讽它。PHP 在处理 HTTP 请求、连接数据库、序列化数据方面,依然是效率界的王者。特别是当我们面对海量数据时,PHP 的单进程模型在处理 I/O 密集型任务(比如读取 50万 行数据)时,配合适当的技巧,简直是神级操作。

我们的核心逻辑很简单:数据库拿数据 -> PHP 打包成 JSON -> 丢给 n8n -> n8n 分发给平台。

1. 别做“全表扫描”的傻瓜

很多新手写 PHP,上来就是 SELECT * FROM articles。朋友,你这是在炸服务器,不是在写代码。面对 50万条数据,你要做的是“分批取餐”。

我们要利用 LIMITOFFSET,或者更优雅的基于时间戳/ID 的查询。我推荐使用基于 ID 的游标方式,既快又不会锁表。

<?php
// database_config.php 已经配置好了 PDO 连接
// 这段代码是我们自动化管道的“取票口”

require_once 'database_config.php';

// 一次取 50 篇,别贪多,贪多嚼不烂,而且容易触发 API 限流
$batchSize = 50;
$processedIds = []; // 记录已经成功处理过的 ID,防止重复

try {
    // SQL 查询:只找那些还没发过视频的,或者需要重新发布的文章
    // 注意:为了演示,我假设有个 'status' 字段,这里用 OR 逻辑
    $stmt = $pdo->prepare("
        SELECT id, title, content, slug, created_at, cover_image 
        FROM articles 
        WHERE status IN ('draft', 'scheduled') 
        ORDER BY id ASC 
        LIMIT :limit
    ");

    $stmt->bindValue(':limit', $batchSize, PDO::PARAM_INT);
    $stmt->execute();

    $articles = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (!$articles) {
        echo "今天已经跑完了,或者没有待发布的文章,PHP 睡觉去了。n";
        exit;
    }

    // 关键一步:把 PHP 的数组转成 JSON。n8n 就爱吃这个。
    // 为了让 n8n 识别,我们加个元数据标记
    $payload = [
        'meta' => [
            'source' => 'php_legacy_backend',
            'timestamp' => time(),
            'total_articles' => count($articles)
        ],
        'data' => $articles
    ];

    // 设置响应头,告诉 n8n “我给你发 JSON 了”
    header('Content-Type: application/json');

    // 输出 JSON
    echo json_encode($payload, JSON_UNESCAPED_UNICODE);

} catch (PDOException $e) {
    // 别在日志里裸奔,至少记录一下错误
    error_log("Database Error: " . $e->getMessage());
    http_response_code(500);
    echo json_encode(['error' => 'Database connection failed']);
}
?>

这段代码的意义在于:它像是一个哨兵,每天定好闹钟(或者让 n8n 定时触发),醒来只抓 50 个还没被“喂”过的文章,打包成 JSON 喂给 n8n。多么优雅。

第二部分:n8n,你的“数字泰勒·斯威夫特”

n8n 是什么?它是连接一切的胶水,是自动化界的瑞士军刀。对于我们这个场景,n8n 就相当于那个拿着大喇叭的指挥家。

1. 第一步:Webhook 节点 —— 接吻的开始

我们需要 PHP 把 JSON 丢给 n8n,怎么丢?用 HTTP。n8n 提供一个免费的 Webhook URL。

在 n8n 里,拖入一个 Webhook 节点。

  • Method: POST
  • Path: /trigger-video-batch (随便起个名字,记住它)
  • Response Mode: On Response (这样 PHP 脚本执行完就能得到 n8n 的回复,虽然我们主要用 HTTP 请求主动拉取)

2. 第二步:HTTP Request 节点 —— PHP 的“求爱信”

现在,我们要在 n8n 里写一个 HTTP Request 节点,让 n8n 去问 PHP 要数据。

  • Method: GET
  • URL: http://your-php-server.com/get_batch.php
  • Authentication: None (如果是本地测试) 或者 Basic Auth (如果是远程服务)

点击“Execute Node”,你应该能看到 PHP 返回的 JSON 数据,里面躺着你的 50 篇文章。

第三部分:内容清洗与格式化 —— 让文章变得“上镜”

TikTok 和 YouTube 不会读小说,它们需要短小精悍的钩子。我们不能直接把 50万字的博客扔进去。我们需要在 n8n 里做个简单的“格式化大师”。

1. Split in Batches 节点

虽然我们一次抓了 50 篇,但为了保证每个视频都能成功上传,通常我们会把这 50 篇再切分成 5 批,每批 10 篇,或者每篇视频处理一次。为了演示简单,我们保持 50 篇不动,直接处理。

2. Function 节点 —— 你的 JS 小手

这是 n8n 最强大的地方之一。我们用一个 Function 节点来处理数据。

目标: 从文章标题和内容中截取前 100 个字作为视频描述。

// n8n Function Node Code
const items = this.getInputData();

return items.map(item => {
    // item.json 包含了 PHP 返回的 JSON 数据结构
    // 我们直接访问 item.json.data[0] 中的内容
    const article = item.json.data[0]; 

    // 简单的字符串处理,模拟生成“钩子”
    // 实际生产中,这里可以接 OpenAI API 让 AI 写脚本
    const title = article.title;
    const content = article.content;

    // 截取前 100 字
    const preview = content.length > 100 ? content.substring(0, 100) + '...' : content;

    // 构造适合 TikTok/YouTube 的新对象
    return {
        json: {
            video_id: article.id,
            title: title,
            description: `🔥 这里有个关于 ${title} 的精彩内容!nn${preview}nn#Automation #Tech #PHP #Life`,
            thumbnail_url: article.cover_image || "https://via.placeholder.com/1280x720.jpg?text=No+Cover",
            tags: ["Automation", "Tech", "PHP", "n8n"],
            // 确保数据类型正确,API 通常不喜欢 PHP 的空字符串变成 null
            status: "ready" 
        }
    };
});

这段代码运行后,你的数据就变成了 n8n 看得懂的格式:标题、描述、缩略图。是不是很爽?

第四部分:YouTube —— 庞大系统的噩梦与解决方案

YouTube 是个傲娇的家伙。它有个规矩:每个 Google 账号,最多只能同时上传 15 个视频,而且每天只能上传 50 个视频。 这对于 50万篇文章来说,简直是杯水车薪。

1. YouTube Data API v3 的接入

在 n8n 里,你要安装 YouTube 扩展(Node)。你需要一个 Google Cloud Project,开启 API,拿到 Client ID 和 Client Secret。

2. Loop over Items 节点 —— 逐个击破

因为 YouTube 限制太严,我们不能一次性扔 50 篇进去。在 Function 节点后面,我们要拖入一个 Loop over Items 节点。

这样,n8n 就会拿到你的 50 篇文章,然后循环执行以下操作 50 次。

3. YouTube Upload 节点配置

在 Loop 里面,放一个 YouTube Upload 节点。

  • Content Type: Video (或者 Audio,取决于你的文章怎么处理)
  • Privacy: Public (根据需求)
  • Video Title: {{ $json.title }}
  • Video Description: {{ $json.description }}
  • Thumbnail URL: {{ $json.thumbnail_url }}

注意: 实际上,YouTube API 对视频文件的格式有要求(MP4, WebM 等)。如果你的文章只是文字,你可能需要:

  1. 使用开源工具(如 ffmpeg)把文章文字合成一个简单的视频(比如字幕滚动视频),或者
  2. 调用 AI 视频生成 API(Runway, Pika 等)把图片转成视频,然后把视频 URL 传给 YouTube。

为了简化,我们假设你有一个脚本,能根据文章内容生成一个视频文件 video.mp4,并且 n8n 能访问这个文件。

这时候,HTTP Request 节点就不止是读数据了,它要写数据

4. HTTP Request 节点 —— 批量上传

在 Loop 内部,使用 HTTP Request 节点。

  • Method: POST
  • Authentication: OAuth2 (选择 “Upload Media” 模式)
  • URL: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=multipart&part=snippet,status
  • Body:
    {
      "snippet": {
        "title": "这里是标题",
        "description": "这里是描述",
        "tags": ["tag1", "tag2"],
        "categoryId": "22" // Technology
      },
      "status": {
        "privacyStatus": "public"
      }
    }
  • File: 选择你的本地视频文件路径。

当这个节点执行成功,YouTube 会返回 videoId。这时候,我们需要把这个 videoId 发回给 PHP 数据库,标记这篇文章“已经上传到 YouTube”。

第五部分:TikTok —— 那个疯狂的舞池

TikTok 呢?TikTok 更有意思。TikTok 官方的 API 对于批量上传是非常保守的。标准的 Creator API 主要用于发布笔记(图文),或者编辑视频。

如果你的目标是批量上传视频到 TikTok,通常有两种路径:

路径 A:使用 TikTok 广告 API (适用于企业账号)

这个比较硬核,需要企业认证,而且需要处理复杂的 OAuth 流程。n8n 支持得很不错,通过 HTTP Request 节点调用 TikTok API。

路径 B:模拟“创作者中心”操作 (适用于个人/小号)

这比较“野路子”,但也最常见。
n8n 可以利用 Puppeteer 节点或者 Crawlee 节点,模拟人类在 TikTok 创作者中心上传视频的操作。虽然这不稳定,但如果 TikTok 允许批量上传(实际上 API 对批量上传限制极严),这或许是唯一出路。

这里我们演示最“正规”的思路:通过 API 尝试上传(注:实际操作中需查阅最新官方文档,因为 TikTok API 经常变):

  1. Auth: 使用 OAuth2 节点获取 TikTok Token。
  2. Media Upload: 使用 HTTP Request 节点上传视频文件。TikTok 的 multipart upload 逻辑和 YouTube 类似,但 Endpoint 不同。
  3. Publish: 获取 media_id 后,再调用 Publish 接口。
// n8n Function Node 伪代码:准备 TikTok Payload
const data = {
    media_description: "这是自动化生成的视频描述",
    media_category: "Entertainment", // TikTok 类别
    // ... 其他参数
};

// n8n HTTP Request Node:
// POST https://open.tiktokapis.com/v2/media/upload/
// Headers: Authorization: "Bearer {{tiktok_token}}", Content-Type: "multipart/form-data"
// Body: 包含视频文件

专家提示: TikTok 对内容审核极其严格。如果你把所有文章都发去,大概率会被限流或者封号。建议使用 n8n 的 Wait 节点,在上传一个视频后,等待 30 分钟再上传下一个,模拟人工操作的节奏。

第六部分:闭环 —— 把状态传回 PHP

现在,我们的文章已经变成了视频,上传到了 YouTube 和 TikTok。

别忘了我们的 PHP 数据库里还有 50万 条数据。我们需要把它们的状态更新一下。

1. Update Article 节点

在 n8n 的工作流最后,我们加一个 HTTP Request 节点,把结果发回 PHP。

  • URL: http://your-php-server.com/update_status.php
  • Method: POST
  • Body:
    {
        "video_id": 12345, // YouTube 返回的 ID
        "tiktok_post_id": "abc123",
        "article_id": 50001,
        "platform": "youtube"
    }

2. PHP 的“反馈处理”脚本

PHP 端的 update_status.php 要写得健壮一些。

<?php
$data = json_decode(file_get_contents('php://input'), true);

if ($data) {
    $stmt = $pdo->prepare("UPDATE articles SET status = 'published_youtube', youtube_video_id = :vid, published_at = NOW() WHERE id = :id");
    $stmt->execute([
        ':vid' => $data['video_id'],
        ':id' => $data['article_id']
    ]);
    echo "Status updated for article " . $data['article_id'];
}
?>

第七部分:打造“不倒翁”系统 —— 错误处理与重试

你可能会问:“万一 n8n 上传到一半断了怎么办?我的 50万 文章岂不是白跑了?”

别慌,我们有 Error Trigger 节点和 Retry 机制。

1. Error Trigger

在 Loop 后面,把 On Error 的输出连到一个 If 节点。

2. 重试策略

在 HTTP Request 节点里,设置 Retry On Fail: Yes,重试 3 次。

3. 失败队列

如果实在不行,n8n 的数据会流向 On Error 分支。我们可以把这个失败的数据存入一个专门的 failed_uploads 数据库表,或者写入 Redis。第二天早上,我们手动点一下“重试失败任务”按钮,n8n 会从那个表里把剩下的文章重新拉出来跑一遍。

第八部分:进阶优化 —— 50万篇的哲学思考

做了这么多代码,我们来聊聊这背后的工程哲学。

  1. 管道化思维: 不要试图在 PHP 里直接调用 YouTube API。PHP 负责数据库,n8n 负责分发。解耦,是稳定性的基石。
  2. 幂等性: 无论是 PHP 查询未处理数据,还是 n8n 上传视频,都要保证“重跑不犯错”。比如 ID 唯一性约束,或者状态标记机制。
  3. 渐进式发布: 50万篇如果一天发完,流量会崩掉。利用 n8n 的 Schedule Trigger,设定每天只发 100 篇。这 100 篇我们可以通过 Filter 节点挑选出“高权重”或“最新”的文章。这叫“精选集”,比“垃圾堆”效果更好。

总结

你看,从 50万 篇死气沉沉的文章,到一个个鲜活跳动的视频,我们只用了:

  1. PHP 做个“分拣员”(筛选数据,打包 JSON)。
  2. n8n 做个“导演”(编排流程,处理数据)。
  3. YouTube/TikTok API 做个“舞台”(展示内容)。

这中间没有复杂的微服务架构,没有 Kubernetes 的过度设计,只有最纯粹的数据流转。这就是自动化最迷人的地方——让机器去干那些枯燥的搬运工作,让你有时间去喝咖啡,或者去思考下一个段子从哪来。

现在,去给你的 PHP 脚本加上 LIMIT,去 n8n 里把 Webhook 接通。当你看到你的服务器日志里开始疯狂打印 Executing Node...,当你看到 YouTube 频道里开始自动长出视频,你会发现,这比写任何复杂的算法都要爽。

好了,今天的讲座到此结束。如果代码跑不通,别怪我,怪 n8n 的文档太晦涩,或者怪 TikTok 的 API 没写好。Debug 的时候记得多喝点水,那是程序员的续命水。

祝你好运,让你的 50万 篇文章在 TikTok 上疯传吧!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注