حالت بدون سر کروم ارتقا یافته است: معرفی --headless=new

حالت بدون سر کروم بسیار بهتر شده است!

پیتر کویتک
Peter Kvitek

حالت بدون سر کروم بسیار بهتر شده است! این مقاله مروری بر تلاش‌های مهندسی اخیر برای مفیدتر کردن Headless برای توسعه‌دهندگان با نزدیک‌تر کردن Headless به حالت عادی «هدفول» کروم ارائه می‌کند.

زمینه

در سال 2017 ، کروم 59 حالت به اصطلاح Headless را معرفی کرد که به شما امکان می دهد مرورگر را در محیطی بدون نظارت و بدون هیچ گونه رابط کاربری قابل مشاهده ای اجرا کنید. در اصل، اجرای کروم بدون کروم!

حالت بدون سر یک انتخاب محبوب برای اتوماسیون مرورگر از طریق پروژه هایی مانند Puppeteer یا ChromeDriver است. در اینجا یک نمونه حداقل خط فرمان از استفاده از حالت Headless برای ایجاد یک فایل PDF از یک URL داده شده است:

chrome --headless --print-to-pdf https://developer.chrome.com/

چه چیز جدیدی در Headless وجود دارد؟

قبل از اینکه به بهبودهای اخیر Headless بپردازیم، مهم است که بدانیم Headless "قدیمی" چگونه کار می کرد. قطعه خط فرمانی که قبلا نشان دادیم از پرچم خط فرمان --headless استفاده می کند که نشان می دهد Headless فقط یک حالت عملکرد مرورگر معمولی کروم است. شاید جای تعجب باشد که این در واقع درست نبود. از نظر فنی، Headless قدیمی یک پیاده سازی جداگانه و جایگزین مرورگر بود که اتفاقاً به عنوان بخشی از همان باینری کروم ارسال شد. هیچ یک از کدهای مرورگر کروم را در //chrome به اشتراک نمی گذارد.

همانطور که ممکن است تصور کنید، پیاده سازی و نگهداری این مرورگر Headless مجزا با هزینه های مهندسی زیادی همراه بود - اما این تنها مشکل نبود. از آنجایی که Headless یک پیاده‌سازی جداگانه بود، باگ‌ها و ویژگی‌های خاص خود را داشت که در Chrome headful وجود نداشت. این وضعیت گیج‌کننده‌ای ایجاد کرد که در آن هر تست مرورگر خودکار ممکن است در حالت headful موفق شود اما در حالت Headless شکست بخورد یا برعکس - یک نقطه دردسر بزرگ برای مهندسان اتوماسیون. همچنین هرگونه آزمایش خودکاری را که برای مثال به نصب افزونه مرورگر متکی باشد، مستثنی کرد. همین امر در مورد سایر عملکردهای سطح مرورگر نیز صدق می کند: مگر اینکه Headless پیاده سازی جداگانه خود را داشته باشد، پشتیبانی نمی شود.

در سال 2021، تیم کروم تصمیم گرفت این مشکل را حل کند و حالت‌های Headless و headful را یک‌بار برای همیشه یکی کند.

Chrome Headless جدید دیگر یک پیاده سازی جداگانه مرورگر نیست و اکنون در عوض کد را با کروم به اشتراک می گذارد.

ما خوشحالیم که اعلام کنیم حالت جدید Headless اکنون در Chrome 112 در دسترس است! در این حالت، کروم هیچ پنجره پلتفرمی را ایجاد می کند اما نمایش نمی دهد. همه عملکردهای دیگر، موجود و آینده، بدون محدودیت در دسترس هستند.

Headless جدید را امتحان کنید

برای امتحان حالت جدید Headless، پرچم --headless=new خط فرمان را ارسال کنید:

chrome --headless=new

در حال حاضر، حالت قدیمی Headless همچنان از طریق:

chrome --headless=old

در حال حاضر، ارسال پرچم خط فرمان --headless بدون مقدار صریح همچنان حالت Headless قدیمی را فعال می کند — اما ما قصد داریم به مرور زمان این پیش فرض را به Headless جدید تغییر دهیم.

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

بی سر جدید در بازی عروسکی

برای شرکت در حالت جدید Headless در Puppeteer:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: 'new',
  // `headless: true` (default) enables old Headless;
  // `headless: 'new'` enables new Headless;
  // `headless: false` enables "headful" mode.
});

const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');

// …

await browser.close();

Headless جدید در Selenium-WebDriver

برای استفاده از حالت جدید Headless در Selenium-WebDriver:

const driver = await env
  .builder()
  .setChromeOptions(options.addArguments('--headless=new'))
  .build();

await driver.get('https://developer.chrome.com/');

// …

await driver.quit();

برای اطلاعات بیشتر، از جمله نمونه هایی با استفاده از زبان های دیگر، به پست وبلاگ تیم سلنیوم مراجعه کنید.

پرچم های خط فرمان خاص بدون سر

پرچم‌های خط فرمان زیر برای حالت جدید Headless در دسترس هستند.

--dump-dom

پرچم --dump-dom DOM سریالی صفحه مورد نظر را در stdout چاپ می کند. در اینجا یک مثال است:

chrome --headless=new --dump-dom https://developer.chrome.com/

توجه داشته باشید که این با چاپ ساده کد منبع HTML متفاوت است (که ممکن است با curl انجام دهید). برای ارائه خروجی --dump-dom , Chrome ابتدا کد HTML را در یک DOM تجزیه می کند، هر <script> را که ممکن است DOM را تغییر دهد اجرا می کند، و سپس آن DOM را دوباره به رشته ای از HTML تبدیل می کند.

--screenshot

پرچم --screenshot یک عکس از صفحه مورد نظر می گیرد و آن را به عنوان screenshot.png در فهرست کاری فعلی ذخیره می کند. این به ویژه در ترکیب با پرچم --window-size مفید است. در اینجا یک مثال است:

chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/

--print-to-pdf

پرچم --print-to-pdf صفحه مورد نظر را به عنوان PDF با نام output.pdf در فهرست کاری فعلی ذخیره می کند. در اینجا یک مثال است:

chrome --headless=new --print-to-pdf https://developer.chrome.com/

به صورت اختیاری، می‌توانید پرچم --no-pdf-header-footer اضافه کنید تا هدر چاپ (با تاریخ و زمان فعلی) و پاورقی (با URL و شماره صفحه) حذف شود.

chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/

--timeout

پرچم --timeout حداکثر زمان انتظار (بر حسب میلی ثانیه) را تعیین می کند که پس از آن محتوای صفحه توسط --dump-dom ، --screenshot و --print-to-pdf ضبط می شود، حتی اگر صفحه همچنان در حال بارگیری باشد.

chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/

پرچم --timeout=5000 به Chrome می گوید که قبل از چاپ PDF حداکثر 5 ثانیه صبر کند. بنابراین، اجرای این فرآیند حداکثر 5 ثانیه طول می کشد.

--virtual-time-budget

--virtual-time-budget امکان سفر در زمان را فراهم می کند! خب تا حدودی زمان مجازی برای هر کد وابسته به زمان (به عنوان مثال، setTimeout / setInterval ) به عنوان یک "سریع به جلو" عمل می کند. مرورگر را مجبور می‌کند تا هر کدام از کدهای صفحه را با بیشترین سرعت ممکن اجرا کند، در حالی که باعث می‌شود صفحه باور کند که زمان واقعاً می‌گذرد.

برای نشان دادن کاربرد آن، این صفحه نمایشی را در نظر بگیرید که با استفاده از setTimeout(fn, 1000) هر ثانیه یک شمارنده را افزایش، ثبت و نمایش می دهد . این هم کد مربوطه:

<output>0</output>
<script>
  const element = document.querySelector('output');
  let counter = 0;
  setInterval(() => {
    counter++;
    console.log(counter);
    element.textContent = counter;
  }, 1_000);
</script>

پس از یک ثانیه، صفحه حاوی "1" است. پس از دو ثانیه، "2"، و غیره. در اینجا نحوه ثبت وضعیت صفحه پس از 42 ثانیه و ذخیره آن به صورت PDF آمده است:

chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time

--allow-chrome-scheme-url

پرچم --allow-chrome-scheme-url برای دسترسی به URL های chrome:// لازم است. این پرچم از Chrome 123 در دسترس است. مثالی در اینجا آمده است:

chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu

اشکال زدایی

از آنجایی که Chrome در حالت Headless عملاً نامرئی است، تشخیص اینکه در صورت بروز مشکل چه اتفاقی می‌افتد ممکن است دشوار به نظر برسد. خوشبختانه، امکان اشکال زدایی Headless Chrome به روشی بسیار شبیه به Chrome headful وجود دارد. ترفند این است که Chrome را در حالت Headless با پرچم خط فرمان --remote-debugging-port راه اندازی کنید.

chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/

این یک URL منحصر به فرد WebSocket را برای stdout چاپ می کند، به عنوان مثال:

DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9

در یک نمونه معمولی هدفول کروم، سپس می‌توانیم از اشکال‌زدایی از راه دور Chrome DevTools برای اتصال به هدف Headless و بررسی آن استفاده کنیم. برای انجام این کار، به chrome://inspect بروید، روی دکمه پیکربندی… کلیک کنید و آدرس IP و شماره پورت را از URL WebSocket وارد کنید. در مثال بالا، من 127.0.0.1:60926 را وارد کردم. روی Done کلیک کنید و می‌بینید که یک Remote Target با تمام برگه‌ها و سایر اهداف فهرست شده در زیر ظاهر می‌شود. بر روی Inspect کلیک کنید و اکنون به Chrome DevTools دسترسی دارید که هدف Headless از راه دور را بررسی می کند، از جمله یک نمای زنده از صفحه !

Chrome DevTools می تواند صفحه هدف Headless از راه دور را بازرسی کند

بازخورد

ما مشتاقانه منتظر شنیدن نظرات شما در مورد حالت جدید Headless هستیم. اگر به مشکلی برخورد کردید، لطفاً آنها را گزارش کنید .