बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले Chrome का इस्तेमाल शुरू करना

बहुत ज़्यादा शब्द हैं, पढ़ा नहीं गया

हेडलेस Chrome की शिपिंग, Chrome 59 में की जा रही है. यह Chrome ब्राउज़र को बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले डिवाइस में चलाने का तरीका है. ज़रूरी है कि Chrome के बिना Chrome को चलाया जा रहा हो! यह कमांड लाइन में, Chromium और Blink रेंडरिंग इंजन की सभी मॉडर्न वेब प्लैटफ़ॉर्म सुविधाएं उपलब्ध कराता है.

यह जानकारी काम की क्यों है?

बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला ब्राउज़र, ऑटोमेटेड टेस्टिंग और सर्वर एनवायरमेंट के लिए एक बेहतरीन टूल है. यहां आपको दिखने वाले यूज़र इंटरफ़ेस (यूआई) शेल की ज़रूरत नहीं होती. उदाहरण के लिए, हो सकता है कि आप किसी असली वेब पेज पर कुछ जांच करना चाहें, उसकी एक PDF बनाना चाहें या सिर्फ़ जांच करना चाहें कि ब्राउज़र किसी यूआरएल को कैसे रेंडर करता है.

बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला ब्राउज़र (सीएलआई) शुरू किया जा रहा है

हेडलेस मोड का इस्तेमाल शुरू करने का सबसे आसान तरीका है कि कमांड लाइन से Chrome बाइनरी को खोलें. अगर आपने Chrome 59 के बाद के वर्शन को इंस्टॉल किया है, तो Chrome को --headless फ़्लैग के साथ शुरू करें:

chrome \
--headless \                   # Runs Chrome in headless mode.
--disable-gpu \                # Temporarily needed if running on Windows.
--remote-debugging-port=9222 \
https://www.chromestatus.com   # URL to open. Defaults to about:blank.

chrome पर क्लिक करने से, वह आपके Chrome के इंस्टॉलेशन की जानकारी देगा. जगह की सटीक जानकारी अलग-अलग प्लैटफ़ॉर्म के हिसाब से अलग-अलग होगी. चूंकि मैं Mac पर हूं, इसलिए मैंने Chrome के हर उस वर्शन के लिए सुविधाजनक उपनाम बनाए हैं जिसे मैंने इंस्टॉल किया है.

अगर आप Chrome के स्टेबल चैनल का इस्तेमाल कर रहे हैं और आपको बीटा वर्शन नहीं मिल पा रहा है, तो हमारा सुझाव है कि आप chrome-canary इस्तेमाल करें:

alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
alias chrome-canary="/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary"
alias chromium="/Applications/Chromium.app/Contents/MacOS/Chromium"

Chrome कैनरी को यहां से डाउनलोड करें.

कमांड-लाइन की सुविधाएं

कुछ मामलों में, हो सकता है कि आपको बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले Chrome को प्रोग्राम के हिसाब से स्क्रिप्ट में बदलने की ज़रूरत न पड़े. कुछ सामान्य टास्क करने के लिए, कुछ काम के कमांड लाइन फ़्लैग हैं.

DOM को प्रिंट करना

--dump-dom फ़्लैग document.body.innerHTML को stdout पर प्रिंट करता है:

    chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/

PDF फ़ाइल बनाएं

--print-to-pdf फ़्लैग, पेज की एक PDF फ़ाइल बनाता है:

chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/

स्क्रीनशॉट लिए जा रहे हैं

किसी पेज का स्क्रीनशॉट लेने के लिए, --screenshot फ़्लैग का इस्तेमाल करें:

chrome --headless --disable-gpu --screenshot https://www.chromestatus.com/

# Size of a standard letterhead.
chrome --headless --disable-gpu --screenshot --window-size=1280,1696 https://www.chromestatus.com/

# Nexus 5x
chrome --headless --disable-gpu --screenshot --window-size=412,732 https://www.chromestatus.com/

--screenshot के साथ चलने पर, मौजूदा डायरेक्ट्री में screenshot.png नाम की फ़ाइल बनेगी. अगर आप पूरे पेज के स्क्रीनशॉट देख रहे हैं, तो चीज़ें ज़्यादा दिलचस्प हैं. डेविड श्नर की एक बेहतरीन ब्लॉग पोस्ट है, जिसमें आप लोगों के बारे में जानकारी देते हैं. अपने-आप स्क्रीनशॉट लेने वाले टूल के तौर पर, बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले Chrome का इस्तेमाल करना लेख पढ़ें.

आरईपीएल मोड (रीड-ईवल-प्रिंट लूप)

--repl फ़्लैग, हेडलेस (सिर्फ़ बैक-एंड पर काम करने की सुविधा देने वाला) मोड में चलता है. इस मोड में, ब्राउज़र में सीधे कमांड लाइन से JS एक्सप्रेशन की जांच की जा सकती है:

$ chrome --headless --disable-gpu --repl --crash-dumps-dir=./tmp https://www.chromestatus.com/
[0608/112805.245285:INFO:headless_shell.cc(278)] Type a Javascript expression to evaluate or "quit" to exit.
>>> location.href
{"result":{"type":"string","value":"https://www.chromestatus.com/features"}}
>>> quit
$

ब्राउज़र यूज़र इंटरफ़ेस (यूआई) के बिना Chrome को डीबग करना है?

जब Chrome को --remote-debugging-port=9222 के साथ चलाया जाता है, तो यह DevTools प्रोटोकॉल के साथ इंस्टेंस शुरू करता है. प्रोटोकॉल का इस्तेमाल, Chrome से संपर्क करने और बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले ब्राउज़र इंस्टेंस को चलाने के लिए किया जाता है. किसी ऐप्लिकेशन को रिमोट तरीके से डीबग करने के लिए, Sublime, VS Code, और नोड जैसे टूल भी इस्तेमाल किए जाते हैं. #synergy

आपके पास पेज देखने के लिए ब्राउज़र यूज़र इंटरफ़ेस (यूआई) नहीं है. इसलिए, किसी दूसरे ब्राउज़र में http://localhost:9222 पर जाएं और देखें कि सब कुछ ठीक से काम कर रहा है या नहीं. आपको ऐसे पेजों की सूची दिखेगी जिन पर क्लिक किया जा सकता है. साथ ही, यह भी देखा जा सकता है कि हेडलेस (सिर्फ़ बैक-एंड पर काम करने की सुविधा देने वाला ऐप्लिकेशन) क्या रेंडर कर रहा है:

DevTools रिमोट
DevTools रिमोट डीबगिंग यूज़र इंटरफ़ेस (यूआई)

यहां से, DevTools की सामान्य सुविधाओं का इस्तेमाल करके, पेज की जांच की जा सकती है, उसे डीबग किया जा सकता है, और उसमें बदलाव किया जा सकता है. अगर हेडलेस (सिर्फ़ बैक-एंड पर काम करने की सुविधा) का इस्तेमाल प्रोग्राम के तौर पर किया जा रहा है, तो यह पेज, डीबग करने वाला एक बेहतरीन टूल है. इसकी मदद से, ब्राउज़र के साथ बातचीत करते हुए, सभी रॉ DevTools प्रोटोकॉल कमांड को देखा जा सकता है.

प्रोग्रामैटिक तरीके से (नोड) का इस्तेमाल करना

कठपुतली

Puppeteer एक नोड लाइब्रेरी है, जिसे Chrome टीम ने डेवलप किया है. यह बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले Chrome को कंट्रोल करने के लिए, हाई-लेवल एपीआई उपलब्ध कराता है. यह Phantom और NightmareJS जैसी अन्य ऑटोमैटिक टेस्टिंग लाइब्रेरी की तरह ही है. हालांकि, यह सिर्फ़ Chrome के सबसे नए वर्शन पर काम करता है.

अन्य चीज़ों के साथ-साथ, Puppeteer का इस्तेमाल आसानी से स्क्रीनशॉट लेने, PDF बनाने, पेजों पर नेविगेट करने, और उन पेजों के बारे में जानकारी फ़ेच करने के लिए भी किया जा सकता है. अगर आपको ब्राउज़र की टेस्टिंग अपने-आप होने की सुविधा चाहिए, तो मेरा सुझाव है कि आप इसकी लाइब्रेरी को चुनें. यह DevTools प्रोटोकॉल की जटिलताओं को छिपा देता है. साथ ही, Chrome का डीबग इंस्टेंस लॉन्च करने जैसे ग़ैर-ज़रूरी कामों को पूरा करता है.

इसे इंस्टॉल करें:

npm i --save puppeteer

उदाहरण - उपयोगकर्ता एजेंट को प्रिंट करें

const puppeteer = require('puppeteer');

(async() => {
  const browser = await puppeteer.launch();
  console.log(await browser.version());
  await browser.close();
})();

उदाहरण - पेज का स्क्रीनशॉट लेना

const puppeteer = require('puppeteer');

(async() => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://www.chromestatus.com', {waitUntil: 'networkidle2'});
  await page.pdf({path: 'page.pdf', format: 'A4'});

  await browser.close();
})();

पूरे एपीआई के बारे में ज़्यादा जानने के लिए, Puppeteer का दस्तावेज़ देखें.

सीआरआई लाइब्रेरी

chrome-remote-interface, Puppeteer के API के मुकाबले निचले स्तर की लाइब्रेरी है. अगर आपको मेटल के करीब रहना है और सीधे DevTools प्रोटोकॉल का इस्तेमाल करना है, तो मेरा सुझाव है.

Chrome लॉन्च करना

chrome-remote-interface आपके लिए Chrome लॉन्च नहीं करता है, इसलिए आपको इसका ध्यान खुद रखना होगा.

सीएलआई सेक्शन में, हमने --headless --remote-debugging-port=9222 का इस्तेमाल करके Chrome को मैन्युअल तरीके से शुरू किया. हालांकि, परीक्षणों को पूरी तरह से ऑटोमेट करने के लिए, हो सकता है कि आप अपने ऐप्लिकेशन से Chrome को बढ़ाना चाहें.

child_process का इस्तेमाल करने का एक तरीका है:

const execFile = require('child_process').execFile;

function launchHeadlessChrome(url, callback) {
  // Assuming MacOSx.
  const CHROME = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome';
  execFile(CHROME, ['--headless', '--disable-gpu', '--remote-debugging-port=9222', url], callback);
}

launchHeadlessChrome('https://www.chromestatus.com', (err, stdout, stderr) => {
  ...
});

हालांकि, अगर आपको कई प्लैटफ़ॉर्म पर काम करने वाला पोर्टेबल टूल चाहिए, तो आपको परेशानी हो सकती है. बस Chrome के लिए हार्ड कोड किए गए पाथ को देखें :(

ChromeLauncher का इस्तेमाल किया जा रहा है

Lighthouse आपके वेब ऐप्लिकेशन की क्वालिटी टेस्ट करने के लिए एक शानदार टूल है. Chrome को लॉन्च करने के लिए, एक मज़बूत मॉड्यूल को लाइटहाउस में बनाया गया है. अब इसे अलग से इस्तेमाल करने के लिए तैयार किया गया है. chrome-launcher एनपीएम मॉड्यूल यह पता लगाएगा कि Chrome कहां इंस्टॉल है. इसके बाद, डीबग इंस्टेंस सेट अप करेगा, ब्राउज़र लॉन्च करेगा, और आपका प्रोग्राम पूरा हो जाने पर बंद कर देगा. सबसे अच्छी बात यह है कि यह नोड से क्रॉस-प्लैटफ़ॉर्म पर काम करता है!

डिफ़ॉल्ट रूप से, chrome-launcher Chrome कैनरी को लॉन्च करने की कोशिश करेगा (अगर यह इंस्टॉल है), लेकिन आप इसे बदलकर मैन्युअल रूप से यह चुन सकते हैं कि किस Chrome का इस्तेमाल करना है. इसका इस्तेमाल करने के लिए, पहले npm से इंस्टॉल करें:

npm i --save chrome-launcher

उदाहरण - बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला ब्राउज़र लॉन्च करने के लिए, chrome-launcher का इस्तेमाल किया जा रहा है

const chromeLauncher = require('chrome-launcher');

// Optional: set logging level of launcher to see its output.
// Install it using: npm i --save lighthouse-logger
// const log = require('lighthouse-logger');
// log.setLevel('info');

/**
 * Launches a debugging instance of Chrome.
 * @param {boolean=} headless True (default) launches Chrome in headless mode.
 *     False launches a full version of Chrome.
 * @return {Promise<ChromeLauncher>}
 */
function launchChrome(headless=true) {
  return chromeLauncher.launch({
    // port: 9222, // Uncomment to force a specific port of your choice.
    chromeFlags: [
      '--window-size=412,732',
      '--disable-gpu',
      headless ? '--headless' : ''
    ]
  });
}

launchChrome().then(chrome => {
  console.log(`Chrome debuggable on port: ${chrome.port}`);
  ...
  // chrome.kill();
});

इस स्क्रिप्ट को चलाने से कुछ नहीं होता है, लेकिन आपको about:blank लोड करने वाले टास्क मैनेजर में Chrome के सक्रिय होने का एक इंस्टेंस दिखना चाहिए. ध्यान रखें कि इसमें कोई भी ब्राउज़र यूज़र इंटरफ़ेस (यूआई) नहीं होगा. हमारे पास हेडलेस (सिर्फ़ बैक-एंड पर काम करने की सुविधा) है.

ब्राउज़र को कंट्रोल करने के लिए, हमें DevTools प्रोटोकॉल की ज़रूरत है!

पेज के बारे में जानकारी पाना

चलिए, लाइब्रेरी इंस्टॉल करते हैं:

npm i --save chrome-remote-interface
उदाहरण

उदाहरण - उपयोगकर्ता एजेंट को प्रिंट करें

const CDP = require('chrome-remote-interface');

...

launchChrome().then(async chrome => {
  const version = await CDP.Version({port: chrome.port});
  console.log(version['User-Agent']);
});

नतीजे इस तरह के होते हैं: HeadlessChrome/60.0.3082.0

उदाहरण - देखें कि साइट का वेब ऐप्लिकेशन मेनिफ़ेस्ट है या नहीं

const CDP = require('chrome-remote-interface');

...

(async function() {

const chrome = await launchChrome();
const protocol = await CDP({port: chrome.port});

// Extract the DevTools protocol domains we need and enable them.
// See API docs: https://chromedevtools.github.io/devtools-protocol/
const {Page} = protocol;
await Page.enable();

Page.navigate({url: 'https://www.chromestatus.com/'});

// Wait for window.onload before doing stuff.
Page.loadEventFired(async () => {
  const manifest = await Page.getAppManifest();

  if (manifest.url) {
    console.log('Manifest: ' + manifest.url);
    console.log(manifest.data);
  } else {
    console.log('Site has no app manifest');
  }

  protocol.close();
  chrome.kill(); // Kill Chrome.
});

})();

उदाहरण - DOM API का इस्तेमाल करके पेज का <title> निकालें.

const CDP = require('chrome-remote-interface');

...

(async function() {

const chrome = await launchChrome();
const protocol = await CDP({port: chrome.port});

// Extract the DevTools protocol domains we need and enable them.
// See API docs: https://chromedevtools.github.io/devtools-protocol/
const {Page, Runtime} = protocol;
await Promise.all([Page.enable(), Runtime.enable()]);

Page.navigate({url: 'https://www.chromestatus.com/'});

// Wait for window.onload before doing stuff.
Page.loadEventFired(async () => {
  const js = "document.querySelector('title').textContent";
  // Evaluate the JS expression in the page.
  const result = await Runtime.evaluate({expression: js});

  console.log('Title of page: ' + result.result.value);

  protocol.close();
  chrome.kill(); // Kill Chrome.
});

})();

सेलेनियम, WebDriver, और ChromeDriver का इस्तेमाल करना

इस समय, सेलेनियम Chrome का पूरा इंस्टेंस खोलता है. दूसरे शब्दों में कहें, तो यह अपने-आप काम करने वाला समाधान है लेकिन पूरी तरह से बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला ब्राउज़र है. हालांकि, थोड़ी-बहुत मेहनत करके, बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले Chrome को चलाने के लिए सेलेनियम को कॉन्फ़िगर किया जा सकता है. अगर आपको सेटिंग खुद सेट अप करने के बारे में सभी निर्देश चाहिए, तो हमारा सुझाव है कि आप हेडलेस Chrome के साथ सेलेनियम का इस्तेमाल करें. हालाँकि, शुरुआत करने के लिए, हमने यहां कुछ उदाहरण दिए हैं.

ChromeDriver का इस्तेमाल करना

ChromeDriver 2.32 में, Chrome 61 का इस्तेमाल किया जाता है और यह हेडलेस (सिर्फ़ बैक-एंड पर काम करने की सुविधा) Chrome के साथ अच्छे से काम करता है.

इंस्टॉल करें:

npm i --save-dev selenium-webdriver chromedriver

उदाहरण:

const fs = require('fs');
const webdriver = require('selenium-webdriver');
const chromedriver = require('chromedriver');

const chromeCapabilities = webdriver.Capabilities.chrome();
chromeCapabilities.set('chromeOptions', {args: ['--headless']});

const driver = new webdriver.Builder()
  .forBrowser('chrome')
  .withCapabilities(chromeCapabilities)
  .build();

// Navigate to google.com, enter a search.
driver.get('https://www.google.com/');
driver.findElement({name: 'q'}).sendKeys('webdriver');
driver.findElement({name: 'btnG'}).click();
driver.wait(webdriver.until.titleIs('webdriver - Google Search'), 1000);

// Take screenshot of results page. Save to disk.
driver.takeScreenshot().then(base64png => {
  fs.writeFileSync('screenshot.png', new Buffer(base64png, 'base64'));
});

driver.quit();

WebDriverIO का इस्तेमाल करना

WebDriverIO, Selenium WebDriver के साथ बेहतर लेवल का एपीआई है.

इंस्टॉल करें:

npm i --save-dev webdriverio chromedriver

उदाहरण: chromestatus.com पर सीएसएस की सुविधाओं को फ़िल्टर करें

const webdriverio = require('webdriverio');
const chromedriver = require('chromedriver');

const PORT = 9515;

chromedriver.start([
  '--url-base=wd/hub',
  `--port=${PORT}`,
  '--verbose'
]);

(async () => {

const opts = {
  port: PORT,
  desiredCapabilities: {
    browserName: 'chrome',
    chromeOptions: {args: ['--headless']}
  }
};

const browser = webdriverio.remote(opts).init();

await browser.url('https://www.chromestatus.com/features');

const title = await browser.getTitle();
console.log(`Title: ${title}`);

await browser.waitForText('.num-features', 3000);
let numFeatures = await browser.getText('.num-features');
console.log(`Chrome has ${numFeatures} total features`);

await browser.setValue('input[type="search"]', 'CSS');
console.log('Filtering features...');
await browser.pause(1000);

numFeatures = await browser.getText('.num-features');
console.log(`Chrome has ${numFeatures} CSS features`);

const buffer = await browser.saveScreenshot('screenshot.png');
console.log('Saved screenshot...');

chromedriver.stop();
browser.end();

})();

अतिरिक्त संसाधन

यहां कुछ ऐसे संसाधन दिए गए हैं जिनसे आपको मदद मिल सकती है:

Docs

टूल

  • chrome-remote-इंटरफ़ेस - नोड मॉड्यूल, जो DevTools प्रोटोकॉल को रैप करता है
  • Lighthouse - वेब ऐप्लिकेशन की क्वालिटी की जांच करने के लिए अपने-आप काम करने वाला टूल; जो प्रोटोकॉल का बहुत ज़्यादा इस्तेमाल करता है
  • chrome-लॉन्चर - Chrome लॉन्च करने के लिए नोड मॉड्यूल, ऑटोमेशन के लिए तैयार है

डेमो

  • "The Headless Web" - पॉल किनलान का शानदार ब्लॉग पोस्ट है, जिसमें api.ai के साथ हेडलेस (सिर्फ़ बैक-एंड पर काम करने की सुविधा) इस्तेमाल करने के बारे में बताया गया है.

अक्सर पूछे जाने वाले सवाल

क्या मुझे --disable-gpu फ़्लैग की ज़रूरत है?

सिर्फ़ Windows पर. अन्य प्लैटफ़ॉर्म को अब इसकी ज़रूरत नहीं है. कुछ गड़बड़ियों को ठीक करने के लिए, --disable-gpu फ़्लैग का इस्तेमाल किया जाता है. आपको Chrome के आने वाले वर्शन में इस फ़्लैग की ज़रूरत नहीं होगी. ज़्यादा जानकारी के लिए, crbug.com/737678 पर जाएं.

क्या मुझे अब भी Xvfb की ज़रूरत है?

नहीं. बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला Chrome विंडो का इस्तेमाल नहीं करता है. इसलिए, अब Xvfb जैसे डिसप्ले सर्वर की ज़रूरत नहीं है. इसके बिना भी, ऑटोमेटेड टेस्ट किए जा सकते हैं.

Xvfb क्या है? Xvfb, यूनिक्स जैसे सिस्टम के लिए इन-मेमोरी डिसप्ले सर्वर है, जिसकी मदद से आप अटैच किए गए फ़िज़िकल डिसप्ले के बिना ग्राफ़िकल ऐप्लिकेशन (जैसे कि Chrome) चला सकते हैं. कई लोग "हेडलेस" टेस्टिंग के लिए, Chrome के पुराने वर्शन चलाने के लिए Xvfb का इस्तेमाल करते हैं.

मैं ऐसा Docker कंटेनर कैसे बनाऊं जो बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला Chrome चलाता है?

लाइट हाउस-सीआई देखें. इसमें Dockerfile का उदाहरण है, जो node:8-slim को बेस इमेज के तौर पर इस्तेमाल करता है. साथ ही, यह App Engine Flex पर Lighthouse चलाता है.

क्या इसे Selenium / WebDriver / ChromeDriver के साथ इस्तेमाल किया जा सकता है?

हाँ। Selenium, WebDriver, और ChromeDriver का इस्तेमाल करना लेख पढ़ें.

यह PhantomJS के साथ कैसे जुड़ा है?

बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला Chrome, PhantomJS जैसे टूल जैसा ही है. दोनों का इस्तेमाल, हेडलेस (सिर्फ़ बैक-एंड पर काम करने की सुविधा) एनवायरमेंट में, ऑटोमेटेड टेस्टिंग के लिए किया जा सकता है. दोनों के बीच मुख्य अंतर यह है कि Phantom, रेंडरिंग इंजन के रूप में, WebKit के पुराने वर्शन का इस्तेमाल करता है. वहीं, Headless Chrome, Blink के सबसे नए वर्शन का इस्तेमाल करता है.

इस समय, Phantom, DevTools प्रोटोकॉल की तुलना में उच्च लेवल का API भी उपलब्ध करवाता है.

मैं गड़बड़ियों की शिकायत कहां करूं?

बिना ग्राफ़िक यूज़र इंटरफ़ेस वाले Chrome में गड़बड़ी होने पर, उन्हें crbug.com पर दर्ज करें.

DevTools प्रोटोकॉल में मौजूद गड़बड़ियों के लिए, github.com/ChromeDevTools/devtools-protocol पर जाकर उनकी शिकायत करें.