CoderCastrov logo
CoderCastrov
Парсер

Как запустить Pyppeteer на Google App Engine Flex

Как запустить Pyppeteer на Google App Engine Flex
просмотров
3 мин чтение
#Парсер

**TL;DR: **Я потратил целый день на исследование того, как запустить Pyppeteer в среде Google App Engine Flex (конкретно). Не найдя решения в Интернете и просто используя здравый смысл, я пишу статью о решении, которую я хотел бы найти. Перейдите к решению ниже.

Немного фоновой информации

Puppeteer - это API без графического интерфейса Chromium, созданный для NodeJS. Pyppeteer - это Python 3-порт Puppeteer с приблизительной совместимостью.

Он в первую очередь используется для модульного тестирования фронтенда, но также может быть использован как автоматизированный виртуальный браузер, из которого можно извлекать ценные данные.

Я - инженер данных в Adtech (читай: backend-инженер, увлекающийся Big Data), и часть текущего проекта, над которым я работаю, включает извлечение данных из собственных платформ, часто без наличия API или с чем-то, едва похожим на него.

В большинстве случаев достаточно просто разобрать фронтенд, извлечь XHR в инструментах разработчика и использовать их в библиотеке requests Python. С помощью простой аутентификации через requests и куки получение необходимых данных тривиально.

Редко возникают проблемы, но часто, если они возникают, это либо очень безопасный фронтенд с раздражающими токенами времени, либо устаревшая система, которая имеет запутанную конструкцию, и не стоит тратить усилия на создание модуля для нее.

Во всех случаях Pyppeteer очень надежен, пока вы не решите интегрировать его в базу кода App Engine Flex и развернуть его.

Стандартный образ Docker Python GCR не содержит необходимых библиотек и драйверов для запуска Chromium. При развертывании сборка завершится успешно, но при вызове метода "launch" вы получите следующую ошибку:

error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory

Решение

Решение, к сожалению, не указано в документации Pyppeteer и не является очевидным, но следующие шаги необходимы:

Вместо использования значения "python" в качестве runtime в файле YAML вашего приложения, установите его как "custom". Это позволяет App Engine знать, что вы будете использовать Dockerfile.

FROM gcr.io/google_appengine/pythonRUN apt-get update && apt-get -y install  gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget

RUN virtualenv /env
ENV _VIRTUAL_ENV _/env
ENV _PATH _/env/bin:$_PATH_RUN mkdir /your/app/path
ADD . /your/app/path
WORKDIR /your/app/path
ADD requirements.txt /your/app/path/requirements.txt
RUN pip3 install -r /your/app/path/requirements.txt
EXPOSE 8080
ENTRYPOINT ["gunicorn", "-b", ":8080", "main:app"]

Давайте разберемся с этим поэтапно.

FROM gcr.io/google_appengine/python

Сначала мы хотим использовать контейнерный образ Google Cloud Repository. Это эквивалент установки вашего runtime как "python", поэтому ничего не меняется, но мы можем добавить пакеты в нашу среду.

RUN apt-get update && apt-get -y install ...etc

Затем мы запускаем apt-get и устанавливаем все зависимости Chromium.

Последующие шаги являются необязательными, но рекомендуется создать виртуальное окружение для вашего приложения, чтобы избежать конфликтов с контейнерным образом.

Кроме того, вам нравится быть аккуратным, верно?

Затем вы устанавливаете пакеты из requirements.txt, открываете порт 8080 (порт по умолчанию для App Engine Flex) и задаете точку входа - в моем случае gunicorn.

  1. Внутри вашего файла Python, где вы используете Pyppeteer, убедитесь, что вы добавляете флаг "--no-sandbox" к вашим аргументам, как показано ниже:
args = ['--no-sandbox']
browser = await launch(args=args)
page = await browser.newPage()

Этот флаг важен, потому что ваш контейнер будет запущен по умолчанию с правами root, и Chromium не позволит вам запуститься в режиме с песочницей по умолчанию для root.

Заключение

Надеюсь, вы найдете это полезным и что оно сэкономит некоторое время разработчикам, которое можно было бы потратить на парсинг (парсер) /r/PraiseTheCameraMan_ (поблагодарите меня позже)_. Если это так, пожалуйста, оставьте свои комментарии и отзывы ниже.

Если вам интересно, я создал проект "Informer - Telegram Mass Surveillance". Это код и пошаговое руководство о том, как массово развернуть бесконечное количество ботов Telegram, которые неотличимы от "реальных" аккаунтов, и показывает, как это можно сделать автоматически.

Прошу прощения за кликбейтное название проекта, FWIW он был представлен на Hacker News, не стесняйтесь поддержать коллегу разработчика звездочками.

Хорошего дня. Продолжайте в том же духе.