📘 بناء أداة تلخيص تلقائي للمقالات (RSS → Python → OpenAI → Notion)
💡 الفكرة
سننشئ أداة تُراقب أي RSS، تجمع الروابط الجديدة، تستخرج نص المقال، تُلخّصه باستخدام واجهة OpenAI، ثم تحفظ الملخّص تلقائيًا في قاعدة بيانات Notion. يمكنك تشغيلها يدويًا أو عبر جدولة/Zap.
🧰 المتطلبات
- حساب OpenAI ومفتاح API فعّال.
- مساحة عمل Notion وقاعدة بيانات (Database) لحفظ الملخصات.
- Python 3.10+ على جهازك.
- رابط RSS لمصدر الأخبار/المدوّنة.
- (اختياري) حساب Zapier لتشغيل الكود عند ورود عنصر RSS جديد.
🔧 الخطوة 1: فهم RSS واختيار المصدر
RSS صيغة معيارية لبث المحتوى المُحدّث (عناوين/ملخص/رابط). ستجد رابط RSS في كثير من المواقع أو عبر أيقونة RSS البرتقالية. سنستخدم الرابط كمدخل للأداة.
🗂️ الخطوة 2: تجهيز قاعدة بيانات في Notion
- أنشئ Database في Notion بعنوان مثل: AI Summaries.
- أضِف الخصائص التالية:
- Title (عنوان الصفحة) — نوعه Title.
- URL — نوعه URL.
- Source — نص قصير.
- Summary — نص طويل.
- Published — تاريخ/وقت (اختياري).
- أنشئ تكامل Integration من Notion Developers، وامنحه صلاحية الوصول لقاعدة البيانات، واحتفظ بـ
NOTION_TOKENوDATABASE_ID. راجع مرجع الإنشاء عبر API إذا احتجت ضبطًا أدق.
🔐 الخطوة 3: حفظ المفاتيح كمتغيرات بيئية
# macOS/Linux
export OPENAI_API_KEY="ضع_المفتاح_هنا"
export NOTION_TOKEN="ضع_رمز_نوتشن"
export NOTION_DATABASE_ID="ضع_معرّف_القاعدة"
📦 الخطوة 4: تثبيت الحزم
pip install feedparser trafilatura requests python-dotenvfeedparser لقراءة RSS، وtrafilatura لاستخراج نص المقال من HTML، وrequests لإرسال الطلبات إلى Notion.
🤖 الخطوة 5: كود Python الكامل
ينفّذ: قراءة RSS → تنزيل نص المقال → تلخيص عبر OpenAI → إنشاء صفحة في Notion.
import os, time, feedparser, requests
from datetime import datetime
import trafilatura
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
NOTION_TOKEN = os.environ["NOTION_TOKEN"]
NOTION_DB = os.environ["NOTION_DATABASE_ID"]
RSS_URL = "https://example.com/feed" # استبدلها بخلاصة RSS الخاصة بك
# 1) قراءة RSS
feed = feedparser.parse(RSS_URL)
items = feed.entries[:5] # جرّب على آخر 5 عناصر
def fetch_article_text(url: str) -> str:
downloaded = trafilatura.fetch_url(url, timeout=20)
return trafilatura.extract(downloaded) or ""
def summarize(text: str, title: str) -> str:
# نستخدم واجهة Responses/Chat في OpenAI
import json, urllib.request
endpoint = "https://api.openai.com/v1/chat/completions"
payload = {
"model": "gpt-4.1-mini",
"messages": [
{"role": "system", "content": "أنت مساعد يلخص نصوصًا عربية بدقة وبشكل موجز."},
{"role": "user", "content": f"لخّص المقال التالي في 6 نقاط واضحة مع إبراز الفكرة الأساسية، واحتفِظ بالأسماء الصحيحة والعناوين:\nالعنوان: {title}\nالنص:\n{text[:12000]}"} # حد للحجم
],
"temperature": 0.2
}
req = urllib.request.Request(endpoint,
data=json.dumps(payload).encode("utf-8"),
headers={"Authorization": f"Bearer {OPENAI_API_KEY}",
"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=60) as resp:
data = json.loads(resp.read().decode("utf-8"))
return data["choices"][0]["message"]["content"].strip()
def create_notion_page(title: str, url: str, source: str, summary: str, published_iso: str = None):
notion_endpoint = "https://api.notion.com/v1/pages"
headers = {
"Authorization": f"Bearer {NOTION_TOKEN}",
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
}
body = {
"parent": {"database_id": NOTION_DB},
"properties": {
"Title": {"title": [{"text": {"content": title}}]},
"URL": {"url": url},
"Source": {"rich_text": [{"text": {"content": source}}]},
},
"children": [
{"object":"block","type":"heading_2","heading_2":{"rich_text":[{"type":"text","text":{"content":"الملخص"}}]}},
{"object":"block","type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content": summary}}]}}
]
}
if published_iso:
body["properties"]["Published"] = {"date": {"start": published_iso}}
resp = requests.post(notion_endpoint, headers=headers, json=body, timeout=60)
resp.raise_for_status()
return resp.json()
for e in items:
title = e.get("title", "بدون عنوان")
link = e.get("link", "")
published = None
if e.get("published_parsed"):
published = datetime(*e.published_parsed[:6]).isoformat()
article_text = fetch_article_text(link)
if not article_text:
print("لم أستطع استخراج نص:", link)
continue
summary = summarize(article_text, title)
create_notion_page(title, link, feed.feed.get("title","RSS Source"), summary, published)
print("أُضيف إلى Notion:", title)
time.sleep(2) # فاصل بسيط لاحترام المعدلات
🧪 الخطوة 6: الاختبار
- بدّل
RSS_URLبرابط خلاصة حقيقي (مثلاً خلاصة مدوّنة تقنية). - شغّل السكربت:
python app.py. - افتح قاعدة بيانات Notion وتحقق من ظهور الصفحات الجديدة بداخلها.
⏱️ خطوة اختيارية: تشغيل تلقائي عبر Zapier
- أنشئ Zap بزناد RSS by Zapier لاكتشاف العناصر الجديدة.
- أضِف خطوة Webhooks by Zapier (POST) لاستدعاء سكربت مستضاف لديك (أو Cloud Function) وتمرير بيانات المقال كـ JSON.
- يمكنك بدلاً من ذلك استدعاء Notion مباشرة من Zap باستخدام خطوة Notion: Create Page وتمرير ملخص جاهز إذا جعلت التلخيص يتم داخل Zap عبر واجهة OpenAI.
🔒 ملاحظات أمان وامتثال
- خزّن مفاتيح API كمتغيرات بيئية أو أسرار على الخادم—لا تُضمّنها داخل المستودع.
- راجِع حدود المعدلات (Rate Limits) لواجهة OpenAI قبل تشغيل دفعات كبيرة.
- لو استخدمت Zapier، احرص على تدوير الرموز السرّية دوريًا والاطلاع على تحديثات الأمان.
🚀 أفكار للتطوير
- إضافة وسم الموضوع (Topic Tagging) تلقائيًا عبر نموذج تصنيف.
- إرسال الملخص كبريد أسبوعي.
- تجميع أكثر من مصدر RSS مع إزالة التكرار.
📚 المصادر
- OpenAI API – مرجع واجهة الدردشة
- OpenAI – أمثلة لصياغة الطلبات
- Notion API – إنشاء صفحة
- Notion API – التعامل مع محتوى الصفحات
- Trafilatura – استخراج نصوص صفحات الويب
- Trafilatura – دليل الاستخدام مع بايثون
- Zapier – البدء مع Webhooks
- Zapier – تكاملات Webhooks
- Microsoft Docs – تعريف وموصل RSS
💬 هل لديك سؤال عن هذا الدرس؟ اتركه في التعليقات وسنساعدك خطوة بخطوة.