دليل · ١٦ دقيقة للقراءة
مراقب صفحة المنافس بالذكاء الاصطناعي مع diff وتنبيهات Slack في n8n
سير n8n مجدول يومياً يجلب صفحات تسعير وميزات منافسيك، يُجري hash مقابل snapshot الأمس في static data لـn8n، يحسب diff على مستوى الجمل، ويُرسل التغييرات المهمة فقط إلى Slack — مدعوم بـgpt-5-mini. سير متفرع كامل بمنطق IF.
بُني واستُورد مباشرة على 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 يعملان — لكن خطوة التنبيه تفشل بـ ٤٠٤. انظر الخطوة ٥ لإجراء الاستبدال.
ما الذي ستبنيه
سير n8n يومي:
- يشتغل الساعة ٩ صباحاً كل يوم
- يجلب قائمة صفحات منافسين تهتم بها (التسعير، الميزات، changelogs)
- يحسب SHA-1 hash لمحتوى كل صفحة بعد تجريدها
- يقارن مع hash السابق المخزن في workflow static data لـn8n
- إذا لم يتغير: no-op صامت (بدون تكلفة AI)
- إذا تغير: يحسب diff على مستوى الجمل (جمل جديدة، جمل محذوفة) ←
gpt-5-miniيُلخص التغيير المادي ← تنبيه Slack Block Kit
تخطَّ البناء — استورد السير
المتطلبات المسبقة
| المتطلب | التفاصيل |
|---|---|
| حساب n8n | تجربة مجانية |
| أرصدة OpenAI | ١٠٠ مجانية من n8n |
| مساحة عمل Slack | صلاحية admin لتثبيت Incoming Webhook |
| بعض روابط المنافسين | التسعير، الميزات، changelog — اختيارك |
| الوقت | حوالي ١٥ دقيقة |
الخطوة ١ — استيراد السير
أنشئ سير عمل جديد. ألصق JSON على اللوحة الفارغة. تُحمَّل ١١ عقدة بتخطيط متفرع — خط مستقيم حتى عقدة If Changed، ثم ينقسم إلى مسار "Summarize & Alert" ومسار "No Change Log".
افتح عقدة OpenAI Chat Model الفرعية وتأكد من gpt-5-mini بدرجة حرارة 0.3.
الخطوة ٢ — قائمة الصفحات التي تراقبها
انقر نقراً مزدوجاً على 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 الأسفل توازيها.
الخطوة ٣ — الجلب و diff مقابل static data
عقدة Fan Out URLs Code تُجري JSON.parse + map لإنتاج عنصر واحد لكل رابط. ثم Fetch Page تشتغل مرة لكل عنصر بالتوازي (توازي n8n التلقائي).
عقدة Diff هي النجمة
انقر نقراً مزدوجاً على Diff vs Last Snapshot. الأجزاء الرئيسية:
١. إزالة الضوضاء، 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 تقتل ٩٥٪ من الإيجابيات الكاذبة. تلك المناطق حيث تسكن معرفات بنر الكوكيز والأختام الزمنية وbuild hashes.
٢. قراءة 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') يُعيد كائناً يُحفظ عبر تشغيلات السير. القراءات مجانية، الكتابات تُحفظ تلقائياً عندما يكتمل تشغيل السير بنجاح.
٣. حساب 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);
يُقسِّم على علامات ترقيم الجمل (نقطة/تعجب/استفهام)، يُرشح الأجزاء الصغيرة (< ٣٠ حرف = روابط nav، تواريخ)، يأخذ فرق Set. محدود بـ١٢ مضافة + ١٢ محذوفة لإبقاء مطالبة AI مُحدودة.
٤. حفظ snapshot الجديد:
wfStatic.snapshots[url] = {
hash: currentHash,
text: stripped.slice(0, 20000),
capturedAt: new Date().toISOString()
};
يخزن الإصدار الحالي ليكون لتشغيل الغد شيء للـdiff ضده. محدود بـ٢٠ ألف حرف لتجنب التضخم.
٥. إرجاع كل ما يحتاجه الفرع التالي:
return [{ json: {
url,
changed: !prevHash || prevHash !== currentHash,
isFirstRun: !prevHash,
addedLines: added,
removedLines: removed
}}];
isFirstRun حاسمة — لا نريد التنبيه في التشغيل الأول (كل URL سينطلق لأن لا شيء للمقارنة ضده).
الخطوة ٤ — التفريع: التلخيص أو التخطي
انقر نقراً مزدوجاً على 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 مُثيرة للذعر.
الخطوة ٥ — التنسيق والإرسال إلى 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.
الخطوة ٦ — تشغيل جدول الإنتاج
Schedule Trigger يُطلق عند ٩ صباحاً بمجرد تبديل السير إلى Active. افتراضياً، السير الجديد غير نشط.
تفعيل السير
اضغط زر Publish أعلى يمين اللوحة، ثم بدّل السير إلى Active. Schedule Trigger يبدأ العد. n8n يتعامل مع الطابور؛ سيرك يشتغل عند ٩ صباحاً في منطقة وقتك المضبوطة في بروفايلك (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"، نبه دائماً. للصفحات الأخرى، نبه فقط عندما تتغير > ٥ جمل. يُقلل الضوضاء في صفحات تسويق المحتوى الثقيلة التي تُغير النص يومياً.
ما التالي
ازدوج مع إثراء العملاء المحتملين بالـ AI لتأهيل العملاء تلقائياً من الشركات التي تغيرت تسعيرتها، أو ملخص أخبار متعدد المصادر لدمج التغييرات التنافسية مع أخبار الصناعة في ملخص صباحي واحد.
الأسئلة الشائعة
لماذا نُجري hash للصفحة بدلاً من diff كامل في كل مرة؟
مقارنة Hash تُجيب 'هل تغير شيء؟' في O(١). إذا طابق hash الأمس، نتخطى diff واستدعاء AI — يوفر ٩٨٪ من التشغيلات. عندما يختلف hash، نحسب diff على مستوى الجمل (O(n)) ونُرسل فقط الجمل المضافة/المحذوفة إلى AI. هذا النهج ذو المرحلتين يعني التشغيلات اليومية لا تُكلف شيئاً تقريباً عندما تكون الصفحات مستقرة، ولا ندفع لـAI إلا في أيام فيها شيء للتلخيص.
أين يخزن السير snapshot السابق؟
في **static data للسير** في n8n، يُوصل إليه عبر `$getWorkflowStaticData('global')`. هذا مخزن key-value محصور بالسير، مُحفوظ عبر التشغيلات، ومجاني على كل خطط n8n. السير يكتب `{ hash, text, capturedAt }` لكل رابط. Static data ينجو من تحرير السير لكن يُمسح إذا حذفت وأعدت استيراد السير — بعد إعادة الاستيراد، التشغيل الأول يُعامل كل رابط كـ'تشغيل أول' ولا ينبه.
هل يعمل هذا لتطبيقات الصفحة الواحدة (مواقع Vercel و Next.js)؟
جزئياً. Next.js ومعظم مواقع SaaS تُجسد من الخادم التحميل الأولي مع المحتوى الحرج (العنوان الرئيسي، التسعير، الميزات) — هذا ما يلتقطه السير. المحتوى الديناميكي المُحمَّل بـJS العميل بعد hydration (CTAs مخصصة، متغيرات A/B، حالة carousel) لن يُلتقط. لالتقاط SPA كامل، استبدل عقدة Fetch Page باستدعاء لخدمة Browserless/Playwright/Puppeteer تُعيد HTML مُجسَّداً.
كيف أتجنب إيجابيات كاذبة من بنرات الكوكيز والأختام الزمنية؟
السير يُزيل كتل `<nav>` و `<header>` و `<footer>` و `<script>` قبل hash — يزيل معظم مصادر الإيجابيات الكاذبة الشائعة (أختام nav الزمنية، سنة حقوق النشر في footer، معرفات بنر الكوكيز). إذا كنت لا تزال ترى إنذارات كاذبة، أضف استبدالات regex في عقدة Diff: استبدل الأختام الزمنية ومعرفات الجلسة ورموز CSRF بـplaceholder ثابت قبل hash. مثال: `.replace(/\b\d{٤}-\d{٢}-\d{٢}T[\d:.]+Z\b/g, 'TIMESTAMP')`.
هل أستطيع مراقبة ٥٠+ صفحة منافس؟
نعم. أضف روابطك إلى مصفوفة `urls` في عقدة Competitor URLs. عقدة Fan Out تُوزعها إلى fetches متوازية، وكل منها يُجري diff مستقلاً وينبه شرطياً. عند ٥٠ رابطاً تشتغل يومياً، تستخدم ~٥٠ تنفيذ/يوم — لا يزال تحت حد 1000/يوم المجاني في n8n. لـ٥٠٠+ رابط، فكر في تقسيم إلى عدة سير مجدولة في ساعات مختلفة لتوزيع الحمل والبقاء تحت حدود معدل الناشرين الصغار.
مقالات ذات صلة
داخل وكلاء الذكاء الاصطناعي للبرمجة: كيف تتطور مسارات التطوير الذاتية
نظرة واقعية ومفصلة عن وكلاء الذكاء الاصطناعي للبرمجة — كيف تعمل، ما الذي يجعلها مختلفة عن الكوبيلوتات التقليدية، وكيف تعيد السيرورات الوكلائية تشكيل تطوير البرمجيات.
إتقان هندسة البرومبت: فن وعلم التحدث مع الذكاء الاصطناعي
غوص عميق في إتقان هندسة المطالبات — من صياغة المطالبات الفعالة إلى توسيع سير عمل الذكاء الاصطناعي بالموثوقية والأداء والدقة.
المزيد من الأدلّة
دليل · ١٥ دقيقة للقراءة
إثراء العملاء المحتملين بالـ AI ورسائل مُخصصة في n8n — ٦ عقد ونموذج واحد
ضع بريد العميل المحتمل ورابط شركته في نموذج n8n. السير يحلل الموقع، يستكشف stack التقني، يُشير لإشارات التوظيف والأسعار والامتثال، ثم يطلب من gpt-5-mini درجة ملاءمة وثلاثة أسباب وبريد بارد مُخصص. مخرجات JSON مُحققة المخطط جاهزة لـCRM.
دليل · ١٦ دقيقة للقراءة
ملخص تقني يومي متعدد المصادر مع ترتيب AI وتوصيل Slack في n8n
سير n8n يسحب Hacker News و Dev.to و GitHub Trending بالتوازي كل صباح، يُلخص كل عنصر في جملة واحدة بالذكاء الاصطناعي، ثم يُرسل رسالة Slack بصيغة Block Kit بروابط قابلة للنقر. مُشغّل بجدول، يدمج ثلاثة أشكال بيانات، ويستخدم `gpt-5-mini` عبر الأرصدة المجانية.
للوكلاء الآليين:/for-agents/llms.txt/ar/guides/n8n-competitor-monitor.md