Подтвердить что ты не робот

Можно ли использовать Chrome Head Chrome/Chromium в облачной функции Google?

Есть ли способ запустить Headless Chrome/Chromium в облачной функции Google? Я понимаю, что могу включить и запустить статически скомпилированные двоичные файлы в GCF. Могу ли я получить статически скомпилированную версию Chrome, которая будет работать для этого?

4b9b3361

Ответ 1

Время выполнения Node.js 8 для облачных функций Google теперь включает в себя все необходимые пакеты ОС для запуска Chrome Headless.

Вот пример кода функции HTTP, которая возвращает скриншоты:

Основной файл index.js:

const puppeteer = require('puppeteer');

exports.screenshot = async (req, res) => {
  const url = req.query.url;

  if (!url) {
    return res.send('Please provide URL as GET parameter, for example: <a href="?url=https://example.com">?url=https://example.com</a>');
  }

  const browser = await puppeteer.launch({
    args: ['--no-sandbox']
  });
  const page = await browser.newPage();
  await page.goto(url);
  const imageBuffer = await page.screenshot();
  await browser.close();

  res.set('Content-Type', 'image/png');
  res.send(imageBuffer);
}

и package.json

{
  "name": "screenshot",
  "version": "0.0.1",
  "dependencies": {
    "puppeteer": "^1.6.2"
  }
}

Ответ 2

Я только что развернул функцию GCF с безголовым Chrome. Несколько приемов:

  1. вам нужно статически компилировать Chromium и NSS на Debian 8
  2. вам нужно исправить переменные окружения, чтобы указать на NSS перед запуском Chromium
  3. производительность намного хуже, чем то, что вы получите на AWS Lambda (3+ секунды)

Для 1 вы можете найти множество инструкций в Интернете.

Для 2 код, который я использую, следующий:

static executablePath() {
  let bin = path.join(__dirname, '..', 'bin', 'chromium');
  let nss = path.join(__dirname, '..', 'bin', 'nss', 'Linux3.16_x86_64_cc_glibc_PTH_64_OPT.OBJ');

  if (process.env.PATH === undefined) {
    process.env.PATH = path.join(nss, 'bin');
  } else if (process.env.PATH.indexOf(nss) === -1) {
    process.env.PATH = [path.join(nss, 'bin'), process.env.PATH].join(':');
  }

  if (process.env.LD_LIBRARY_PATH === undefined) {
    process.env.LD_LIBRARY_PATH = path.join(nss, 'lib');
  } else if (process.env.LD_LIBRARY_PATH.indexOf(nss) === -1) {
    process.env.LD_LIBRARY_PATH = [path.join(nss, 'lib'), process.env.LD_LIBRARY_PATH].join(':');
  }

  if (fs.existsSync('/tmp/chromium') === true) {
    return '/tmp/chromium';
  }

  return new Promise(
    (resolve, reject) => {
      try {
        fs.chmod(bin, '0755', () => {
          fs.symlinkSync(bin, '/tmp/chromium'); return resolve('/tmp/chromium');
        });
      } catch (error) {
        return reject(error);
      }
    }
  );
}

При запуске Chrome вам также необходимо использовать несколько необходимых аргументов, а именно:

--disable-dev-shm-usage
--disable-setuid-sandbox
--no-first-run
--no-sandbox
--no-zygote
--single-process

Надеюсь, это поможет.

Ответ 3

Как упоминалось в комментарии, ведется работа над возможным решением для запуска браузера без браузера в облачной функции. Прямо применимое обсуждение: " безгласный хром и aws лямбда" можно прочитать в группах Google.

Ответ 4

Вопрос в. был ли у вас безголовый хром или хром в облачных функциях Firebase... ответ НЕТ! так как проект node.js не будет иметь доступ к исполняемым файлам chrome/chromium и, следовательно, не сработает! (ДОВЕРИЕ МЕНЯ - Я ПРОШЕЛ!).

Лучшим решением является использование пакета Phantom npm, который использует PhantomJS под капотом: https://www.npmjs.com/package/phantom

Документы и информация можно найти здесь:

http://amirraminfar.com/phantomjs-node/#/

или же

https://github.com/amir20/phantomjs-node

На сайте, на котором я пытался просканировать, было реализовано программное обеспечение для очистки экрана, трюк заключается в том, чтобы дождаться загрузки страницы путем поиска ожидаемой строки или соответствия регулярному выражению, то есть я делаю регулярное выражение для a, если вам нужно регулярное выражение любой сложности для вас - свяжитесь с https://AppLogics.uk/ - начиная с 5 фунтов стерлингов (GPB).

здесь приведен фрагмент машинописного текста для вызова http или https:

        const phantom = require('phantom');
        const instance: any = await phantom.create(['--ignore-ssl-errors=yes', '--load-images=no']);
        const page: any = await instance.createPage();
        const status = await page.open('https://somewebsite.co.uk/');
        const content = await page.property('content');

опять же в JavaScript:

        const phantom = require('phantom');
        const instance = yield phantom.create(['--ignore-ssl-errors=yes', '--load-images=no']);
        const page = yield instance.createPage();
        const status = yield page.open('https://somewebsite.co.uk/');
        const content = yield page.property('content');

Это легкий бит! если его статическая страница в значительной степени выполнена, и вы можете анализировать HTML-код в виде пакета cheerio npm: https://github.com/cheeriojs/cheerio - реализация ядра JQuery, предназначенного для серверов!

Однако, если это страница с динамической загрузкой, то есть ленивая загрузка или даже методы скремблирования, вам нужно будет дождаться обновления страницы путем циклирования и вызова page.property('content') и запуска текстового поиска или regex, чтобы узнать, закончилась ли ваша страница.

Я создал общую асинхронную функцию, возвращающую содержимое страницы (как строку) при успешном запуске и выдает исключение при сбое или таймауте. В качестве параметров в качестве параметров используются переменные для страницы, текст (строка для поиска, указывающая на успех), ошибка (строка для указания отказа или null, чтобы не проверять наличие ошибки), и тайм-аут (номер - сам по себе):

Машинопись:

    async function waitForPageToLoadStr(page: any, text: string, error: string, timeout: number): Promise<string> {
        const maxTime = timeout ? (new Date()).getTime() + timeout : null;
        let html: string = '';
        html = await page.property('content');
        async function loop(): Promise<string>{
            async function checkSuccess(): Promise <boolean> {
                html = await page.property('content');
                if (!isNullOrUndefined(error) && html.includes(error)) {
                    throw new Error('Error string found: ${ error }');
                }
                if (maxTime && (new Date()).getTime() >= maxTime) {
                    throw new Error('Timed out waiting for string: ${ text }');
                }
                return html.includes(text)
            }
            if (await checkSuccess()){
                return html;
            } else {
                return loop();
            }                
        }
        return await loop();
    }

JavaScript:

    function waitForPageToLoadStr(page, text, error, timeout) {
            return __awaiter(this, void 0, void 0, function* () {
                const maxTime = timeout ? (new Date()).getTime() + timeout : null;
                let html = '';
                html = yield page.property('content');
                function loop() {
                    return __awaiter(this, void 0, void 0, function* () {
                        function checkSuccess() {
                            return __awaiter(this, void 0, void 0, function* () {
                                html = yield page.property('content');
                                if (!isNullOrUndefined(error) && html.includes(error)) {
                                    throw new Error('Error string found: ${error}');
                                }
                                if (maxTime && (new Date()).getTime() >= maxTime) {
                                    throw new Error('Timed out waiting for string: ${text}');
                                }
                                return html.includes(text);
                            });
                        }
                        if (yield checkSuccess()) {
                            return html;
                        }
                        else {
                            return loop();
                        }
                    });
                }
                return yield loop();
            });
        }

Я лично использовал эту функцию следующим образом:

Машинопись:

    try {
        const phantom = require('phantom');
        const instance: any = await phantom.create(['--ignore-ssl-errors=yes', '--load-images=no']);
        const page: any = await instance.createPage();
        const status = await page.open('https://somewebsite.co.uk/');
        await waitForPageToLoadStr(page, '<div>Welcome to somewebsite</div>', '<h1>Website under maintenance, try again later</h1>', 1000);
    } catch (error) {
        console.error(error);
    }

JavaScript:

    try {
        const phantom = require('phantom');
        const instance = yield phantom.create(['--ignore-ssl-errors=yes', '--load-images=no']);
        const page = yield instance.createPage();
        yield page.open('https://vehicleenquiry.service.gov.uk/');
        yield waitForPageToLoadStr(page, '<div>Welcome to somewebsite</div>', '<h1>Website under maintenance, try again later</h1>', 1000);
    } catch (error) {
        console.error(error);
    }

Счастливый ползающий!