SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-08-21

آموزش نصب و میزبانی Moli روی VPS برای ایجنت‌های هوش مصنوعی

اگر Chrome headless منابع سرور شما را اشغال می‌کند، Moli را جایگزین کنید. این راهنما نحوه اتصال Playwright به CDP در Moli و محدودیت‌های اجرای آن در اوت 2026 را بررسی می‌کند.

یک مرورگر بدون رابط کاربری (headless) مناسب برای VPSهای کوچک

Moli یک مرورگر headless برای ایجنت‌های هوش مصنوعی است و به اندازه‌ای سبک است که می‌توان آن را روی VPSهایی میزبانی کرد که Chrome headless در آن‌ها اجرا نمی‌شود. این یک موتور مرورگر است که با Rust نوشته شده و یک wrapper برای Chromium نیست؛ همچنین از پروتکل Chrome DevTools Protocol (CDP) پشتیبانی می‌کند، همان پروتکلی که کتابخانه اتوماسیون شما هم‌اکنون از آن استفاده می‌کند. شما یک فایل باینری را نصب می‌کنید، moli serve را اجرا می‌کنید و سپس Playwright یا کد ایجنت خود را به http://127.0.0.1:9222 متصل می‌کنید.

پیش از نصب، محدودیت‌ها را مطالعه کنید. این پروژه محدوده کاری خود را به صراحت بیان کرده است: بدون رابط کاربری گرافیکی (GUI)، بدون GPU compositor، بدون تطابق پیکسل‌به‌پیکسل با Chrome و بدون پشتیبانی از Canvas با دقت بالا یا پخش رسانه. صفحاتی که به این موارد نیاز دارند، با خطا مواجه خواهند شد. Chrome واقعی در کنار Playwright همچنان گزینه جایگزین باقی می‌ماند و بخش آخر به شما نشان می‌دهد که چگونه تشخیص دهید کدام صفحات به آن نیاز دارند.

تمام دستورات زیر از فایل README پروژه و فایل‌های مهارت منتشرشده آن استخراج شده و در اوت 2026 بررسی شده‌اند. تمام اعداد موجود در نمودارها، ارقامی هستند که خود پروژه درباره موتور خود منتشر کرده است (نه اندازه‌گیری‌های این سایت) و زیرنویس هر نمودار به این موضوع اشاره دارد. اگر هنوز در حال انتخاب موتور هستید، بررسی جامع‌تر مرورگرهای headless برای ایجنت‌ها روی VPS گزینه‌های جایگزین را پوشش می‌دهد.

چرا Chrome بدون رابط کاربری (headless) حافظه زیادی مصرف می‌کند؟

Chrome یک مرورگر چند-پردازشی است. هر تب و هر iframe بین‌سایتی، پردازش رندر (renderer process) اختصاصی خود را دارد و هر پردازش رندر، V8 heap و بافرهای گرافیکی مخصوص به خود را حمل می‌کند. این طراحی برای دسکتاپ مناسب است، جایی که کرش کردن یک تب نباید کل پنجره را از کار بیندازد. در یک VPS با 2 گیگابایت رم، این یعنی یک مرحله مرور ساده می‌تواند حافظه بیشتری نسبت به برنامه‌ای که واقعاً در حال اجرای آن هستید، اشغال کند.

این پروژه 192 آدرس URL عمومی مختلف را با چهار موتور بررسی کرد و نتایج را منتشر نمود.

ChartMixed public web crawl, 192 URLs, figures published by the Moli project
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
  }
]

نسخه Headless مرورگر Chrome تعداد 101 صفحه مفید و Moli تعداد 103 صفحه مفید را بازگرداند؛ بنابراین در آن نمونه، هر دو موتور سهم تقریباً یکسانی از وب را خواندند. تفاوت اصلی در میزان مصرف حافظه است: میانه RSS (اندازه مجموعه مقیم، یعنی حافظه‌ای که یک پردازش واقعاً در RAM نگه می‌دارد) برای Chrome برابر با 773 MiB و برای Moli برابر با 73 MiB است. این روند منطقی است زیرا از معماری پردازشی آن‌ها ناشی می‌شود. نباید فرض کنید که نسبت دقیق در صفحات شما نیز همین‌گونه خواهد بود.

میانه عددی نیست که به شما آسیب می‌زند، بلکه مقدار اوج (Peak) است. وقتی یک سرور 2 گیگابایتی با کمبود حافظه مواجه می‌شود، هسته سیستم‌عامل یک پردازش را انتخاب و آن را متوقف (kill) می‌کند و گزارش آن در 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

عامل (agent) شما هرگز آن خط را نمی‌بیند. آنچه می‌بیند مرورگری است که پاسخ‌دهی را متوقف کرده، که معمولاً به صورت خطای Playwright مانند page.goto: Page crashed یا یک هدف (target) بسته شده ظاهر می‌شود. هیچ‌چیز در آن خطا به حافظه اشاره نمی‌کند، به همین دلیل است که وقتی یک عامل به‌طور تصادفی روی یک سرور کوچک شکست می‌خورد، OOM (خروج از حافظه) اولین چیزی است که باید بررسی کنید. تعیین اندازه برای مقدار اوج، همان تمرینی است که در انتخاب RAM و CPU برای VPS عامل توضیح داده شده است.

نصب باینری Moli با نسخه ثابت

این پروژه یک نصب‌کننده shell و فایل‌های tarball پیش‌ساخته را در GitHub releases منتشر می‌کند. تا اوت 2026، نسخه فعلی 1.0.1 است که در 18 اوت 2026 منتشر شده است. ارقام بنچمارک ذکر شده در این راهنما توسط تیم پروژه روی نسخه 0.1.1 اندازه‌گیری شده‌اند، بنابراین آن‌ها را به عنوان نمای کلی از ساختار موتور در نظر بگیرید، نه تعهدی برای نسخه‌ای که نصب می‌کنید.

نسخه را ثابت (Pin) کنید. نصب‌کننده‌ای که همیشه latest را فراخوانی می‌کند، در بازسازی بعدی، عامل (agent) شما را به یک موتور مرورگر متفاوت منتقل می‌کند؛ تغییر در رفتار مرورگر از آن دسته تغییراتی است که باید برای آن برنامه‌ریزی کنید، نه اینکه به‌طور اتفاقی با آن مواجه شوید.

نصب‌کننده 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 را تنظیم کنید. توجه کنید که اسکریپت برای نسخه چه چیزی را فراخوانی می‌کند: جدیدترین نسخه منتشر شده، نه تگی که اسکریپت را از آن دریافت کرده‌اید. این برای بررسی اولیه مناسب است، اما برای بازسازی‌هایی که می‌خواهید تکرارپذیر باشند، اشتباه است.

بنابراین برای هر مورد دائمی، کاری که نصب‌کننده انجام می‌دهد را به‌صورت دستی انجام دهید و آرشیو دقیق را خودتان نام‌گذاری کنید. این روش همچنین باعث می‌شود باینری را در جایی قرار دهید که یک سرویس سیستمی به آن دسترسی داشته باشد و شما را از لوله‌کشی (piping) یک اسکریپت دانلود شده به داخل 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

بسیاری از وظایفی که یک عامل (agent) به مرورگر محول می‌کند، از نوع «این 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 و ردپای درخواست (trace) را به همراه دارد؛ بنابراین زمانی که یک fetch خالی برمی‌گردد و نیاز دارید دلیل آن را بدانید، از آن استفاده کنید.

استراتژی انتظار تعیین می‌کند که محتوا را دریافت می‌کنید یا یک پوسته خالی. --wait-until networkidle به محض آرام شدن شبکه بازمی‌گردد. --wait-until domstable به محض اینکه تغییرات DOM متوقف شود بازمی‌گردد؛ این گزینه برای صفحاتی که در پس‌زمینه polling انجام می‌دهند و هرگز کاملاً آرام نمی‌شوند، انتخاب بهتری است. --wait-selector منتظر یک انتخابگر (selector) خاص می‌ماند که شما تعیین می‌کنید. این تنها استراتژی است که از محتوای صفحه‌ای که در حال دریافت آن هستید آگاهی دارد و به همین دلیل، هر زمان که هدف را می‌شناسید، مطمئن‌ترین گزینه است.

اسکرین‌شات و PDF به چیدمان (layout) واقعی نیاز دارند و چیدمان به‌صورت پیش‌فرض غیرفعال است:

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 نام‌گذاری کرده است: هندسه صفحه شبیه‌سازی می‌شود اما چیزی ترسیم (paint) نمی‌شود، زیرا چیدمان و ترسیم، نیمه پرهزینه کارکرد یک مرورگر هستند. آن پیش‌فرض دلیل ارقام حافظه ذکر شده در بالا است. همچنین به این معناست که یک PNG خالی معمولاً به دلیل نبود پرچم --layout است، نه خرابی صفحه.

برای URLهایی که عامل شما پیدا کرده (نه URLهایی که خودتان انتخاب کرده‌اید)، از --block-private-networks استفاده کنید. عاملی که لینک‌های خوانده‌شده در یک صفحه را دنبال می‌کند، ممکن است به سمت دریافت http://169.254.169.254/ برای اعتبارسنجی‌های نمونه ابری (cloud instance) یا پورت دیتابیس روی localhost هدایت شود که هرگز قرار نبوده در معرض وب قرار بگیرند. این پرچم از هدایت به فضای آدرس‌های خصوصی جلوگیری می‌کند و --block-cidrs این محدودیت را حتی بیشتر می‌کند. هنگامی که وظیفه به جای خواندن یک صفحه، خزیدن (crawling) در سایت باشد، شکل آن خط لوله در جایگزین‌های self-hosted برای Firecrawl پوشش داده شده است و مرحله پیش از آن، یعنی یافتن URLها، در مهارت جستجوی مبتنی بر SearXNG برای عامل‌ها توضیح داده شده است.

Point an agent at Moli over CDP

For an agent that navigates and clicks across many steps, run the server instead.

moli serve --host 127.0.0.1 --port 9222

127.0.0.1 and port 9222 are the defaults, so a bare moli serve already binds to loopback only. Write both out anyway in anything permanent, because the next person to read your service file should not have to remember what the default was.

Check the server before you connect a client to it:

curl -s http://127.0.0.1:9222/json/version

A healthy server answers with a JSON object holding a webSocketDebuggerUrl field, and that URL is what a CDP client attaches to. curl: (7) Failed to connect to 127.0.0.1 port 9222: Connection refused means nothing is listening, so read the terminal you started it in, or journalctl -u moli -n 50 once it is a service. /json/list lists the open targets and /json/protocol lists the domains this build implements, which is how you find out whether a CDP method you depend on exists here.

Playwright attaches to that endpoint instead of launching a browser of its own:

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();

The line that matters is connectOverCDP, not chromium.launch(). There is no child Chromium process here, so executablePath and the usual container flags such as --no-sandbox have nothing to act on. Proxy, cookie and user-agent settings go to the Moli server as its own flags for the same reason. Expect selected CDP coverage rather than the whole Chrome protocol: an explicit unsupported-method error is a boundary of the engine, not a bug in your code.

Two server flags decide what the agent can do. --layout turns on real geometry, which is what coordinate clicks and screenshots need. --resource fetches the optional images, fonts and media, and it costs bandwidth and memory on every page load, so leave it off until a page proves it needs them. --profile-dir persists cookies and storage between runs, and without it every run is disposable.

ChartOne agent episode, Moli against Chromium, figures published by the Moli project
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
  }
]

On the project's sample agent workload, Moli accepted a CDP connection after 34.85 ms against 169.37 ms for Chromium, at a peak PSS (proportional set size, memory counted with shared pages split between the processes sharing them) of 102.46 MiB against 348.82 MiB. The structural difference is the last column: 1 process against 11. One process is one thing for systemd to supervise and one cgroup to cap, which is what makes the next section short.

اجرای moli serve به‌عنوان یک سرویس systemd روی loopback

زمانی که یک agent به مرورگری نیاز دارد که در انتظار آن باشد، سرور را به‌عنوان یک سرویس اجرا کنید. در غیر این صورت، همچنان از moli fetch برای هر URL استفاده کنید، زیرا سرورِ بیکار همچنان حافظه را اشغال می‌کند.

پورت 9222 را روی رابط عمومی (public interface) قرار ندهید. پروتکل CDP هیچ‌گونه مرحله احراز هویتی ندارد. هر کسی که به آن پورت دسترسی داشته باشد می‌تواند مرورگر را کنترل کرده و هر چیزی که مرورگر به آن دسترسی دارد، از جمله کوکی‌های موجود در دایرکتوری پروفایل شما را بخواند. آن را روی 127.0.0.1 نگه دارید. از طریق یک تونل SSH (ssh -L 9222:127.0.0.1:9222 user@your-vps) یا یک رابط VPN خصوصی به آن متصل شوید و اجازه دهید agent به http://127.0.0.1:9222 در سمت خودِ تونل متصل شود.

یک کاربر سرویس ایجاد کنید و سپس فایل unit را بسازید:

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.target
sudo 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 مربوط به discovery را بازگرداند. ProtectSystem=strict کل سیستم فایل را برای این unit به‌صورت فقط‌خواندنی (read-only) mount می‌کند؛ به همین دلیل است که StateDirectory=moli در اینجا اختیاری نیست: این دستور /var/lib/moli را ایجاد می‌کند که مالکیت آن با کاربر سرویس است و آن مسیر خاص را قابل‌نوشتن می‌کند. unitای که شروع می‌شود و سپس با خطای مجوز در journalctl -u moli از کار می‌افتد، تقریباً همیشه در تلاش است در جایی بنویسد که ProtectSystem آن را فقط‌خواندنی کرده است؛ بنابراین آن مسیر را به زیر دایرکتوری state منتقل کنید.

MemoryMax=768M همان چیزی است که اجرای آن را در کنار برنامه شما ایمن می‌کند. این unit دارای cgroup اختصاصی خود است و هنگامی که آن cgroup از حد مجاز فراتر رود، هسته سیستم‌عامل چیزی را در داخل آن می‌کشد (kill می‌کند) و بقیه سیستم را دست‌نخورده باقی می‌گذارد. ژورنال این رویداد را ثبت می‌کند:

moli.service: A process of this unit has been killed by the OOM killer.

آن خط را به‌عنوان یک سیگنال برای تعیین اندازه (sizing) در نظر بگیرید. یا صفحات سنگین‌تر از آن چیزی هستند که برنامه‌ریزی کرده‌اید، یا حد مجاز بسیار پایین است. عدد را بر اساس اندازه‌گیری صفحات خود تنظیم کنید که موضوع بخش بعدی است. همان فلگ‌های حسابرسی، سایر سرویس‌های موجود روی سیستم را نیز محدود می‌کنند و محدود کردن حافظه و CPU با systemd برای بقیه آن‌ها نیز کاربرد دارد.

اندازه‌گیری اوج مصرف حافظه توسط خودتان

ارقام منتشرشده از سخت‌افزار و صفحات وب دیگران به‌دست آمده‌اند. اوج مصرف حافظه تعیین می‌کند که آیا سرور شما پایدار می‌ماند یا خیر، و این مقدار کاملاً به آنچه بارگذاری می‌کنید بستگی دارد. پیش از تعیین ابعاد سرور، اندازه‌گیری کنید.

برای دریافت‌های تک‌مرحله‌ای (one-shot)، از باینری time استفاده کنید که گزارش بسیار دقیق‌تری نسبت به دستور داخلی (builtin) هم‌نام خود در 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 به‌دست آید. این دستور را روی 10 صفحه‌ای که agent شما واقعاً بازدید می‌کند اجرا کنید (نه روی example.com) و به‌جای میانگین، بدترین نتیجه را نگه دارید، زیرا OOM killer به اوج‌های مصرف واکنش نشان می‌دهد.

برای سرویس، شمارنده‌ای را بخوانید که هسته سیستم‌عامل از قبل برای cgroup آن نگهداری می‌کند:

cat /sys/fs/cgroup/system.slice/moli.service/memory.peak
systemd-cgtop -m

memory.peak یک شمارش بایت است و نشان‌دهنده بالاترین حد مصرف (high-water mark) از زمان آخرین راه‌اندازی unit است، بنابراین با restart کردن، این مقدار بازنشانی می‌شود. این همان رقمی است که MemoryMax باید بالاتر از آن قرار بگیرد، به‌طوری که فضایی نیز برای سنگین‌ترین صفحه‌ای که هنوز بازدید نکرده‌اید، باقی بماند. systemd-cgtop -m میزان مصرف لحظه‌ای هر unit را نشان می‌دهد که سریع‌ترین راه برای تشخیص این است که کدام سرویس در حال حاضر پرمصرف‌ترین سرویس روی سرور است.

Moli کجا شکست می‌خورد و چه زمانی همچنان به Chrome نیاز دارید؟

این پروژه همچنین یک بنچمارک شامل 1,308 وظیفهٔ خودکارسازی مرورگر قابل‌مقایسه اجرا می‌کند و امتیاز چندین موتور را منتشر می‌سازد.

ChartLexbench headless browser suite, 1,308 tasks, figures published by the Moli project
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
  }
]

در میان آن 5 موتور، Moli 0.1.1 توانست 81.88 درصد از وظایف را تکمیل کند و Chrome، که موتور مرجع است، 99.85 درصد را به پایان رساند. از آنجا که این پروژه خودش را با مجموعه تست‌های خودش ارزیابی کرده است، آن را به عنوان یک ادعا در نظر بگیرید، نه یک نتیجهٔ مستقل.

برداشت کاربردی از این موضوع ساده است. تقریباً از هر پنج وظیفه، یکی در Moli شکست می‌خورد که Chrome آن را تکمیل می‌کند. اگر عامل (agent) شما از مجموعه صفحات ثابتی بازدید می‌کند که تحت کنترل شما هستند، این نسبت اطلاعات کمی به شما می‌دهد؛ زیرا صفحات شما یا کار می‌کنند یا نمی‌کنند و می‌توانید همین امروز بعدازظهر این موضوع را متوجه شوید. اگر عامل شما در وب آزاد جستجو می‌کند، این یک نرخ شکست واقعی است که باید برای آن برنامه‌ریزی کنید.

آنچه شکست می‌خورد، بر اساس محدودهٔ اعلام‌شدهٔ پروژه قابل پیش‌بینی است:

  • برنامه‌هایی که رابط کاربری خود را به جای DOM در یک عنصر Canvas ترسیم می‌کنند، زیرا دقت Canvas صراحتاً خارج از محدودهٔ پروژه است.
  • هر چیزی که به WebGL یا ترکیب‌کننده (compositor) GPU نیاز دارد، زیرا هیچ ترکیب‌کنندهٔ GPU وجود ندارد.
  • ویدیوهای دارای محافظت DRM و پخش رسانه‌ای سنگین.
  • تست‌های بصری که اسکرین‌شات‌های دقیق پیکسلی را با Chrome مقایسه می‌کنند، زیرا برابری با Chrome هدف این پروژه نیست.

رقم دیگری که پروژه ذکر می‌کند، یعنی موفقیت در 1.612 میلیون تست پلتفرم وب، بیانیه‌ای دربارهٔ پوشش استانداردها است. این یک تضمین دربارهٔ سایت‌هایی که عامل شما بازدید می‌کند نیست. یک صفحه می‌تواند فقط از استانداردهای کاملاً پشتیبانی‌شده استفاده کند و همچنان در یک بررسی ربات (bot check) شکست بخورد، و هیچ امتیاز موتوری این مورد را پوشش نمی‌دهد.

بنابراین، قابلیت بازگشت به حالت جایگزین (fallback) را در طراحی خود حفظ کنید. ابتدا هر URL را به Moli بفرستید. زمانی که یک صفحه خالی برمی‌گردد یا یک selector هرگز ظاهر نمی‌شود، آن URL خاص را دوباره با Playwright و با استفاده از Chrome واقعی، روی یک ماشین بزرگ‌تر یا در زمان‌بندی خاصی که در آن یک پردازش 773 MiB مقرون‌به‌صرفه است، امتحان کنید. اکثر عامل‌ها بیشترین زمان خود را در صفحات معمولی صرف می‌کنند، بنابراین موتور سبک حجم کار را بر عهده می‌گیرد و موتور سنگین و گران‌قیمت، موارد خاص و دشوار را مدیریت می‌کند.

FAQ

آیا Moli می‌تواند جایگزین headless Chrome برای ایجنت من باشد؟

برای خواندن صفحات، استخراج متن و کلیک‌های معمولی، معمولاً بله. در بنچمارک اختصاصی این پروژه که شامل 1308 تسک است، این ابزار به نرخ موفقیت 81.88 درصد در مقابل 99.85 درصد برای Chrome دست یافته است؛ بنابراین از هر 5 تسک، حدود 1 تسک به قابلیتی نیاز دارد که Moli فاقد آن است. برنامه‌های رندر شده با Canvas، WebGL و ویدیوهای دارای DRM از جمله موارد شناخته‌شده‌ای هستند که در آن‌ها ضعف دارد. برای این URLها، به‌جای بازگرداندن کل سیستم، آن‌ها را به یک Chrome واقعی هدایت کنید.

Moli روی یک VPS به چه مقدار RAM نیاز دارد؟

این پروژه میانگین RSS برابر با 73 MiB را در یک crawl شامل 192 URL و حداکثر PSS برابر با 102.46 MiB را در یک نمونه از اجرای ایجنت گزارش کرده است، در حالی که این مقدار برای headless Chrome به‌طور میانگین 773 MiB است. این اعداد مربوط به مستندات خود پروژه است. برای استفاده موردی، میزان مصرف خود را با /usr/bin/time -v در اطراف یک فراخوانی moli fetch اندازه‌گیری کنید، یا برای سرویس، /sys/fs/cgroup/system.slice/moli.service/memory.peak را بخوانید و سپس MemoryMax را روی مقداری بالاتر از بدترین عددی که مشاهده کرده‌اید، تنظیم کنید.

آیا باز گذاشتن پورت 9222 روی اینترنت امن است؟

خیر. پروتکل CDP فاقد احراز هویت است؛ بنابراین هر کسی که به این پورت دسترسی داشته باشد، می‌تواند مرورگر شما را کنترل کرده و به هر چیزی که مرورگر به آن دسترسی دارد، نفوذ کند. پورت را روی --host 127.0.0.1 نگه دارید و از طریق یک SSH tunnel یا یک رابط VPN خصوصی، از دستگاه دیگری به endpoint متصل شوید. اگر مجبور به bind کردن روی آدرس دیگری هستید، آن را روی یک رابط خصوصی قرار داده و دسترسی را با فایروال کنترل کنید.

چرا اسکرین‌شات من خالی است یا کلیک‌هایم به هدف نمی‌خورند؟

Layout به‌صورت پیش‌فرض غیرفعال است. در فایل README، سیاست پیش‌فرض LayoutPolicy::Mock ذکر شده است؛ بنابراین هندسه عناصر واقعی نیست و هر چیزی که به موقعیت یک کادر در صفحه وابسته باشد، کار نخواهد کرد. سرور را با moli serve --layout راه‌اندازی کنید یا --layout را به moli fetch اضافه کنید تا اسکرین‌شات و مسیرهای مختصاتی شروع به کار کنند. تصاویر گمشده مربوط به فلگ متفاوتی هستند: --resource.

کدام نسخه از Moli را باید نصب کنم؟

یک نسخه را انتخاب و آن را یادداشت کنید. تا اوت 2026، نسخه فعلی 1.0.1 است، در حالی که ارقام بنچمارک منتشر شده توسط پروژه بر اساس نسخه 0.1.1 اندازه‌گیری شده‌اند؛ بنابراین هنگام مقایسه نتایج با دیگران، این دو نسخه قابل جایگزینی نیستند. فایل moli-x86_64-unknown-linux-gnu.tar.gz مربوط به آن تگ را دانلود کرده و به‌جای تکیه بر shell installer (که به‌جای تگ مورد نظر شما، جدیدترین نسخه را نصب می‌کند)، باینری را شخصاً نصب کنید و سپس با moli --version آن را تأیید نمایید.