
متعقب مفتوح المصدر لأسطول الظل في بحر البلطيق. أكثر من 1200 سفينة، نظام AIS المباشر، تنبيهات القرب من الكابلات. لا سحابة، لا اشتراك، يعمل محلياً.
مراقبة الأسطول الظل في بحر البلطيق عبر بيانات AIS الحية. يراقب أكثر من 1200 سفينة من كتالوج العقوبات والحرب الأوكراني GUR مقابل تغذية WebSocket الخاصة بـ AISStream، ويعرض المواقع على خريطة محدثة ذاتيًا، ويُنبّه عند الاقتراب من الكابلات تحت البحر، ويكشف أنماط الشحن بين روسيا والغرب.
مجاني، مفتوح المصدر، يعمل محليًا. لا سحابة، لا اشتراك سوى مفتاح API مجاني من AISStream.
جزء من سلسلة أدوات الاستخبارات السيادية Former Lab.
متعقب الأسطول الظل الخفيف مبني ومُصان بواسطة فريق Former Lab — حوسبة سيادية، بناء أدوات مفتوحة تراعي الخصوصية على أجهزة قديمة دون دعم من رأس المال الاستثماري.
إذا كانت هذه الأداة مفيدة لك، ففكّر في دعمنا على Patreon. تتوفر طبقة مجانية، مع نسخة تجريبية لمدة 7 أيام على الطبقات المدفوعة. ادعم أوكرانيا دائمًا!
git clone https://github.com/FormerLab/shadow-fleet-tracker-light.git
cd shadow-fleet-tracker-light
pip install -r requirements.txt
export AISSTREAM_API_KEY=your_key_here # مجاني على aisstream.io
python shadow_tracker.py &
uvicorn webserver:app --host 0.0.0.0 --port 8000
افتح http://localhost:8000 — الخريطة على /map.
مستخدمو Windows: راجع قسم الإعداد لصياغة متغيرات البيئة في PowerShell/cmd.
يمكن لمستخدمي Linux / macOS استخدام start.sh. يمكن لمستخدمي Windows استخدام start.bat أو start.ps1 — كلاهما يفتح المتعقب ولوحة القيادة في نوافذ منفصلة ويشغّل المتصفح تلقائيًا.
Vessels1.db)filtered_cables.kml)خريطة أساسية CartoDB داكنة مع مسارات الكابلات متراكبة باللون الأخضر. علامات السفن تُحدّث كل 3 دقائق مع عدّاد تنازلي حي للتحديث التالي — تُعاد تحميل الصفحة تلقائيًا. تظهر النوافذ المنبثقة MMSI، IMO، العلم، السرعة، الاتجاه، الوجهة، وروابط عميقة إلى MarineTraffic وVesselFinder وWar&Sanctions. حالة عقوبات OpenSanctions تُظهر إذا تم تكوين مفتاح API.
أسماء السفن المعروفة من Vessels1.db تظهر فورًا عند أول ظهور دون انتظار رسالة AIS ثابتة.
عند بدء التشغيل، تُملأ الخريطة مسبقًا من آخر 24 ساعة من سجل المواقع. السفن التي لم تُرَ بعد في الجلسة الحالية تظهر كعلامات رمادية مع تسمية "شوهدت آخر مرة منذ X ساعات" — تتحول إلى اللون الحي عند وصول نقاط جديدة.
shadow_tracker.py العملية الرئيسية — مستهلك WS، معالج الخريطة، كتابات DB
loitering_module.py كشف التباطؤ وتعليق الخريطة
transshipment_module.py كشف زيارات الموانئ ووضع علامات الشحن بين روسيا والغرب
webserver.py لوحة قيادة FastAPI
gur_scrape.py أداة مسح لمرة واحدة — بناء تعيين IMO→GUR-ID + كتالوج كامل للسفن
check.py فحوصات أولية — إصدار Python، التبعيات، مفتاح API، الشبكة
start.sh مُشغّل لنظام Linux / macOS
start.bat مُشغّل لنظام Windows (Command Prompt)
start.ps1 مُشغّل لنظام Windows (PowerShell)
requirements.txt التبعيات
Vessels1.db قائمة المراقبة — أكثر من 1200 سفينة (MMSI + IMO + اسم حيث عُرف)
vessel_data_log.db سجل المواقع — زمن التشغيل، إلحاق فقط
vessel_static.db ذاكرة تخزين مؤقت لبيانات AIS الثابتة (الاسم، الوجهة، تاريخ العلم)
transshipment.db سجل زيارات الموانئ وأحداث الشحن
loitering_events.db أحداث التباطؤ
filtered_cables.kml هندسة الكابلات تحت البحر في بحر البلطيق
cables.kml مجموعة بيانات الكابلات الكاملة (مصدر ما قبل التصفية)
gur_mapping.json تعيين IMO→GUR-ID (يُنتج بواسطة gur_scrape.py، اختياري)
gur_vessels_full.json كتالوج GUR الكامل — GUR-ID→{imo, mmsi, name, flag} (يُنتج بواسطة gur_scrape.py)
Vessels1.db هي القائمة الأساسية للسفن المُتتبعة. أكثر من 1200 إدخال مأخوذ من كتالوج العقوبات والحرب الأوكراني GUR، تغطي ناقلات وسفن شحن تم تحديدها كجزء من الأسطول الظل الروسي أو متورطة في أنشطة هجينة في بحر البلطيق.
تتضمن القائمة سفن تم الاستيلاء عليها أو اعتراضها مؤخرًا من قبل سلطات البلطيق:
يتم تصحيح MMSIs مقابل بيانات AIS الحالية — سفن الأسطول الظل تغير أعلامها بشكل متكرر. يوثق ملف update_vessels_2026_03.sql جميع التغييرات مع المصادر.
قائمة المراقبة مفتوحة عن قصد. يمكنك إضافة سفن مباشرة إلى Vessels1.db أثناء تشغيل المتعقب — سيتم التقاطها في غضون 5 دقائق دون إعادة تشغيل.
Linux / macOS:
sqlite3 Vessels1.db "INSERT OR IGNORE INTO vessels (mmsi, imo, name) VALUES ('123456789', '9999999', 'VESSEL NAME');"
Windows (بدون الحاجة لواجهة sqlite3 CLI):
import sqlite3
conn = sqlite3.connect("Vessels1.db")
conn.execute("INSERT OR IGNORE INTO vessels (mmsi, imo, name) VALUES ('123456789', '9999999', 'VESSEL NAME')")
conn.commit()
conn.close()
Vessels1.db — قائمة المراقبة
vessels(mmsi TEXT PK, imo TEXT, name TEXT, destination TEXT)
vessel_data_log.db — سجل المواقع
vessel_data_log(timestamp, mmsi, name, imo, destination, speed, heading, latitude, longitude, cable_alert)
إلحاق فقط. يُكتب في كل دورة عرض خريطة.
vessel_static.db — ذاكرة تخزين مؤقت لبيانات AIS الثابتة
vessel_static(mmsi TEXT PK, name TEXT, imo TEXT, destination TEXT, flag TEXT)
flag_history(id, mmsi, flag, timestamp)
يُملأ من رسائل ShipStaticData الحية. يأخذ الأولوية على أسماء Vessels1.db بمجرد استلامه. يسجل flag_history كل تغيير علم مع طابع زمني — يتم تسجيل وتغيير العلم وعرضه في صفحة السفينة الفردية.
loitering_events.db — سجل التباطؤ (يُنشأ أثناء التشغيل)
loitering_events(id, mmsi, timestamp, latitude, longitude, near_cable)
transshipment.db — سجل زيارات الموانئ والشحن (يُنشأ أثناء التشغيل)
port_calls(id, mmsi, name, port, port_type, entry_ts, exit_ts, min_speed)
transshipment_events(id, mmsi, name, direction, from_port, from_exit_ts,
to_port, to_entry_ts, days_between, detected_ts)
requirements.txtأسهل طريقة لتشغيل المتعقب. يقوم كل نص بتثبيت التبعيات، تشغيل الفحوصات الأولية، وتشغيل العمليتين.
Linux / macOS:
chmod +x start.sh
export AISSTREAM_API_KEY=your_key_here
./start.sh
Windows (PowerShell):
$env:AISSTREAM_API_KEY = "your_key_here"
.\start.ps1
Windows (Command Prompt):
set AISSTREAM_API_KEY=your_key_here
start.bat
جميع النصوص الثلاثة تشغّل check.py أولاً — فحص أولي يتحقق من إصدار Python، التبعيات، ملفات البيانات، مفتاح API، وإمكانية الوصول إلى الشبكة، مع رسائل خطأ واضحة إذا كان هناك أي شيء ناقص.
يمكنك أيضًا تشغيل الفحص الأولي بمفرده في أي وقت:
python check.py
1. استنساخ وتثبيت التبعيات
git clone https://github.com/FormerLab/shadow-fleet-tracker-light.git
cd shadow-fleet-tracker-light
pip install -r requirements.txt
على Ubuntu 22.04+ و Debian 12+ قد تحصل على خطأ "بيئة مُدارة خارجيًا" من pip. تتعامل نصوص التشغيل مع هذا تلقائيًا عن طريق إنشاء بيئة افتراضية — فقط شغّل start.sh وسيتولى الأمر. إذا كنت تقوم بالتثبيت يدويًا، أنشئ بيئة افتراضية أولاً:
python3 -m venv .venv
source .venv/bin/activate # Linux/macOS
.venv\Scripts\activate # Windows
pip install -r requirements.txt
2. تعيين مفتاح API الخاص بـ AISStream
Linux / macOS:
export AISSTREAM_API_KEY=your_key_here
export OPENSANCTIONS_API_KEY=your_key_here # اختياري
Windows (Command Prompt):
set AISSTREAM_API_KEY=your_key_here
set OPENSANCTIONS_API_KEY=your_key_here
Windows (PowerShell):
$env:AISSTREAM_API_KEY = "your_key_here"
$env:OPENSANCTIONS_API_KEY = "your_key_here"
3. تشغيل المتعقب ولوحة القيادة في محطتين منفصلتين
المحطة 1 — مستهلك تغذية AIS:
python shadow_tracker.py
المحطة 2 — لوحة القيادة على الويب:
uvicorn webserver:app --host 0.0.0.0 --port 8000
4. افتح لوحة القيادة
http://localhost:8000
الخريطة الحية على http://localhost:8000/map وتُحدّث كل 3 دقائق. في أول تشغيل، تُعرض الخريطة فورًا من أي سجل مواقع موجود بالفعل في قاعدة البيانات — لا انتظار لشاشة فارغة.
| الخدمة | مطلوب | الطبقة المجانية | الرابط |
|---|---|---|---|
| AISStream | نعم | نعم — غير محدود للاستخدام غير التجاري | aisstream.io |
بدون OPENSANCTIONS_API_KEY يعمل المتعقب بشكل طبيعي — ببساطة تُحذف شارات العقوبات من النوافذ المنبثقة للخريطة.
جميع المعلمات القابلة للضبط في أعلى shadow_tracker.py:
متغيرات البيئة:
| المتغير | مطلوب | الوصف |
|---|---|---|
AISSTREAM_API_KEY | نعم | مفتاح API لـ WebSocket AISStream |
OPENSANCTIONS_API_KEY | لا | يُفعّل البحث عن العقوبات في النوافذ المنبثقة للخريطة |
OpenSanctions مجانية للاستخدام غير التجاري — سجّل على opensanctions.org/api. بدون مفتاح، يعمل المتعقب بشكل طبيعي؛ تُحذف حقول العقوبات من النوافذ المنبثقة.
war-sanctions.gur.gov.ua هو الكتالوج العام الأوكراني لسفن الأسطول الظل والخاضعة للعقوبات. لكل سفينة صفحة مرقمة تحتوي على تاريخ زيارات الموانئ، خرائط، وتفاصيل العقوبات.
يقوم gur_scrape.py ببناء تعيين محلي IMO→GUR-ID عن طريق المسح مرة واحدة:
python gur_scrape.py
ينتج هذا gur_mapping.json. يقوم المتعقب بتحميله عند بدء التشغيل ويستخدم روابط عميقة مباشرة (/en/transport/ships/{id}) في النوافذ المنبثقة للخريطة حيثما كان ذلك متاحًا، مع العودة إلى بحث Google site-search للسفن غير الموجودة بعد في الكتالوج.
يغطي المسح حوالي 1600 إدخال بمعدل 1.5 ثانية/طلب (~40 دقيقة). أعد تشغيله من حين لآخر مع نمو الكتالوج — استخدم --start لاستئناف من معرف محدد:
python gur_scrape.py --start 1580
لتصحيح صفحة مفردة:
python gur_scrape.py --probe 1517
يتم إعادة تحميل gur_mapping.json تلقائيًا كل 5 دقائق بالتزامن مع قائمة المراقبة — لا حاجة لإعادة تشغيل المتعقب بعد إعادة المسح.
عتبات التباطؤ في loitering_module.py:
| الثابت | القيمة الافتراضية | الوصف |
|---|---|---|
SPEED_THRESHOLD_KN | 0.5 عقدة |
إعدادات الشحن في transshipment_module.py:
| الثابت | القيمة الافتراضية | الوصف |
|---|---|---|
SPEED_THRESHOLD_KN |
مناطق الموانئ المغطاة:
| الميناء | النوع |
|---|---|
| Ust-Luga، Primorsk، سانت بطرسبرغ، Vyborg | محطات تصدير روسية |
| Skaw/Skagen، Gothenburg، Kiel، Copenhagen، Aarhus | محاور شحن غربية |
كل صفحة سفينة (/vessel/<mmsi>) تُظهر:
تضع علامات على نمطين مُستنتجين من بيانات المواقع:
يتم استنتاج زيارات الموانئ من نقاط المواقع — لا حاجة لواجهة برمجة تطبيقات خارجية. يجب أن تكون السفينة داخل منطقة ميناء بسرعة <1.5 عقدة لمدة نقطتين على الأقل لتسجيل زيارة. هذا يُظهر نمطًا، وليس حكمًا.
filtered_cables.kml مشتق من مجموعات بيانات مفتوحة المصدر وهو تقريبي — غير مناسب لحسابات القرب الدقيقة. عتبة التنبيه 10 كم تراعي هذا الهامش. نرحب بالمساهمات لتحسين هندسة الكابلات.
يعمل المتعقب بحلقة غير متزامنة واحدة على تيار WebSocket. يتم الاحتفاظ بالحالة في الذاكرة (vessel_info, static_cache) ويتم تفريغها إلى SQLite في كل دورة عرض. تُكتب الخريطة بشكل ذري عبر os.replace لتجنب تقديم ملف جزئي.
عند بدء التشغيل، يقرأ warm_restart() آخر WARM_RESTART_HOURS ساعة من vessel_data_log.db ويُملأ vessel_info مسبقًا قبل اتصال WebSocket. تُعرض الخريطة الأولية فورًا. يتم تمييز المواقع القديمة بصريًا (علامات رمادية، مسارات باهتة) وتتحول إلى اللون الحي عند وصول نقاط جديدة.
يتم إعادة تحميل قائمة المراقبة و gur_mapping.json من القرص كل 5 دقائق — يمكن إضافة السفن وإعادة مسح GUR أثناء تشغيل المتعقب، دون إعادة تشغيل.
خادم الويب عديم الحالة ويقرأ مباشرة من ملفات SQLite — لا ذاكرة مشتركة مع عملية المتعقب.
| السفينة | IMO | الحدث |
|---|
| EAGLE S | 9329760 | استولت عليها فنلندا ديسمبر 2024 — تخريب كابل Estlink-2، معدات تجسس عُثر عليها |
| EVENTIN | 9308065 | استولت عليها ألمانيا يناير-مارس 2025 — انجرفت قبالة Rügen، صودرت 100,000 طن من النفط الروسي |
| KIWALA | 9332810 | احتجزتها إستونيا أبريل 2025 — بلا علم، خاضعة لعقوبات الاتحاد الأوروبي/المملكة المتحدة |
| JAGUAR | 9293002 | اعترضتها إستونيا مايو 2025 — أرسلت روسيا طائرة Su-35 لمرافقتها |
| KIRA K | 9346720 | تأكيد طاقم فاغنر/GRU على متنها ديسمبر 2025 |
| QENDIL | 9310525 | طاقم فاغنر/GRU سبتمبر 2025 — ضربة طائرة مسيرة أوكرانية ديسمبر 2025 |
| FITBURG | 9250397 | استولت عليها فنلندا 31 ديسمبر 2025 — تخريب كابل هلسنكي-تالين |
| CAFFA | 9143611 | استولت عليها السويد 6 مارس 2026 — حبوب أوكرانية مسروقة، علم مزيف |
| SEA OWL I | 9321172 | استولت عليها السويد 12 مارس 2026 — خاضعة لعقوبات الاتحاد الأوروبي، علم جزر القمر مزيف |
| OpenSanctions | لا | نعم — استخدام غير تجاري | opensanctions.org/api |
| الثابت | القيمة الافتراضية | الوصف |
|---|
BALTIC_BBOX | 52.65–66°N, 9–30°E | مربع حدود اشتراك AISStream |
CABLE_ALERT_KM | 10 | عتبة الاقتراب من الكابل |
MAP_RENDER_INTERVAL | 180 ثانية | وتيرة تحديث الخريطة |
MMSI_RELOAD_INTERVAL | 300 ثانية | إعادة تحميل قائمة المراقبة من DB |
WARM_RESTART_HOURS | 24 | ساعات من سجل المواقع لتحميلها عند بدء التشغيل |
RECONNECT_DELAY | 10 ثوانٍ | تأخير إعادة اتصال WS |
| أقل من هذا يُعتبر متوقفًا |
TIME_THRESHOLD_S | 1200 ثانية | المدة قبل وضع علامة التباطؤ |
RADIUS_THRESHOLD_KM | 0.5 كم | أقصى انجراف ليظل نفس النقطة |
| 1.5 عقدة |
| أقل من هذا داخل منطقة الميناء يُعتبر زيارة |
MIN_PINGS_IN_ZONE | 2 | الحد الأدنى من النقاط قبل تسجيل زيارة ميناء |
WINDOW_DAYS | 21 | أقصى أيام بين زيارات الموانئ لوضع علامة شحن |
| المسار | الوصف |
|---|
/ | عارض السجلات الحية، يُحدّث تلقائيًا كل 60 ثانية |
/map | أحدث خريطة معروضة (متوافقة مع iframe) |
/analyze | جدول سجلات السفن قابل للتصفية مع تصدير CSV |
/timeline | نظرة عامة على النشاط — بطاقة واحدة لكل سفينة مُتتبعة، مرتّبة حسب آخر مشاهدة |
/vessel/<mmsi> | تاريخ كل سفينة: انقطاعات AIS، قرب الكابل، تغييرات العلم، تصدير GPX |
/vessel/<mmsi>/gpx | تصدير مسار GPX — يُفتح في QGIS، OpenStreetMap، GPSBabel |
/loitering | أحداث التباطؤ مع علامة قرب الكابل، ملخص لكل سفينة، تصدير CSV |
/transshipment | أنماط زيارات الموانئ روسيا↔غرب — أحداث RU→WEST و WEST→RU، تصدير CSV |
/log/download | تنزيل ملف السجل الخام |
| المكون | الحالة |
|---|
| مستهلك تيار AIS | يعمل |
| قائمة المراقبة | أكثر من 1200 سفينة (كتالوج GUR الكامل) |
| تنبيه قرب الكابل | يعمل |
| كشف التباطؤ | يعمل |
| كشف الشحن | يعمل — استنتاج زيارات الموانئ من المواقع، نافذة 21 يومًا |
| عرض الخريطة | يعمل — وتيرة 3 دقائق، عدّاد تنازلي حي، إعادة تحميل تلقائي |
| إعادة التشغيل الدافئة | يعمل — يُملأ الخريطة مسبقًا من آخر 24 ساعة من السجلات عند بدء التشغيل |
| النوافذ المنبثقة للسفن | روابط مباشرة لـ MarineTraffic + VesselFinder + War&Sanctions (تم تعيين 1337 سفينة) |
| النوافذ المنبثقة للسفن | حالة عقوبات OpenSanctions (اختياري، يتطلب مفتاح API) |
| كشف تغيير العلم | يعمل — يسجل التغييرات، مخزّن في flag_history |
| لوحة القيادة — سجل، سفن، تصدير CSV | يعمل |
| لوحة القيادة — عرض الجدول الزمني | يعمل |
| لوحة القيادة — تاريخ كل سفينة + GPX | يعمل |
| لوحة القيادة — إعادة تشغيل المسار | يعمل — تشغيل/إيقاف مؤقت/إعادة تعيين، التحكم في السرعة، تمييز تنبيه الكابل |
| لوحة القيادة — لوحة التباطؤ | يعمل |
| لوحة القيادة — لوحة الشحن | يعمل |