מצב 'דפדפן ללא GUI' מקבל שדרוג: --headless=new

מצב 'דפדפן ללא GUI' של Chrome השתפר מאוד!

Peter Kvitek
Peter Kvitek

מצב 'דפדפן ללא GUI' של Chrome השתפר מאוד! במאמר הזה מוצגת סקירה כללית של המאמצים ההנדסיים שבוצעו לאחרונה כדי ש-Headless יהיה שימושי יותר למפתחים. לשם כך, צריך לקרב את Headless למצב "headful" הרגיל של Chrome.

רקע

ב-2017 השקנו את Chrome 59 שנקרא 'מצב 'ללא GUI'. מצב זה מאפשר לכם להפעיל את הדפדפן בסביבה ללא השגחה וללא ממשק משתמש גלוי. למעשה, הפעלת Chrome ללא Chrome!

מצב 'דפדפן ללא GUI' הוא בחירה פופולרית לאוטומציה של הדפדפן בפרויקטים כמו Puppeteer או ChromeDriver. הנה דוגמה מינימלית של שורת פקודה לשימוש במצב 'דפדפן ללא GUI' כדי ליצור קובץ PDF של כתובת URL נתונה:

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

מה חדש באפליקציית Headless?

לפני שנתעמק בשיפורים שבוצעו לאחרונה באפליקציית Headless, חשוב להבין איך הגרסה הישנה של Headless עבדה. קטע הקוד של שורת הפקודה שהצגנו קודם לכן משתמש בסימון שורת הפקודה --headless, ומרמז ש-Headless הוא רק מצב פעולה של דפדפן Chrome הרגיל. אולי באופן מפתיע, זה לא היה נכון. מבחינה טכנית, הגרסה הקודמת של Headless הייתה הטמעה נפרדת של דפדפן חלופי, שנשלחה כחלק מאותו קובץ בינארי של Chrome. הוא לא משתף את הקוד של דפדפן Chrome ב-//chrome.

כפי שאולי חשבתם, ההטמעה והתחזוקה של דפדפן Headless הנפרד הזה היו כרוך בהרבה תקורה של הנדסיות, אבל זו לא הייתה הבעיה היחידה. אפליקציית Headless הייתה הטמעה נפרדת, ולכן היו לה באגים ותכונות שלא היו קיימות ב-Chrome המתקדם. המצב הזה יצר מצב מבלבל שבו כל בדיקת דפדפן אוטומטית עלולה לעבור במצב 'גרפיקה', אבל להיכשל במצב 'דפדפן ללא GUI', או להפך – בעיה חמורה למהנדסי האוטומציה. לדוגמה, היא גם לא כללה בדיקות אוטומטיות שהסתמכו על התקנה של תוסף לדפדפן. אותו עיקרון חל על כל פונקציונליות אחרת ברמת הדפדפן: אלא אם ל-Headless הייתה הטמעה נפרדת ונפרדת שלה, היא לא נתמכת.

בשנת 2021, צוות Chrome בחר לפתור את הבעיה הזו, ולאחד בין מצבי Headless ומצב GUI אחת ולתמיד.

אפליקציית Chrome Headless החדשה כבר לא הטמעה נפרדת של דפדפן, ועכשיו היא משתפת קוד עם Chrome.

אנחנו שמחים להודיע שמצב 'דפדפן ללא GUI' זמין עכשיו ב-Chrome 112. במצב זה, Chrome יוצר חלונות של פלטפורמה אבל לא מציג אותם. כל שאר הפונקציות, הקיימות והעתידיות, זמינות ללא מגבלות.

כדאי לנסות את אפליקציית Headless החדשה

כדי לנסות את מצב 'דפדפן ללא GUI', מעבירים את הדגל --headless=new של שורת הפקודה:

chrome --headless=new

נכון לעכשיו, המצב הישן של 'דפדפן ללא GUI' עדיין זמין דרך:

chrome --headless=old

נכון לעכשיו, העברת סימון שורת הפקודה --headless ללא ערך מפורש עדיין מפעילה את המצב הישן של 'דפדפן ללא GUI'. עם זאת, אנחנו מתכננים לשנות את ברירת המחדל הזו לגרסה החדשה של אפליקציית 'דפדפן ללא GUI'.

אנחנו מתכננים להסיר לחלוטין את הגרסה הישנה של Headless מהקובץ הבינארי של Chrome ולהפסיק את התמיכה במצב הזה ב-Puppeteer בהמשך השנה. כחלק מההסרה, הגרסה הישנה של Headless זמינה כקבצים בינאריים נפרדים למשתמשים שעדיין לא יכולים לשדרג.

חדש במשחק Puppeteer 'ללא ממשק גרפי'

כדי להצטרף למצב 'דפדפן ללא GUI' החדש ב-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();

דפדפן חדש ללא ממשק גרפי ב-Selenium-WebDriver

כדי להשתמש במצב 'דפדפן ללא GUI' החדש ב-Selenium-WebDriver:

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

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

// …

await driver.quit();

מידע נוסף זמין בפוסט בבלוג של צוות Selenium, כולל דוגמאות לשימוש בקישורי שפות אחרות.

תכונות ניסיוניות בשורת הפקודה ללא GUI

הסימונים הבאים של שורת הפקודה זמינים במצב 'דפדפן ללא GUI'.

--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 להמתין עד 5 שניות לפני הדפסת קובץ ה-PDF. לכן, הרצת התהליך הזה נמשכת עד 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://. הסימון הזה זמין החל מגרסה 123 של Chrome. לדוגמה:

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

ניפוי באגים

מכיוון ש-Chrome בלתי נראה בפועל במצב 'דפדפן ללא GUI', ייתכן שיהיה קשה להבין מה קורה אם יש בעיות. למרבה המזל, ניתן לנפות באגים ב-Headless Chrome בדרך שדומה מאוד ל-Chrome מבוסס ממשק גרפי. הטריק הוא להפעיל את Chrome במצב 'דפדפן ללא GUI' עם הדגל --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 עם ממשק גרפי, אנחנו יכולים להשתמש בניפוי באגים מרחוק של כלי הפיתוח ל-Chrome כדי להתחבר ליעד של Headless ולבדוק אותו. כדי לעשות את זה, עוברים אל chrome://inspect, לוחצים על הלחצן הגדרה... ומזינים את כתובת ה-IP ואת מספר היציאה מכתובת ה-URL של ה-WebSocket. בדוגמה שלמעלה הזנתי 127.0.0.1:60926. לוחצים על סיום. היעד המרוחק אמור להופיע עם כל הכרטיסיות והיעדים האחרים שלו שמפורטים למטה. לוחצים על inspect ויש לכם עכשיו גישה לכלי הפיתוח ל-Chrome שבודקים את היעד המרוחק ללא Headless, inspect!

כלי הפיתוח ל-Chrome יכולים לבדוק דף יעד מרוחק של Headless

משוב

נשמח לקבל את המשוב שלך על מצב 'דפדפן ללא GUI'. נתקלתם בבעיות? אפשר לדווח עליהן.