كيف تستضيف Moli كمتصفح بلا واجهة لوكلائك؟
ثبّت Moli على VPS صغير، وشغّل CDP على loopback، ثم وصّل Playwright أو وكيلك به. تعرّف إلى الصفحات التي تفشل بسبب غياب GPU وCanvas عالي الدقة.
متصفح بلا واجهة رسومية يناسب VPS صغيراً
Moli هو متصفح بلا واجهة رسومية لوكلاء الذكاء الاصطناعي، وهو صغير بما يكفي لاستضافته ذاتياً على VPS لا يتسع لـheadless Chrome. وهو محرّك متصفح مكتوب بلغة Rust، وليس غلافاً حول Chromium، ويستجيب إلى Chrome DevTools Protocol (CDP)، وهو البروتوكول الذي تتحدث به مكتبة الأتمتة لديك بالفعل. تثبّت ملفاً ثنائياً واحداً، وتشغّل moli serve، ثم توجّه Playwright أو رمز وكيلك الخاص إلى http://127.0.0.1:9222.
اقرأ المقايضة قبل تثبيت أي شيء. يوضح المشروع نطاقه بنفسه: لا يوجد متصفح بواجهة رسومية، ولا compositor لوحدة GPU، ولا تطابق بكسل مقابل بكسل مع Chrome، ولا دعم عالي الدقة لـCanvas أو تشغيل الوسائط. ستفشل الصفحات التي تحتاج إلى هذه الميزات. يبقى Chrome الفعلي عبر Playwright خياراً بديلاً، ويوضح لك القسم الأخير كيفية تحديد الصفحات التي تحتاج إليه.
يأتي كل أمر أدناه من README الخاص بالمشروع وملفات skill المنشورة لديه، وقد جرى التحقق منها في August 2026. كل رقم في المخططات هو رقم نشره المشروع عن محرّكه نفسه، وليس قياساً أُجري على هذا الموقع، ويوضح ذلك كل عنوان للمخطط. إذا كنت لا تزال تختار محرّكاً، فسيغطي الاستطلاع الأوسع لـالمتصفحات بلا واجهة رسومية للوكلاء على VPS البدائل.
لماذا يستهلك Chrome headless كل هذه الذاكرة؟
Chrome متصفح متعدد العمليات. تحصل كل علامة تبويب وكل iframe من موقع مختلف على عملية renderer خاصة بها، وتحمل كل عملية renderer كومة V8 ومخازن الرسومات الخاصة بها. هذا التصميم مناسب لسطح المكتب، حيث يجب ألا تتسبب علامة تبويب متوقفة في إيقاف النافذة بأكملها. لكن على VPS بسعة 2 GB، قد تستهلك خطوة تصفح واحدة ذاكرة أكبر من التطبيق الذي تشغّله فعلياً.
زحف المشروع إلى 192 عنوان URL عاماً ومتنوعاً باستخدام أربعة محركات، ثم نشر النتيجة.
The data behind this chart
[
{
"engine": "Moli",
"useful_pages": 103,
"median_rss_mib": 73
},
{
"engine": "Chrome Headless",
"useful_pages": 101,
"median_rss_mib": 773
},
{
"engine": "Lightpanda",
"useful_pages": 85,
"median_rss_mib": 40
},
{
"engine": "Obscura",
"useful_pages": 57,
"median_rss_mib": 39
}
]أعاد Chrome Headless عدد 101 من الصفحات المفيدة، بينما أعاد Moli العدد 103، لذلك قرأ المحركان في هذه العينة حصة متقاربة من الويب. يظهر الفرق في الذاكرة: بلغ وسيط RSS (حجم المجموعة المقيمة، أي الذاكرة التي تحتفظ بها العملية فعلياً في RAM) 773 MiB في Chrome، مقابل 73 MiB في Moli. وهذا الاتجاه منطقي لأن بنية العمليات تفسّره. لكن لا تفترض أن النسبة نفسها ستظهر في صفحاتك.
الوسيط ليس الرقم الذي يسبب المشكلة. الذروة هي المهمة. عندما تنفد ذاكرة جهاز بسعة 2 GB، تختار النواة عملية وتُنهيها، ويظهر السجل في dmesg -T أو journalctl -k:
Out of memory: Killed process 4211 (chrome) total-vm:2318936kB, anon-rss:1418324kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:3540kB oom_score_adj:0لا يرى وكيلك ذلك السطر. بل يرى متصفحاً توقف عن الاستجابة، ويظهر ذلك عادةً كخطأ من Playwright مثل page.goto: Page crashed أو كهدف مغلق. لا يذكر هذا الخطأ الذاكرة، ولذلك يكون OOM (منهي نفاد الذاكرة) أول ما يجب التحقق منه عندما يفشل وكيل عشوائياً على جهاز صغير. إن تحديد الموارد وفق الذروة هو العملية نفسها المتّبعة عند اختيار RAM وCPU لـVPS الوكيل.
ثبّت ملف Moli الثنائي بإصدار محدد
ينشر المشروع برنامج تثبيت shell وأرشيفات tar مُعدّة مسبقاً ضمن إصدارات GitHub. اعتباراً من August 2026، الإصدار الحالي هو 1.0.1، وقد نُشر في 18 August 2026. قاس المشروع أرقام الأداء الواردة في هذا الدليل باستخدام الإصدار 0.1.1، لذلك تعامل معها باعتبارها تصوراً تقريبياً لسلوك المحرك، لا ضماناً لنسخة البناء التي ستثبتها.
ثبّت الإصدار. إذا حلّ برنامج التثبيت دائماً latest، فسوف ينقل وكيلك إلى محرك متصفح مختلف عند إعادة البناء التالية. وتغيير سلوك المتصفح من التغييرات التي ينبغي لك جدولتها، لا اكتشافها بعد حدوثها.
برنامج تثبيت shell هو أسرع طريقة للبدء. ومن المفيد قراءته قبل تشغيله.
curl --proto '=https' --tlsv1.2 -fsSL \
-o /tmp/moli-installer.sh \
https://github.com/lexmount/moli/releases/download/v1.0.1/moli-installer.sh
less /tmp/moli-installer.sh
sh /tmp/moli-installer.shاقرأ البرنامج النصي قبل تشغيله. فهو قصير. يختار أرشيفاً من uname -m، ثم يفك أرشيفاً يحتوي على ملف ثنائي واحد داخل ~/.local/bin. على x86_64، يستخدم moli-x86_64-unknown-linux-gnu.tar.gz، وعلى خادم Arm يستخدم أرشيف aarch64، لذلك فهو يغطي خطتي VPS لكل من Arm وx86. عيّن MOLI_INSTALL_DIR للتثبيت في مكان آخر. لاحظ الإصدار الذي يحلّه البرنامج: أحدث إصدار، وليس الوسم الذي جلبت البرنامج النصي منه. هذا مناسب لإلقاء نظرة أولى، لكنه غير مناسب لإعادة بناء قابلة للتكرار.
لذلك، نفّذ يدوياً كل ما ينفذه برنامج التثبيت عند تثبيت دائم، وحدد الأرشيف الدقيق بنفسك. بهذه الطريقة تضع الملف الثنائي أيضاً في مكان تستطيع خدمة النظام الوصول إليه، وتتجنب تمرير برنامج نصي مُنزّل إلى shell.
cd /tmp
curl --proto '=https' --tlsv1.2 -fsSLO \
https://github.com/lexmount/moli/releases/download/v1.0.1/moli-x86_64-unknown-linux-gnu.tar.gz
mkdir -p moli-pkg
tar -xzf moli-x86_64-unknown-linux-gnu.tar.gz -C moli-pkg --strip-components=1
sudo install -m 0755 moli-pkg/moli /usr/local/bin/moli
moli --versionطباعة الإصدار الذي ثبّتَّه عبر moli --version هي كامل الاختبار. يشير moli: command not found مباشرة بعد برنامج التثبيت إلى أن دليل التثبيت ليس ضمن PATH لديك، ويطبع برنامج التثبيت سطراً يحدد الدليل الذي تحتاج إلى إضافته.
الاستخراج لمرة واحدة باستخدام moli fetch
تتمثل كثير من المهام التي يطلب فيها الوكيل من المتصفح في «حمّل عنوان URL هذا وأخبرني بما يحتويه». لا يتطلب ذلك خادماً على الإطلاق. يبدأ moli fetch المحرك، ويحمّل صفحة واحدة، ويكتب ناتجاً واحداً إلى الإخراج القياسي، ثم يخرج؛ لذلك لا يحتفظ بأي ذاكرة بين الاستدعاءات.
moli fetch --dump markdown --wait-until networkidle https://example.com
moli fetch --dump semantic_tree_text --wait-selector "main" https://example.com
moli fetch --dump json --wait-until networkidle https://example.com > page.jsonيطبع الخيار الأول الصفحة بصيغة Markdown، بدءاً من # Example Domain. وتُعد Markdown أرخص صيغة لتقديمها إلى نموذج، لأنها تزيل الترميز وتُبقي النص. يحافظ semantic_tree_text على الأدوار والبنية، وهذا ما تحتاج إليه في صفحة تكثر فيها عناصر التنقل، حيث لا تقل أهمية الروابط عن أهمية النص. ينقل --dump json حالة HTTP وتتبع الطلب، لذا استخدمه عندما يعود الجلب فارغاً وتحتاج إلى معرفة السبب.
تحدد استراتيجية الانتظار ما إذا كنت ستحصل على المحتوى أو على هيكل فارغ. يعيد --wait-until networkidle النتيجة عندما تهدأ حركة الشبكة. ويعيد --wait-until domstable النتيجة عندما يتوقف DOM عن التغير، وهو الخيار الأفضل في صفحة تستطلع البيانات في الخلفية، ولذلك لا تهدأ حركة الشبكة فيها أبداً. ينتظر --wait-selector محدداً واحداً تسميه. وهي الاستراتيجية الوحيدة التي تعرف شيئاً عن الصفحة التي تجلبها، ما يجعلها الأكثر موثوقية كلما كنت تعرف العنصر المستهدف.
تحتاج لقطات الشاشة وملفات PDF إلى تخطيط فعلي، ويكون التخطيط معطلاً افتراضياً:
moli fetch --layout --dump screenshot https://example.com > page.png
moli fetch --layout --dump screenshot_full https://example.com > full-page.png
moli fetch --layout --dump pdf https://example.com > page.pdfيسمي README سياسة التخطيط الافتراضية LayoutPolicy::Mock: تُحاكى الهندسة ولا يُرسم أي شيء، لأن التخطيط والرسم هما الجزء الأعلى كلفة في المتصفح. وهذا الافتراض هو سبب ظهور أرقام الذاكرة أعلاه على ذلك النحو. ويعني أيضاً أن ملف PNG الفارغ ينتج عادةً عن غياب الخيار --layout، لا عن تعطل الصفحة.
أضف --block-private-networks إلى عناوين URL التي عثر عليها وكيلك، بدلاً من عناوين URL التي اخترتها أنت. فقد يتبع وكيل الروابط التي قرأها في صفحة، ثم يُوجَّه إلى جلب http://169.254.169.254/ للحصول على بيانات اعتماد مثيل سحابي، أو إلى منفذ قاعدة بيانات على localhost لم يكن معداً للوصول من الويب. يرفض ذلك الخيار الانتقال إلى مساحة العناوين الخاصة، ويضيّق --block-cidrs النطاق أكثر. عندما تكون المهمة زحفاً بدلاً من قراءة صفحة واحدة، يشرح بدائل Firecrawl المستضافة ذاتياً بنية خط الأنابيب هذه، بينما يشرح مهارة بحث للوكلاء مدعومة بـSearXNG الخطوة السابقة لها، أي العثور على عناوين URL أصلاً.
وجّه agent إلى Moli عبر CDP
بالنسبة إلى agent الذي يتنقل وينقر عبر خطوات كثيرة، شغّل الخادم بدلاً من ذلك.
moli serve --host 127.0.0.1 --port 9222يُعد 127.0.0.1 والمنفذ 9222 القيمتين الافتراضيتين، لذلك يرتبط moli serve المجرد بـloopback فقط. اكتب القيمتين صراحةً في أي إعداد دائم، حتى لا يضطر الشخص الذي يقرأ ملف الخدمة لاحقاً إلى تذكّر القيمة الافتراضية.
تحقّق من الخادم قبل توصيل client به:
curl -s http://127.0.0.1:9222/json/versionيستجيب الخادم السليم بكائن JSON يحتوي على الحقل webSocketDebuggerUrl، وهذا هو عنوان URL الذي يتصل به client الخاص بـCDP. يعني curl: (7) Failed to connect to 127.0.0.1 port 9222: Connection refused أنه لا توجد عملية تستمع، لذلك اقرأ الطرفية التي شغّلت الخادم منها، أو استخدم journalctl -u moli -n 50 بعد تشغيله كخدمة. يعرض /json/list الأهداف المفتوحة، بينما يعرض /json/protocol النطاقات التي يطبقها هذا الإصدار. بهذه الطريقة تعرف ما إذا كانت طريقة CDP التي تعتمد عليها متاحة هنا.
يتصل Playwright بنقطة النهاية هذه بدلاً من تشغيل browser خاص به:
import { chromium } from "playwright";
const browser = await chromium.connectOverCDP("http://127.0.0.1:9222");
const context = browser.contexts()[0];
const page = context.pages()[0] ?? await context.newPage();
await page.goto("https://example.com");
console.log(await page.locator("body").innerText());
await browser.close();السطر المهم هو connectOverCDP، وليس chromium.launch(). لا توجد هنا عملية Chromium فرعية، لذلك لا يوجد ما يؤثر فيه executablePath أو flags الحاويات المعتادة مثل --no-sandbox. وللسبب نفسه، تُمرَّر إعدادات proxy وcookie وuser-agent إلى خادم Moli بوصفها flags خاصة به. توقّع دعماً جزئياً لـCDP، لا دعماً كاملاً لبروتوكول Chrome. خطأ صريح يفيد بأن method غير مدعومة يحدد حدود المحرك، ولا يعني وجود خطأ في كودك.
يحدّد flagان للخادم ما يستطيع agent تنفيذه. يفعّل --layout الحساب الفعلي للهندسة، وهو ما تحتاج إليه نقرات الإحداثيات ولقطات الشاشة. يجلب --resource الصور والخطوط والوسائط الاختيارية، ويستهلك ذلك bandwidth وذاكرةً عند تحميل كل صفحة، لذلك اتركه معطلاً إلى أن تثبت صفحة ما حاجتها إليه. يحافظ --profile-dir على cookies وstorage بين عمليات التشغيل. ومن دونه تكون كل عملية تشغيل مؤقتة.
The data behind this chart
[
{
"engine": "Moli",
"cdp_ready_ms": 34.85,
"peak_pss_mib": 102.46,
"processes": 1
},
{
"engine": "Chromium",
"cdp_ready_ms": 169.37,
"peak_pss_mib": 348.82,
"processes": 11
}
]في حمل العمل النموذجي لـagent في المشروع، قبل Moli اتصال CDP بعد 34.85 ms، مقارنةً بـ169.37 ms لـChromium، وبـPSS أقصى (الحجم المتناسب للمجموعة، حيث تُحتسب الذاكرة مع توزيع الصفحات المشتركة بين العمليات التي تشاركها) بلغ 102.46 MiB، مقارنةً بـ348.82 MiB. يظهر الفرق البنيوي في العمود الأخير: عملية واحدة 1، مقارنةً بـ11. العملية الواحدة تعني مورداً واحداً يشرف عليه systemd وcgroup واحداً يفرض حده، وهذا ما يجعل القسم التالي مختصراً.
شغّل moli serve كخدمة systemd على loopback
شغّل الخادم كخدمة عندما يحتاج أحد الوكلاء إلى متصفح ينتظره. استخدم moli fetch لكل عنوان URL عندما لا يحتاج إليه، لأن الخادم الخامل يظل يشغل الذاكرة.
لا تضع المنفذ 9222 على واجهة عامة. لا يوفّر CDP أي خطوة مصادقة على الإطلاق. يمكن لأي جهة تصل إلى هذا المنفذ التحكم في المتصفح وقراءة كل ما يمكن للمتصفح الوصول إليه، بما في ذلك أي cookies في دليل ملفك الشخصي. أبقه على 127.0.0.1. وصّل إليه من جهاز آخر عبر نفق SSH (ssh -L 9222:127.0.0.1:9222 user@your-vps) أو عبر واجهة VPN خاصة، ودَع الوكيل يتصل بـhttp://127.0.0.1:9222 على جانبه من ذلك النفق.
أنشئ مستخدم خدمة، ثم أنشئ ملف الوحدة:
sudo useradd --system --home-dir /var/lib/moli --shell /usr/sbin/nologin moliاكتب /etc/systemd/system/moli.service:
[Unit]
Description=Moli headless browser CDP server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=moli
Group=moli
ExecStart=/usr/local/bin/moli serve --host 127.0.0.1 --port 9222 --profile-dir /var/lib/moli/profile --block-private-networks
Restart=on-failure
RestartSec=2
StateDirectory=moli
MemoryAccounting=yes
MemoryMax=768M
NoNewPrivileges=yes
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=strict
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now moli.service
systemctl status moli.service
curl -s http://127.0.0.1:9222/json/versionيجب أن يعرض systemctl status القيمة active (running)، ويجب أن يعيد curl JSON الاكتشاف. يركّب ProtectSystem=strict نظام الملفات بالكامل للقراءة فقط لهذه الوحدة، ولذلك فإن StateDirectory=moli ليس اختيارياً هنا: فهو ينشئ /var/lib/moli، ويملكه لمستخدم الخدمة، ويجعل هذا المسار وحده قابلاً للكتابة. إذا بدأت الوحدة ثم توقفت بسبب خطأ صلاحيات في journalctl -u moli، فهي تحاول في الغالب الكتابة في مكان جعله ProtectSystem للقراءة فقط، لذلك انقل هذا المسار إلى دليل الحالة.
MemoryMax=768M هو ما يجعل تشغيل هذه الخدمة آمناً بجانب تطبيقك. تحصل الوحدة على cgroup خاص بها. وعندما يتجاوز ذلك الـcgroup الحد المعيّن له، تقتل النواة عملية داخله وتترك بقية الخادم دون تأثير. يسجل journal ذلك:
moli.service: A process of this unit has been killed by the OOM killer.اقرأ هذا السطر كمؤشر لتحديد الحجم. إما أن الصفحات أكبر مما خططت له، أو أن الحد منخفض جداً. اضبط الرقم استناداً إلى قياس صفحاتك الفعلية. يشرح القسم التالي هذه العملية. تحصر علامات المحاسبة نفسها أي خدمة أخرى على الخادم، كما يتيح تحديد حد الذاكرة ووحدة المعالجة المركزية باستخدام systemd تطبيق ذلك على بقية الخدمات.
قِس استهلاك الذاكرة الأقصى بنفسك
الأرقام المنشورة مأخوذة من عتاد شخص آخر وصفحات شخص آخر. يحدد استهلاك الذاكرة الأقصى ما إذا كان خادمك سيستمر في العمل، ويعتمد هذا الاستهلاك بالكامل على المحتوى الذي تحمّله. قِس الاستهلاك قبل تحديد الموارد.
لجلب الصفحات مرة واحدة، استخدم الملف التنفيذي time، فهو يعرض معلومات أكثر بكثير من الأمر المضمّن في shell الذي يحمل الاسم نفسه:
sudo apt update && sudo apt install -y time
/usr/bin/time -v moli fetch --dump markdown --wait-until networkidle https://example.com > /dev/nullينتهي الناتج بكتلة من إحصاءات الموارد تتضمن Maximum resident set size (kbytes). اقسم القيمة على 1024 لتحويلها إلى MiB. شغّل الأمر على عشر صفحات يزورها وكيلك فعلاً، وليس على example.com، واحتفظ بأسوأ نتيجة بدلاً من المتوسط، لأن OOM killer يستجيب للقمم.
بالنسبة إلى الخدمة، اقرأ العداد الذي يحتفظ به kernel مسبقاً لمجموعة cgroup الخاصة بها:
cat /sys/fs/cgroup/system.slice/moli.service/memory.peak
systemd-cgtop -mmemory.peak هو عدد بالبايت، ويمثل أعلى قيمة مسجلة منذ بدء تشغيل الوحدة آخر مرة، لذلك تؤدي إعادة التشغيل إلى تصفيره. يجب أن تكون قيمة MemoryMax أعلى من هذا الرقم، مع ترك مساحة إضافية للصفحة الأثقل التي لم تزرها بعد. يعرض systemd-cgtop -m الاستخدام الحالي لكل وحدة، وهو أسرع طريقة لمعرفة الخدمة الأكثر استهلاكاً للموارد على الخادم اليوم.
أين يفشل Moli، ومتى تظل بحاجة إلى Chrome؟
يشغّل المشروع أيضاً معياراً يتضمن 1,308 مهمة قابلة للمقارنة لأتمتة المتصفح، وينشر النتيجة لعدة محركات.
The data behind this chart
[
{
"engine": "Chrome",
"success_rate_pct": 99.85
},
{
"engine": "Moli 0.1.1",
"success_rate_pct": 81.88
},
{
"engine": "Kitesurf",
"success_rate_pct": 62.08
},
{
"engine": "Lightpanda",
"success_rate_pct": 53.29
},
{
"engine": "Obscura",
"success_rate_pct": 44.88
}
]أكمل Moli 0.1.1، عبر تلك المحركات البالغ عددها 5، 81.88 بالمئة من المهام، بينما أكمل Chrome، وهو المحرك المرجعي، 99.85 بالمئة. يقيس المشروع أداءه باستخدام مجموعته الخاصة، لذلك تعامل مع هذه النتيجة باعتبارها ادعاءً، لا نتيجة مستقلة.
الاستنتاج العملي بسيط. فشلت مهمة واحدة تقريباً من كل خمس مهام في Moli، بينما نجح Chrome في إكمالها. إذا كان وكيلك يزور مجموعة ثابتة من الصفحات التي تتحكم فيها، فلن تخبرك هذه النسبة بالكثير، لأن صفحاتك إما تعمل أو لا تعمل، ويمكنك معرفة ذلك هذا afternoon. أما إذا كان وكيلك يتصفح الويب المفتوح، فهذه نسبة فشل فعلية يجب أن تصمم النظام على أساسها.
يمكن توقّع حالات الفشل من النطاق الذي يحدده المشروع.
- التطبيقات التي ترسم واجهتها داخل عنصر Canvas بدلاً من DOM، لأن مطابقة Canvas خارج النطاق المعلن صراحةً
- أي شيء يحتاج إلى WebGL أو تركيب رسومي باستخدام GPU، لعدم وجود مُركِّب GPU
- الفيديو المحمي بواسطة DRM وتشغيل الوسائط المتطلب لموارد كبيرة
- الاختبارات المرئية التي تتحقق من لقطات شاشة مطابقة للبكسل مع Chrome، لأن تحقيق التكافؤ مع Chrome ليس هدفاً
أما الرقم الآخر الذي يورده المشروع، وهو اجتياز تشغيل كامل يتضمن 1.612 مليون اختبار لمنصة الويب، فيتعلق بتغطية المعايير. ولا يمثل ضماناً بأن المواقع التي سيزورها وكيلك ستعمل. فقد تستخدم الصفحة معايير مدعومة بالكامل، ومع ذلك تفشل في فحص خاص بالروبوتات، ولا تغطي نتيجة أي محرك هذه الحالة.
لذلك أبقِ المسار الاحتياطي ضمن التصميم. أرسل كل عنوان URL إلى Moli أولاً. عندما تعود الصفحة فارغة، أو لا يظهر محدد مطلقاً، أعد محاولة عنوان URL نفسه باستخدام Playwright لتشغيل Chrome الحقيقي، على جهاز أكبر أو وفق جدول تكون فيه عملية تستهلك 773 MiB مقبولة التكلفة. تقضي معظم الوكلاء معظم وقتها على صفحات عادية، لذلك يتولى المحرك الصغير حجم العمل، بينما يتولى المحرك الأعلى تكلفة الحالات النادرة والصعبة.
FAQ
هل يمكن لـMoli أن يحل محل Chrome عديم الواجهة لوكيلي؟
لقراءة الصفحات، واستخراج النص، والنقر العادي، تكون الإجابة عادةً نعم. في الاختبار المعياري الخاص بالمشروع، الذي شمل 1,308 مهمة، أكمل Moli نسبة 81.88 بالمئة، مقابل نسبة 99.85 بالمئة لـChrome، ما يعني أن مهمة واحدة تقريباً من كل خمس مهام تحتاج إلى وظيفة لا يوفرها Moli. تشمل الفجوات المعروفة التطبيقات التي تُعرَض عبر Canvas، وWebGL، وفيديو DRM. وجّه عناوين URL هذه إلى Chrome فعلي بدلاً من إعادة كل شيء إلى Chrome.
ما مقدار RAM الذي يحتاج إليه Moli على VPS؟
يذكر المشروع أن متوسط RSS الوسيط يبلغ 73 MiB خلال زحف شمل 192 عنوان URL، وأن ذروة PSS تبلغ 102.46 MiB في حلقة نموذجية لوكيل، مقابل وسيط قدره 773 MiB لـChrome عديم الواجهة. هذه أرقامهم على صفحاتهم. قِس قيمتك باستخدام /usr/bin/time -v حول استدعاء moli fetch للاستخدام لمرة واحدة، أو اقرأ /sys/fs/cgroup/system.slice/moli.service/memory.peak للخدمة، ثم اضبط MemoryMax على قيمة أعلى من أسوأ رقم تراه.
هل من الآمن إتاحة المنفذ 9222 على الإنترنت؟
لا. لا يوفر CDP مصادقة، لذلك يمكن لأي شخص يستطيع الوصول إلى ذلك المنفذ التحكم في متصفحك وقراءة أي شيء يستطيع المتصفح الوصول إليه. أبقِ --host 127.0.0.1، ووصل إلى نقطة النهاية من جهاز آخر عبر نفق SSH أو من خلال واجهة VPN خاصة. إذا اضطررت إلى ربط عنوان آخر، فاستخدم واجهة خاصة وتحكّم في الوصول باستخدام جدار الحماية.
لماذا تكون لقطة الشاشة فارغة، أو لماذا يصل النقر إلى لا شيء؟
التخطيط معطّل افتراضياً. يذكر README أن السياسة الافتراضية هي LayoutPolicy::Mock، ولذلك لا تكون هندسة العناصر حقيقية، ولا يمكن لأي وظيفة تعتمد على مربع في الصفحة أن تعمل. ابدأ الخادم باستخدام moli serve --layout، أو أضف --layout إلى moli fetch، وعندها تبدأ لقطة الشاشة ومسارات الإحداثيات بالعمل. الصور المفقودة مرتبطة بوسم مختلف: --resource.
ما إصدار Moli الذي ينبغي أن أثبّته؟
ثبّت إصداراً واحداً وسجّل الإصدار الذي اخترته. اعتباراً من August 2026، الإصدار الحالي هو 1.0.1، بينما قِيست أرقام الاختبار المعياري التي ينشرها المشروع على الإصدار 0.1.1، لذلك لا يمكن التعامل مع الإصدارين على أنهما متطابقان عند مقارنة ملاحظاتك مع شخص آخر. نزّل moli-x86_64-unknown-linux-gnu.tar.gz الخاص بذلك الوسم وثبّت البرنامج الثنائي بنفسك بدلاً من الاعتماد على مثبّت shell، الذي يحلّ أحدث إصدار بدلاً من الوسم الذي نزّلته منه، ثم تحقّق باستخدام moli --version.