返回首页

Pinterest 网站自动图钉设置

为静态网站设置自动 Pinterest 图钉的指南。域名验证、文章 meta 标签、从 HTML 生成 RSS 的 Node.js 脚本。连接 Pinterest Business 获取流量。

Pinterest 自动图钉:Node.js 上的 RSS 生成器
Advertisement 728x90

通过RSS和元标签为静态网站自动化生成Pinterest图钉

要将您的网站与Pinterest集成,首先需要验证您的域名。在Pinterest商业中心,选择元标签验证方法,并将其插入到主页的<head>中:

<meta name="p:domain_verify" content="12ac6ff1eaa70a3386sg439fda58bbb6"/>

这允许Pinterest索引带有富图钉的页面。接下来,为每篇文章的<head>添加元标签:

<meta name="is_article" content="true">
<meta name="pinterest_description" content="图钉描述,150–200个字符">
<meta name="pinterest_image" content="https://example.com/image.webp">
<meta name="article_published_at" content="2026-04-03T12:00:00+03:00">

图片应为竖版(1000×1500像素),通过HTTPS提供,且小于2 MB。如果没有pinterest_image,Pinterest将使用页面上的第一个<img>,这通常效果不佳。

Google AdInline article slot

使用Node.js脚本生成RSS源

Pinterest通过解析RSS来自动创建图钉。使用脚本来扫描HTML文件、提取元数据并生成rss.xml

scripts文件夹中创建generate-rss.js

import fs from 'node:fs/promises';
import path from 'node:path';
import * as cheerio from 'cheerio';

// ================== 设置(请自定义这些) ==================

const BASE_URL = 'https://YOUR_SITE.com';
const ROOT_DIR = path.resolve(process.cwd(), 'dist');
const OUTPUT_RSS_PATH = path.join(ROOT_DIR, 'rss.xml');
const CHANNEL_TITLE = '您的博客名称';
const CHANNEL_DESCRIPTION = '描述:关于开发、SEO、设计的文章';

// ================== 请勿修改以下内容 ==================

function escapeXml(value = '') {
  return value
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}

function getMimeTypeByExt(urlOrPath = '') {
  const ext = urlOrPath.split('.').pop()?.toLowerCase();
  switch (ext) {
    case 'jpg': case 'jpeg': return 'image/jpeg';
    case 'png': return 'image/png';
    case 'webp': return 'image/webp';
    case 'gif': return 'image/gif';
    default: return 'image/*';
  }
}

function buildArticleUrl(filePath) {
  const relativePath = path.relative(ROOT_DIR, filePath).replace(/\\/g, '/');
  return `${BASE_URL}/${relativePath}`;
}

function buildImageUrl(src) {
  if (!src) return '';
  if (/^https?:\/\//i.test(src)) return src;
  if (src.startsWith('/')) return `${BASE_URL}${src}`;
  return `${BASE_URL}/${src}`;
}

async function collectHtmlFiles(dir) {
  const entries = await fs.readdir(dir, { withFileTypes: true });
  const files = [];
  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name);
    if (entry.isDirectory()) {
      const nested = await collectHtmlFiles(fullPath);
      files.push(...nested);
    } else if (entry.isFile() && entry.name.endsWith('.html')) {
      files.push(fullPath);
    }
  }
  return files;
}

async function parseArticle(filePath) {
  const content = await fs.readFile(filePath, 'utf8');
  const $ = cheerio.load(content);

  const isArticle = $('meta[name="is_article"]').length > 0;
  if (!isArticle) return null;

  const title = $('h1').first().text().trim() || '无标题';
  const pinterestDescription = $('meta[name="pinterest_description"]').attr('content')?.trim() || '';
  const pinterestImg = $('meta[name="pinterest_image"]').attr('content');
  let firstImgSrc = $('img').first().attr('src') || '';
  if (firstImgSrc.endsWith('.svg')) firstImgSrc = '';
  const imageUrl = buildImageUrl(pinterestImg || firstImgSrc);

  let pubDate;
  const articleDateMeta = $('meta[name="article_published_at"]').attr('content');
  if (articleDateMeta) {
    const parsed = new Date(articleDateMeta);
    if (!isNaN(parsed.getTime())) pubDate = parsed;
  }
  if (!pubDate) {
    const stat = await fs.stat(filePath);
    pubDate = stat.mtime;
  }

  return { title, pinterestDescription, url: buildArticleUrl(filePath), imageUrl, pubDate };
}

function buildRssXml(items) {
  const itemsXml = items.map(item => {
    const enclosure = item.imageUrl ? `\n        <enclosure url="${escapeXml(item.imageUrl)}" type="${getMimeTypeByExt(item.imageUrl)}" />` : '';
    return `\n    <item>\n        <title>${escapeXml(item.title)}</title>\n        <link>${escapeXml(item.url)}</link>\n        <description><![CDATA[${item.pinterestDescription}]]></description>\n        <pubDate>${item.pubDate.toUTCString()}</pubDate>${enclosure}\n    </item>`;
  }).join('\n');

  return `<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0">\n<channel>\n    <title>${escapeXml(CHANNEL_TITLE)}</title>\n    <link>${escapeXml(BASE_URL)}</link>\n    <description>${escapeXml(CHANNEL_DESCRIPTION)}</description>${itemsXml}\n</channel>\n</rss>`;
}

async function main() {
  console.log('🔍 在以下目录搜索HTML:', ROOT_DIR);
  const htmlFiles = await collectHtmlFiles(ROOT_DIR);
  console.log(`📄 找到的HTML文件:${htmlFiles.length}`);

  const articles = [];
  for (const filePath of htmlFiles) {
    const article = await parseArticle(filePath);
    if (article) articles.push(article);
  }
  console.log(`📰 带有is_article的文章:${articles.length}`);

  if (!articles.length) {
    console.warn('⚠️ 未找到文章。未创建RSS。');
    return;
  }

  articles.sort((a, b) => b.pubDate - a.pubDate);
  const rssXml = buildRssXml(articles);
  await fs.writeFile(OUTPUT_RSS_PATH, rssXml, 'utf8');
  console.log(`✅ RSS已保存:${OUTPUT_RSS_PATH}`);
}

main().catch(err => {
  console.error('❌ 错误:', err);
  process.exit(1);
});

运行步骤:

Google AdInline article slot
  • npm install cheerio
  • 配置BASE_URLROOT_DIR和频道详情。
  • node generate-rss.js

该脚本递归扫描HTML,使用Cheerio解析,转义XML,根据扩展名确定MIME类型,并构建绝对URL。按pubDate排序。

将RSS连接到Pinterest并实现自动化

在Pinterest中:“创建” → “富图钉” → “RSS源” → 粘贴https://your-site.com/rss.xml。图钉将在6–24小时内生成。

流程:

Google AdInline article slot
  • 添加带有元标签的文章。
  • 运行node generate-rss.js
  • Pinterest解析RSS并根据<title><description><enclosure>创建图钉。

要实现完全自动化,可集成到CI/CD(如GitHub Actions)或cron任务中:0 0 * cd /path/to/project && node scripts/generate-rss.js

此方法的优势:

  • 适用于静态网站(Hugo、Eleventy、纯HTML)。
  • 无需CMS或插件。
  • 可扩展到数千篇文章。
  • Pinterest会缓存RSS,因此无需实时更新。

关键要点

  • 使用p:domain_verify元标签验证域名以进行索引。
  • 使用pinterest_image控制图钉视觉效果。
  • 脚本处理回退到文件mtime和第一个<img>
  • RSS包含带有MIME类型的<enclosure>用于图片。
  • 通过cron或CI实现生产环境自动化。

— Editorial Team

Advertisement 728x90

继续阅读