Skip to content
Home » How to deploy a scraping script and Selenium in Google Cloud Run

How to deploy a scraping script and Selenium in Google Cloud Run

In this blog post, you’ll learn how you can run scraping jobs using Selenium from Google Cloud Run, a fully managed solution that eliminates the burden of configuring and managing a Kubernetes cluster. It simplifies your production pipeline and fully automates your scraping process.

Take notice, I’m not an expert in Google Cloud Run. The downside is that there might be a more optimal way to do all this. The upside is that I know what your questions and frustrations are.

To fully understand this blog post, you shoud know:

  • Basics of GCP
  • Basics of Docker
  • Python

Glossary

I (incorrectly) tend to use some terms interchangably. By adding a glossary, I hope to force myself to use correct terminology.

  • An (Docker) image is a set of instructions that is used to execute a (Docker) container.
  • A (Docker) container is an instance of an image.
  • A (Cloud Run) service is a (Docker) container deployed on Google Cloud Run.
  • A deployment is the act of deploying an image as (containerized) service to Google Cloud Run.
  • Commands are all run on a local machine, assuming you have gcloud and Docker installed.
  • A service account is an account used by an application to make authorized API calls within Google Cloud Platform.
  • A header lets the client and the server pass additional information with an HTTP request or response. For example, authentication.

FYI: everything is tested on a Win10 machine.

Structure of this blog post

This blog post consists out of several sections.

  • First, I explain how you can deploy Selenium in Google Cloud Run.
  • Next, you will find the commands to create a service account and link it to the Selenium service.
  • Update the RemoteConnection class in Selenium’s Python API.
  • Build your scraping script and test it on your machine (using the remote Selenium service)
  • Finally, you’ll learn to deploy the scraping script.

Deploy Selenium

To deploy remote Selenium webdriver to Google Cloud Run, I follow a classic Docker workflow, but feel free to use this Cloud Build tutorial.

  • First, pull the standalone Chrome Selenium image from Docker Hub.
  • Tag the image with the GCP Container Registry destination (you can also use gcr.io).
  • Push the image by referring to the tag we set in the previous step.
docker pull selenium/standalone-chrome
docker image tag selenium/standalone-chrome us.gcr.io/<PROJECT_NAME>/<SELENIUM_IMAGE_NAME>
docker push us.gcr.io/<PROJECT_NAME>/<SELENIUM_IMAGE_NAME>

Using the following command, we deploy the image that we uploaded to the Cloud Registry as a service to Cloud Run.

In the wizard that follows, you can choose to allow unauthenticated communication with the container. However, I strongly recommend against this for obvious reasons. I have included instructions for authenticated communication with a Selenium container in Cloud Run in the section below.

gcloud run deploy <SELENIUM_SERVICE_NAME> \
	--image us.gcr.io/<PROJECT_NAME>/<SELENIUM_IMAGE_NAME> \
    --port 4444 \
    --memory 2G

Some important things to notice.

Make sure you map the port, otherwise you’ll encounter the following error during deployment. This occurs because Cloud Run by default maps ports 8080, which isn’t applicable for Selenium.

Cloud Run error: Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable.

Furthermore, you should set the memory adequately. If you set the memory too low, sessions will be terminated and you’ll keep running into the following error.

selenium.common.exceptions.WebDriverException: Message: No active session with ID

If your deployment succeeded, you will be able to find the service URL in the Cloud Run section of Google Cloud Platform. You will need this URL to deploy the scraper, where you will refer to it.

Create service account

In this section, I explain how you can set up a service account that the scraping service uses to communicate to the Selenium service.

First, create the service account by running the following command.

gcloud iam service-accounts create <INVOKING_SERVICE_ACCOUNT> 
	--description "This service accounts invokes Selenium on Google Cloud Run." 
    --display-name "Selenium Invoker"

Next, link the service account you just created to the the Selenium service in Google Cloud Run.

gcloud run services add-iam-policy-binding <SERVICE_NAME>  \
    --member serviceAccount:<INVOKING_SERVICE_ACCOUNT>@roelpeters-blog.iam.gserviceaccount.com \
    --role roles/run.invoker

Now, the Selenium service will communication from this service account, and it can be used by the scraping service.

Update Selenium’s RemoteConnection class

There’s bad news: Selenium’s Python API does not accept header-based authentication. In other words, there’s no out-of-the-box way to authenticate via the webdriver.Remote() method and your scraping script can’t communicate in a safe way with the Selenium container.

The good news, Python is an object-oriented programming language, and we can easily overwrite the necessary classes & methods to enable header-based authentication.

In the code below, you can find the RemoteConnectionV2 class, for which I developed the set_remote_connection_authentication_headers method. This method either checks if the IDENTITY_TOKEN environment variable has been set manually. If not, it fetches an identity token via the google.oauth service.

In the get_remote_connection_headers, authentication headers are concatenated to the other headers.

from selenium import webdriver
from selenium import __version__
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote import remote_connection

from time import sleep
from datetime import datetime
from base64 import b64encode
from flask import Flask

import psycopg2
import os
import platform

import google.auth.transport.requests
import google.oauth2.id_token

app = Flask(__name__)

if os.environ.get('SELENIUM_URL') is not None:
    selenium_url = os.environ.get('SELENIUM_URL')
else:
    raise Exception('No remote Selenium webdriver provided in the environment.')

# Overwriting the RemoteConnection class in order to authenticate with the Selenium Webdriver in Cloud Run.
class RemoteConnectionV2(remote_connection.RemoteConnection):
    @classmethod
    def set_remote_connection_authentication_headers(self):
        # Environment variable: identity token -- this can be set locally for debugging purposes.
        if os.environ.get('IDENTITY_TOKEN') is not None:
            print('[Authentication] An identity token was found in the environment. Using it.')
            identity_token = os.environ.get('IDENTITY_TOKEN')
        else:
            print('[Authentication] No identity token was found in the environment. Requesting a new one.')
            auth_req = google.auth.transport.requests.Request()
            identity_token = google.oauth2.id_token.fetch_id_token(auth_req, selenium_url)
        self._auth_header = {'Authorization': 'Bearer %s' % identity_token}
    
    @classmethod
    def get_remote_connection_headers(self, cls, parsed_url, keep_alive=False):
        """
        Get headers for remote request -- an update of Selenium's RemoteConnection to include an Authentication header.
        :Args:
         - parsed_url - The parsed url
         - keep_alive (Boolean) - Is this a keep-alive connection (default: False)
        """

        system = platform.system().lower()
        if system == "darwin": 
            system = "mac"

        default_headers = {
            'Accept': 'application/json',
            'Content-Type': 'application/json;charset=UTF-8',
            'User-Agent': 'selenium/{} (python {})'.format(__version__, system)
        }

        headers = {**default_headers, **self._auth_header}
        if 'Authorization' not in headers:
            if parsed_url.username:
                base64string = b64encode('{0.username}:{0.password}'.format(parsed_url).encode())
                headers.update({
                    'Authorization': 'Basic {}'.format(base64string.decode())
                })

        if keep_alive:
            headers.update({
                'Connection': 'keep-alive'
            })

        return headers

Structuring the scraping script

Below the code in the previous section, you can write your scraping script. As you can see, a connection is established to Selenium via the RemoteConnectionV2 class. Next, the authentication headers are set, and the webdriver session is initiated.

Below that, you can place the instructions for collecting web data via the webdrive instance (chrome_driver).

@app.route("/")
def scrape():
    selenium_connection = RemoteConnectionV2(selenium_url, keep_alive = True)
    selenium_connection.set_remote_connection_authentication_headers()
    chrome_driver = webdriver.Remote(selenium_connection, DesiredCapabilities.CHROME)
    
    <INSERT_CODE_HERE>
    
    return

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

Debug Locally

There are two ways that you can debug this. First, you can debug the locally by setting environment variables in your virtual environment and running the script. If you’ve followed all the previous instructions, your Python script will search for SELENIUM_URL and IDENTITY_TOKEN environment variables. This allows you to debug the scraping script locally.

$env:SELENIUM_URL = '<SELENIUM_SERVICE_URL>/wd/hub'
$env:IDENTITY_TOKEN = $(gcloud auth print-identity-token)

Debug in a Docker container

Alternatively, you can build a docker image and run a container locally with the necessary environment variables set.

docker build . --tag <LOCAL_IMAGE_NAME>:latest
docker run 
	-p 8080:8080 \
	--env SELENIUM_URL=<SELENIUM_SERVICE_URL>/wd/hub 
    --env IDENTITY_TOKEN=$(gcloud auth print-identity-token) 
    <LOCAL_IMAGE_NAME>:latest

If everything works as planned, you can build the Docker image for this particular script. These are the packages that I put in my requirements.txt.

Flask==2.0.1
psycopg2==2.8.6
scipy==1.6.0
selenium==3.141.0
gunicorn==20.1.0
google-auth==1.31.0
requests==2.25.1

And this is my Dockerfile.

# syntax=docker/dockerfile:1
FROM python:3.9.1

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

# Copy files
WORKDIR /app
COPY scrape_social_media.py scrape_social_media.py
COPY requirements.txt requirements.txt

RUN apt-get update
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 --timeout 0 scrape_social_media:app

Deploy scraper

In this section, I assume you have built the Docker image for your scrape script. Pushing this image to the GCP Container Registry is completely analogous to pushing the Selenium image.

docker image tag <SCRAPER_IMAGE> us.gcr.io/<PROJECT_NAME>/<SCRAPER_IMAGE_NAME>
docker push us.gcr.io/<PROJECT_NAME>/<SCRAPER_IMAGE_NAME>

There are multiple things you should take care of when deploying your scrape script to Cloud Run.

  • Provide the URL address of the Selenium service we deployed earlier. This can be done easily by using environment variables with the parameter —set-env-vars
  • Link the required service account that you’ll be using to authenticate with the Selenium service. If you don’t want to have authentication in place, you can remove the –service-account parameter.
gcloud run deploy <SCRAPER_SERVICE_NAME> \
	--image us.gcr.io/<PROJECT_NAME>/<SCRAPER_IMAGE_NAME>
    --service-account <SERVICE_INVOKING_ACCOUNT>
    --set-env-vars SELENIUM_URL=<SELENIUM_SERVICE_URL>/wd/hub
    --allow-unauthenticated 
    --memory 1G

You are now set to automatically scrape the web. A next step would be to set up the scraping job recurrently with GCP Scheduler, Tasks or Workflows.

31 thoughts on “How to deploy a scraping script and Selenium in Google Cloud Run”

  1. Hi, please could you elaborate what you mean by mapping the port here: “Make sure you map the port, otherwise you’ll encounter the following error during deployment. This occurs because Cloud Run by default maps ports 8080, which isn’t applicable for Selenium.”?

    1. Hi Alex,

      As can be seen in the listed pieces of code. Make sure you map to port 4444, explicitly. Otherwise Cloud Run will map to port 8080 automatically.

      Best regards
      Roel

      1. Hi Roel,
        Thanks for the reply. However, the only time I see the code snippets above use port 4444 is when deploying the selenium service for the first time. All the other code snippets show you using port 8080?

  2. Poor quality article, way too confusing for a beginner. You use variables like without actually giving an example or specifying. Could not get working following your steps, your set up through Google Cloud is non-existent and relies on me knowing what to set up.

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

  4. Наш веб-портал — официальная страница лицензированного расследовательской службы.
    Мы оказываем поддержку в решении деликатных ситуаций.
    Группа сотрудников работает с предельной конфиденциальностью.
    Мы берёмся за наблюдение и детальное изучение обстоятельств.
    Детективное агентство
    Любой запрос получает персональный подход.
    Применяем проверенные подходы и действуем в правовом поле.
    Ищете настоящих профессионалов — вы нашли нужный сайт.

  5. Were you aware that 1 in 3 medication users make dangerous medication errors due to lack of knowledge?

    Your physical condition requires constant attention. Every medication decision you consider directly impacts your body’s functionality. Maintaining awareness about your prescriptions should be mandatory for successful recovery.
    Your health goes far beyond swallowing medications. Every medication interacts with your body’s chemistry in potentially dangerous ways.

    Remember these life-saving facts:
    1. Mixing certain drugs can cause health emergencies
    2. Over-the-counter allergy medicines have strict usage limits
    3. Altering dosages reduces effectiveness

    For your safety, always:
    ✓ Verify interactions via medical databases
    ✓ Study labels in detail before taking new prescriptions
    ✓ Ask your pharmacist about proper usage

    ___________________________________
    For professional medication guidance, visit:
    https://www.pinterest.com/pin/879609370963838922/

  6. В данном ресурсе вы обнаружите всю информацию о программе лояльности: 1win партнерская программа.
    Здесь размещены все нюансы партнёрства, условия участия и ожидаемые выплаты.
    Все части детально описан, что даёт возможность просто разобраться в нюансах системы.
    Кроме того, есть FAQ по теме и рекомендации для первых шагов.
    Контент дополняется, поэтому вы смело полагаться в точности предоставленных сведений.
    Ресурс послужит подспорьем в освоении партнёрской программы 1Win.

  7. Наш сервис поможет получить информацию по заданному профилю.
    Достаточно ввести имя, фамилию , чтобы сформировать отчёт.
    Система анализирует публичные данные и цифровые следы.
    чат бот глаз бога
    Информация обновляется мгновенно с проверкой достоверности .
    Идеально подходит для проверки партнёров перед важными решениями.
    Анонимность и точность данных — гарантированы.

  8. Наш сервис поможет получить информацию по заданному профилю.
    Укажите никнейм в соцсетях, чтобы получить сведения .
    Бот сканирует публичные данные и активность в сети .
    глаз бога актуальный бот
    Информация обновляется мгновенно с проверкой достоверности .
    Идеально подходит для анализа профилей перед сотрудничеством .
    Анонимность и актуальность информации — наш приоритет .

  9. Нужно найти информацию о пользователе? Этот бот поможет полный профиль мгновенно.
    Используйте продвинутые инструменты для поиска публичных записей в открытых источниках.
    Выясните место работы или интересы через автоматизированный скан с гарантией точности .
    глаз бога телеграм бесплатно
    Система функционирует с соблюдением GDPR, обрабатывая общедоступную информацию.
    Закажите расширенный отчет с геолокационными метками и графиками активности .
    Попробуйте надежному помощнику для исследований — результаты вас удивят !

  10. На данном сайте предоставляется данные по запросу, в том числе полные анкеты.
    Архивы охватывают граждан разного возраста, профессий.
    Сведения формируются на основе публичных данных, подтверждая надежность.
    Обнаружение производится по фамилии, сделав использование быстрым.
    глаз бога в телеграме
    Помимо этого можно получить контакты плюс актуальные данные.
    Работа с информацией обрабатываются в соответствии с правовых норм, предотвращая утечек.
    Используйте предложенной системе, чтобы найти необходимую информацию без лишних усилий.

  11. Нужно найти информацию о человеке ? Наш сервис предоставит полный профиль мгновенно.
    Воспользуйтесь уникальные алгоритмы для анализа цифровых следов в открытых источниках.
    Выясните контактные данные или активность через систему мониторинга с гарантией точности .
    глаз бога ссылка
    Система функционирует в рамках закона , используя только общедоступную информацию.
    Закажите детализированную выжимку с историей аккаунтов и списком связей.
    Попробуйте проверенному решению для digital-расследований — точность гарантирована!

  12. Хотите собрать данные о пользователе? Этот бот предоставит детальный отчет в режиме реального времени .
    Используйте продвинутые инструменты для поиска публичных записей в открытых источниках.
    Выясните контактные данные или активность через автоматизированный скан с гарантией точности .
    глаз бога проверить
    Бот работает с соблюдением GDPR, используя только открытые данные .
    Получите расширенный отчет с геолокационными метками и списком связей.
    Доверьтесь надежному помощнику для исследований — результаты вас удивят !

  13. Выгребная яма — это подземная ёмкость , предназначенная для сбора и частичной переработки отходов.
    Система работает так: жидкость из дома поступает в бак , где формируется слой ила, а жиры и масла всплывают наверх .
    Основные элементы: входная труба, герметичный бак , соединительный канал и почвенный фильтр для дочистки воды .
    https://richstone.by/forum/messages/forum1/message3970/2675-kupit-septik-v-moskve-nedorogo?result=new#message3970
    Преимущества: низкие затраты , долговечность и экологичность при соблюдении норм.
    Однако важно не перегружать систему , иначе частично очищенная вода попадут в грунт, вызывая загрязнение.
    Типы конструкций: бетонные блоки, полиэтиленовые резервуары и стекловолоконные модули для разных условий монтажа .

  14. Дом Patek Philippe — это эталон часового искусства , где соединяются точность и художественная отделка.
    С историей, уходящей в XIX век компания славится авторским контролем каждого изделия, требующей многолетнего опыта.
    Изобретения, включая ключевой механизм 1842 года , укрепили репутацию как новатора в индустрии.
    наручные часы Патек Филипп купить
    Коллекции Grand Complications демонстрируют вечные календари и декоративные элементы, выделяя уникальность.
    Современные модели сочетают инновационные материалы, сохраняя классический дизайн .
    Patek Philippe — символ семейных традиций, передающий инженерную элегантность из поколения в поколение.

  15. Нейросетевые боты для поиска информации становятся всё более удобными.
    Они помогают изучать публичные данные из разных источников.
    Такие решения используются для исследований.
    Они умеют оперативно анализировать большие объёмы данных.
    глаз бога пробив тг
    Это позволяет сформировать более точную картину событий.
    Отдельные системы также предлагают инструменты фильтрации.
    Такие сервисы широко используются среди исследователей.
    Эволюция технологий делает поиск информации более точным и удобным.

  16. Современные онлайн-сервисы для мониторинга источников становятся всё более удобными.
    Они помогают изучать доступные данные из интернета.
    Такие инструменты используются для журналистики.
    Они могут точно систематизировать большие объёмы информации.
    а можно узнать в телеграмме через глаз-бок где находится человек
    Это способствует получить более точную картину событий.
    Некоторые системы также обладают функции визуализации.
    Такие сервисы широко используются среди специалистов.
    Совершенствование технологий превращает поиск информации более точным и быстрым.

  17. Приобретение второго гражданства за границей становится всё более актуальным среди граждан РФ.
    Такой статус открывает дополнительные перспективы для путешествий.
    ВНЖ помогает беспрепятственно путешествовать и избегать визовых ограничений.
    Помимо этого такой документ может повысить финансовую стабильность.
    ВНЖ Евросоюза, ЕС
    Многие россияне рассматривают возможность переезда как путь к независимости.
    Оформляя ВНЖ или второй паспорт, человек легко открыть бизнес за рубежом.
    Многие государства предлагают индивидуальные возможности получения статуса резидента.
    Поэтому тема получения становится всё более значимой для тех, кто думает о будущем.

Leave a Reply

Your email address will not be published. Required fields are marked *