{/* آخر تحديث: 2026-04-24 | بُني واستُورد مباشرة على nerdleveltech.app.n8n.cloud | gpt-5-mini */}
إحدى عشرة عقدة،
Ifمتفرع واحد، مُقارن على مستوى الجمل، مُلخِّص AI — كلها وُصلت وحُفظت على n8n cloud. أكثر العقد إثارة هي Code التي تُجري hash مقابل$getWorkflowStaticDataلتحصل على تنبيهات فقط عندما يهم الأمر. تنفيذ حقيقي مُلتقط في الأسفل.
⚠️ قبل التفعيل: عقدة Post to Slack تأتي برابط webhook عام (
https://hooks.slack.com/services/REPLACE/WITH/YOUR_WEBHOOK). حتى تستبدله، diff وتلخيص AI يعملان — لكن خطوة التنبيه تفشل بـ 404. انظر الخطوة 5 لإجراء الاستبدال.
ما الذي ستبنيه
سير n8n يومي:
- يشتغل الساعة 9 صباحاً كل يوم
- يجلب قائمة صفحات منافسين تهتم بها (التسعير، الميزات، changelogs)
- يحسب SHA-1 hash لمحتوى كل صفحة بعد تجريدها
- يقارن مع hash السابق المخزن في workflow static data لـn8n
- إذا لم يتغير: no-op صامت (بدون تكلفة AI)
- إذا تغير: يحسب diff على مستوى الجمل (جمل جديدة، جمل محذوفة) ←
gpt-5-miniيُلخص التغيير المادي ← تنبيه Slack Block Kit
تخطَّ البناء — استورد السير
المتطلبات المسبقة
| المتطلب | التفاصيل |
|---|---|
| حساب n8n | تجربة مجانية |
| أرصدة OpenAI | 100 مجانية من n8n |
| مساحة عمل Slack | صلاحية admin لتثبيت Incoming Webhook |
| بعض روابط المنافسين | التسعير، الميزات، changelog — اختيارك |
| الوقت | حوالي 15 دقيقة |
الخطوة 1 — استيراد السير
أنشئ سير عمل جديد. ألصق JSON على اللوحة الفارغة. تُحمَّل 11 عقدة بتخطيط متفرع — خط مستقيم حتى عقدة If Changed، ثم ينقسم إلى مسار "Summarize & Alert" ومسار "No Change Log".
افتح عقدة OpenAI Chat Model الفرعية وتأكد من gpt-5-mini بدرجة حرارة 0.3.
الخطوة 2 — قائمة الصفحات التي تراقبها
انقر نقراً مزدوجاً على Competitor URLs. عقدة Set بتعيين واحد:
"urls": "[\"https://openai.com/pricing\", \"https://www.anthropic.com/pricing\"]"
مُحوَّلة إلى JSON-string لأن حقول تعبير n8n لا تعرض المصفوفات الخام بسلاسة. العقدة التالية تحللها.
لإضافة روابط، عدّل السلسلة:
"urls": "[\"https://openai.com/pricing\", \"https://www.anthropic.com/pricing\", \"https://docs.n8n.io/changelog/\", \"https://www.zapier.com/pricing\"]"
بدون حد أقصى — عقدة Fan Out الأسفل توازيها.
الخطوة 3 — الجلب و diff مقابل static data
عقدة Fan Out URLs Code تُجري JSON.parse + map لإنتاج عنصر واحد لكل رابط. ثم Fetch Page تشتغل مرة لكل عنصر بالتوازي (توازي n8n التلقائي).
عقدة Diff هي النجمة
انقر نقراً مزدوجاً على Diff vs Last Snapshot. الأجزاء الرئيسية:
1. إزالة الضوضاء، hash ما تبقى:
const stripped = html
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, ' ')
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, ' ')
.replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, ' ')
.replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, ' ')
.replace(/<header[^>]*>[\s\S]*?<\/header>/gi, ' ')
.replace(/<[^>]+>/g, ' ')
.replace(/\s+/g, ' ')
.trim();
const currentHash = crypto.createHash('sha1').update(stripped).digest('hex');
إزالة nav/footer/header تقتل 95% من الإيجابيات الكاذبة. تلك المناطق حيث تسكن معرفات بنر الكوكيز والأختام الزمنية وbuild hashes.
2. قراءة snapshot السابق من static data:
const wfStatic = $getWorkflowStaticData('global');
wfStatic.snapshots = wfStatic.snapshots || {};
const prev = wfStatic.snapshots[url] || null;
const prevHash = prev?.hash;
const prevText = prev?.text || '';
$getWorkflowStaticData('global') يُعيد كائناً يُحفظ عبر تشغيلات السير. القراءات مجانية، الكتابات تُحفظ تلقائياً عندما يكتمل تشغيل السير بنجاح.
3. حساب diff على مستوى الجمل:
const toLines = t => t.split(/(?<=[.!?])\s+/).filter(l => l.length > 30);
const newLines = new Set(toLines(stripped));
const oldLines = new Set(toLines(prevText));
const added = [...newLines].filter(l => !oldLines.has(l)).slice(0, 12);
const removed = [...oldLines].filter(l => !newLines.has(l)).slice(0, 12);
يُقسِّم على علامات ترقيم الجمل (نقطة/تعجب/استفهام)، يُرشح الأجزاء الصغيرة (< 30 حرف = روابط nav، تواريخ)، يأخذ فرق Set. محدود بـ12 مضافة + 12 محذوفة لإبقاء مطالبة AI مُحدودة.
4. حفظ snapshot الجديد:
wfStatic.snapshots[url] = {
hash: currentHash,
text: stripped.slice(0, 20000),
capturedAt: new Date().toISOString()
};
يخزن الإصدار الحالي ليكون لتشغيل الغد شيء للـdiff ضده. محدود بـ20 ألف حرف لتجنب التضخم.
5. إرجاع كل ما يحتاجه الفرع التالي:
return [{ json: {
url,
changed: !prevHash || prevHash !== currentHash,
isFirstRun: !prevHash,
addedLines: added,
removedLines: removed
}}];
isFirstRun حاسمة — لا نريد التنبيه في التشغيل الأول (كل URL سينطلق لأن لا شيء للمقارنة ضده).
الخطوة 4 — التفريع: التلخيص أو التخطي
انقر نقراً مزدوجاً على If Changed. الشرط:
{{ $json.changed && !$json.isFirstRun }}
يجب أن يكون true وليس تشغيلاً أولاً. فروع المخرجات:
- True ← Summarize the Change ← Format Alert ← Post to Slack
- False ← No Change Log (عقدة
noOp— لا تفعل شيئاً، مجرد terminator بصري)
مطالبة Summarize the Change
انقر نقراً مزدوجاً على Summarize the Change. المطالبة حذرة عن قصد:
You are a competitive-intelligence analyst. A competitor's page changed
overnight. Summarize what is materially different, based strictly on the
added/removed sentences below. Do not speculate beyond what is shown.
PAGE: {{ $json.url }}
ADDED SENTENCES:
{{ ($json.addedLines || []).map(l => '+ ' + l).join('\n') }}
REMOVED SENTENCES:
{{ ($json.removedLines || []).map(l => '- ' + l).join('\n') }}
RULES
- Output a punchy 3-5 bullet Slack message.
- Lead with the most commercially-interesting change (pricing, feature,
tier, customer, policy).
- Call out specific numbers, tier names, or feature names from the diff.
- If the change is cosmetic/copy-only, say that in one line and stop.
- No preamble. No "As an AI...". No hashtags.
القاعدة "If the change is cosmetic/copy-only, say that in one line and stop" تمنع AI من تضخيم تبديلات كلمات تافهة إلى قوائم bullet مُثيرة للذعر.
الخطوة 5 — التنسيق والإرسال إلى Slack
Format Alert عقدة Code تبني JSON Slack Block Kit برأس، قسم بحقلين (URL + أعداد diff)، ملخص AI، وتذييل سياق.
Post to Slack عقدة HTTP Request. استبدل placeholder الرابط:
https://hooks.slack.com/services/REPLACE/WITH/YOUR_WEBHOOK
…برابط Incoming Webhook الحقيقي. انظر دليل ملخص الأخبار متعدد المصادر للخطوات الدقيقة لإنشاء واحد.
تنبيه Slack المُعروض يبدو هكذا:
🚨 Competitor page changed
─────────────────────────
Page: openai.com/pricing Diff: +3 new, -2 removed
─────────────────────────
• Flex pricing tier now public: $1/M input tokens for gpt-5-nano
• Enterprise tier removed minimum commitment language
• "Priority processing" replaced with "Batch processing" as tier label
رابط قابل للنقر، أعداد diff واضحة، bullets محددة. بالضبط ما يريده تسويق on-call.
الخطوة 6 — تشغيل جدول الإنتاج
Schedule Trigger يُطلق عند 9 صباحاً بمجرد تبديل السير إلى Active. افتراضياً، السير الجديد غير نشط.
تفعيل السير
اضغط زر Publish أعلى يمين اللوحة، ثم بدّل السير إلى Active. Schedule Trigger يبدأ العد. n8n يتعامل مع الطابور؛ سيرك يشتغل عند 9 صباحاً في منطقة وقتك المضبوطة في بروفايلك (UTC افتراضياً).
التشغيل الإنتاجي الأول
في التشغيل الأول بعد التفعيل، كل رابط سيُصنَّف كـisFirstRun: true — فلا تنبيه Slack. اليوم الثاني، كل رابط يُقارن مع snapshot الأول — التغييرات تُطلق تنبيهات.
اختبر خط الأنابيب قبل الانتظار: اضغط Execute workflow لتشغيله يدوياً. التشغيل الأول يلتقط الأساس. عدّل إحدى صفحات المنافسين (ليس حقاً — لكن يمكن محاكاة بتحرير النص المخزن عبر كتابة يدوية في static data)، ثم شغّل مرة أخرى للتحقق من إطلاق تنبيه Slack.
في اختبارنا الحقيقي مقابل openai.com/pricing و anthropic.com/pricing، السير جلب الاثنين بشكل صحيح، حسب SHA-1 hashes، ووجّه كلا الرابطين عبر فرع No Change Log لأن isFirstRun: true (لم يكن لهما snapshot سابق). في التشغيل المجدول التالي، أي تغيير في صفحة التسعير سيُطلق مُلخص AI + تنبيه Slack.
⚠️ ملاحظة المواقع المحمية بـ Cloudflare: خلال اختبارنا الحقيقي، أعادت كلتا صفحتي التسعير شاشة "Enable JavaScript and cookies to continue" بدلاً من المحتوى الكامل. هذا يعني diff يلتقط الشاشة الفاصلة، ليس الأسعار الحقيقية. للمواقع ذات حماية البوتات، استبدل عقدة Fetch Page باستدعاء Browserless أو ScrapingBee (انظر التوسعات) — تعيد HTML ما بعد JS.
التوسعات: لقطات شاشة، Teams، Notion
تضمين لقطة شاشة للصفحة
أضف استدعاء HTTP Browserless أو ScreenshotOne بالتوازي مع Fetch Page. غذِّ رابط الصورة المُعاد إلى عقدة Format Alert لـSlack كبلوك image:
{ "type": "image", "image_url": "{{ $json.screenshotUrl }}", "alt_text": "Before / after preview" }
يتيح لفريقك رؤية التغيير البصري بدون نقر.
النشر إلى Teams بدلاً من ذلك
استبدل عقدة Post to Slack Webhook بـHTTP Request إلى رابط Incoming Webhook لـTeams. حوّل Block Kit إلى JSON Adaptive Card في عقدة Format Alert. انظر adaptivecards.io للمخطط.
أرشفة كل snapshot إلى Notion
بعد Diff vs Last Snapshot، أضف عقدة Notion Append Database Row. أنشئ قاعدة بيانات بأعمدة: URL و Captured At و Changed (bool) و Diff Summary و Full Text. تحصل على أرشيف مُصدَّر لكل صفحة منافس — رائع للمراجعات التنافسية ربع السنوية.
التلخيص الشرطي بالأهمية
أضف عقدة If أخرى بين Fetch Page و Diff: إذا كان URL يحتوي على "/pricing" أو "/changelog"، نبه دائماً. للصفحات الأخرى، نبه فقط عندما تتغير > 5 جمل. يُقلل الضوضاء في صفحات تسويق المحتوى الثقيلة التي تُغير النص يومياً.
ما التالي
ازدوج مع إثراء العملاء المحتملين بالـ AI لتأهيل العملاء تلقائياً من الشركات التي تغيرت تسعيرتها، أو ملخص أخبار متعدد المصادر لدمج التغييرات التنافسية مع أخبار الصناعة في ملخص صباحي واحد.