网页提取的进一步优化
本文最后更新于70 天前,其中的信息可能已经过时,如有错误请发送邮件到184874483@qq.com

重新设计工作流程:从获取元数据到数据对比

直接从WordPress获取的元数据不能直接用于对比,需要先与数据库中的记录进行关联。重新设计这个关键环节。

重新设计的工作流程

[获取WordPress元数据] → [获取数据库记录] → [数据关联与对比] → [变更检测] → [分支处理]

具体实现步骤

步骤1:获取WordPress文章元数据

HTTP Request 节点配置

// 获取WordPress文章列表(仅元数据)
- URL: https://你的博客.com/wp-json/wp/v2/posts
- 方法: GET
- 参数:
  ?per_page=100
  &orderby=modified
  &order=desc
  &_fields=id,slug,modified,title

如果出现问题:明明节点执行成功,但是没有任何返回结果,跟据get请求,直接将请求参数合并到url中:http://www.preluna.xyz/wp-json/wp/v2/posts?per_page=10&orderby=modified&order=desc&_fields=id,title,slug,modified&_**cacheBuster={{**Date.now()**}}*

输出数据结构

[
  {
    "id": 123,                    // → wp_post_id
    "slug": "my-first-post",      // → slug
    "modified": "2024-01-15T10:30:00", // → last_modified
    "title": {"rendered": "我的第一篇文章"} // → title
  },
  // ... 更多文章
]

附:参数查询的设计

这里的参数查询,应该与自己的数据库相关,没必要查询一些毫无意义的参数

数据库初始化

-- 优化后的文章表
CREATE TABLE IF NOT EXISTS articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    wp_post_id INT UNIQUE NOT NULL,           -- WordPress文章ID
    slug VARCHAR(255) NOT NULL,               -- 文章别名
    last_modified TIMESTAMP NOT NULL,         -- 最后修改时间
    title TEXT,                               -- 文章标题(用于显示)
    
    -- 索引优化
    INDEX idx_wp_post_id (wp_post_id),
    INDEX idx_slug (slug),
    INDEX idx_last_modified (last_modified)
);

执行后创建的表,只有1个表 – articles 表

主要存储字段:

  1. id – 主键标识
  2. wp_post_id – WordPress文章关联ID
  3. slug – 文章别名(用于URL)
  4. last_modified – 最后修改时间
  5. title – 文章标题

步骤2:获取数据库现有记录

MySQL 节点配置

-- 只获取必要的对比字段
SELECT 
    id,
    wp_post_id,
    slug, 
    last_modified
FROM articles 
WHERE is_deleted = 0;

输出数据结构

[
  {
    "id": 1,
    "wp_post_id": 123,
    "slug": "my-first-post", 
    "last_modified": "2024-01-14T15:20:00"
  },
  // ... 更多记录
]

步骤3:快速数据对比(简化版)

Code 节点 – 精简对比逻辑

// 获取两个数据源
const wpArticles = $input[0].json; // WordPress数据
const dbArticles = $input[1].json; // 数据库数据

// 创建数据库文章的快速查找映射
const dbMap = new Map();
dbArticles.forEach(dbArticle => {
  dbMap.set(dbArticle.wp_post_id, dbArticle);
});

// 执行快速对比
const changes = {
  to_process: [], // 需要处理的新增和更新文章
  to_delete: []   // 需要删除的文章
};

// 处理WordPress中的文章
wpArticles.forEach(wpArticle => {
  const wpId = wpArticle.id;
  const dbArticle = dbMap.get(wpId);
  
  if (!dbArticle) {
    // 新增文章
    changes.to_process.push({
      wp_post_id: wpId,
      slug: wpArticle.slug,
      last_modified: wpArticle.modified,
      title: wpArticle.title.rendered,
      change_type: 'new'
    });
  } else {
    const wpModified = new Date(wpArticle.modified);
    const dbModified = new Date(dbArticle.last_modified);
    
    if (wpModified > dbModified) {
      // 更新文章
      changes.to_process.push({
        wp_post_id: wpId,
        slug: wpArticle.slug,
        last_modified: wpArticle.modified,
        title: wpArticle.title.rendered,
        change_type: 'updated',
        db_id: dbArticle.id
      });
    }
    // 移除已处理的记录
    dbMap.delete(wpId);
  }
});

// 剩余在dbMap中的就是需要删除的文章
dbMap.forEach((dbArticle, wpId) => {
  changes.to_delete.push({
    wp_post_id: wpId,
    slug: dbArticle.slug,
    db_id: dbArticle.id,
    change_type: 'deleted'
  });
});

// 添加简单统计
changes.stats = {
  total_wordpress: wpArticles.length,
  total_database: dbArticles.length,
  to_process: changes.to_process.length,
  to_delete: changes.to_delete.length
};

return [changes];

 数据准备阶段

// 创建数据库文章的快速查找映射
const dbMap = new Map();
dbArticles.forEach(dbArticle => {
  dbMap.set(dbArticle.wp_post_id, dbArticle);
});

目的:将数据库记录转换为以 wp_post_id 为键的 Map,实现 O(1) 时间复杂度的查找

核心对比逻辑

新增文章检测:

if (!dbArticle) {
  // WordPress有但数据库没有 → 新增
  changes.to_process.push({
    change_type: 'new'
  });
}

更新文章检测:

if (wpModified > dbModified) {
  // WordPress修改时间更晚 → 更新
  changes.to_process.push({
    change_type: 'updated'
  });
}

删除文章检测:

// 处理完WordPress文章后,dbMap中剩余的记录
dbMap.forEach((dbArticle, wpId) => {
  changes.to_delete.push({
    change_type: 'deleted'
  });
});

通过 dbMap.delete(wpId) 逐步移除已存在的记录,剩下的就是需要删除的

输出数据结构

{
  to_process: [    // 需要处理的文章(新增+更新)
    {
      wp_post_id: number,    // WordPress ID
      slug: string,          // 文章别名
      last_modified: string, // 修改时间
      title: string,         // 文章标题
      change_type: 'new'|'updated',
      db_id?: number         // 仅更新时有,数据库主键ID
    }
  ],
  to_delete: [     // 需要删除的文章
    {
      wp_post_id: number,
      slug: string,
      db_id: number,         // 数据库主键ID
      change_type: 'deleted'
    }
  ],
  stats: {         // 统计信息
    total_wordpress: number,
    total_database: number,
    to_process: number,
    to_delete: number
  }
}

可简单的方法(可选)

当然以上看不懂也不要紧,如果你说n8n的输入输出结构太过于严苛也不要紧。我还有一个更加简单的方法,当然功能性和扩展性,可读性都会受到大大的减少,但是至少可以保证你整个流程能勉强的运行。

先按着图片搭建节点,并连线,然后再往里面输入具体代码,注意节点之间的输入端,这里面一个都不能错。(已经非常简化了,总不能还不会吧)

重置数据表

DROP TABLE IF EXISTS articles;
CREATE TABLE articles (
    slug VARCHAR(255) PRIMARY KEY,
    modified TIMESTAMP NOT NULL,
    INDEX idx_slug (slug),
    INDEX idx_last_modified (modified)
);

在工作流开始时验证表结构

SELECT 
    CASE 
        WHEN COUNT(*) = 2 THEN '表结构正确'
        ELSE '表结构错误,期望2个字段但找到' || COUNT(*) || '个'
    END as validation_result
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_SCHEMA = 'article_system' 
AND TABLE_NAME = 'articles'
AND COLUMN_NAME IN ('slug', 'modified');

第1次拉取数据库

SELECT slug, modified FROM articles;

获取wordpress列表

http://www.preluna.xyz/wp-json/wp/v2/posts?per_page=5&orderby=modified&order=desc&_fields=slug,modified

对比得被删除的文章

清除被删除的文章

验证删除成果

SELECT * FROM articles ORDER BY modified DESC;

合并得新增或更新的文章

插入更新的文章

验证成果

文末附加内容
暂无评论

发送评论 编辑评论


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