Selen funktioniert mit AWS EC2, jedoch nicht mit AWS Lambda
Ich habe fast jeden anderen Beitrag zu diesem Thema ohne Glück angeschaut und ausprobiert.
EC2
Ich benutze python 3.6also folgendes AMI amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2(siehe hier ). Sobald ich SSH in mein EC2 habe, lade ich Chrome herunter mit:
sudo curl https://intoli.com/install-google-chrome.sh | bash
cp -r /opt/google/chrome/ /home/ec2-user/
google-chrome-stable --version
# Google Chrome 86.0.4240.198
Laden Sie den passenden Chromedriver herunter und entpacken Sie ihn:
sudo wget https://chromedriver.storage.googleapis.com/86.0.4240.22/chromedriver_linux64.zip
sudo unzip chromedriver_linux64.zip
Ich installiere python36und seleniummit:
sudo yum install python36 -y
sudo /usr/bin/pip-3.6 install selenium
Führen Sie dann das Skript aus:
import os
import selenium
from selenium import webdriver
CURR_PATH = os.getcwd()
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--window-size=1280x1696')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--hide-scrollbars')
chrome_options.add_argument('--enable-logging')
chrome_options.add_argument('--log-level=0')
chrome_options.add_argument('--v=99')
chrome_options.add_argument('--single-process')
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_argument('--remote-debugging-port=9222')
chrome_options.binary_location = f"{CURR_PATH}/chrome/google-chrome"
driver = webdriver.Chrome(
executable_path = f"{CURR_PATH}/chromedriver",
chrome_options=chrome_options
)
driver.get("https://www.google.com/")
html = driver.page_source
print(html)
Das funktioniert
Lambda
Ich komprimiere dann meine Chromedriver- und Chrome-Dateien:
mkdir tmp
mv chromedriver tmp
mv chrome tmp
cd tmp
zip -r9 ../chrome.zip chromedriver chrome
Und kopieren Sie die komprimierte Datei in einen S3Bucket
Dies ist meine Lambda-Funktion:
import os
import boto3
from botocore.exceptions import ClientError
import zipfile
import selenium
from selenium import webdriver
s3 = boto3.resource('s3')
def handler(event, context):
chrome_bucket = os.environ.get('CHROME_S3_BUCKET')
chrome_key = os.environ.get('CHROME_S3_KEY')
# DOWNLOAD HEADLESS CHROME FROM S3
try:
# with open('/tmp/headless_chrome.zip', 'wb') as data:
s3.meta.client.download_file(chrome_bucket, chrome_key, '/tmp/chrome.zip')
print(os.listdir('/tmp'))
except ClientError as e:
raise e
# UNZIP HEADLESS CHROME
try:
with zipfile.ZipFile('/tmp/chrome.zip', 'r') as zip_ref:
zip_ref.extractall('/tmp')
# FREE UP SPACE
os.remove('/tmp/chrome.zip')
print(os.listdir('/tmp'))
except:
raise ValueError('Problem with unzipping Chrome executable')
# CHANGE PERMISSION OF CHROME
try:
os.chmod('/tmp/chromedriver', 0o775)
os.chmod('/tmp/chrome/chrome', 0o775)
os.chmod('/tmp/chrome/google-chrome', 0o775)
except:
raise ValueError('Problem with changing permissions to Chrome executable')
# GET LINKS
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--window-size=1280x1696')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--hide-scrollbars')
chrome_options.add_argument('--enable-logging')
chrome_options.add_argument('--log-level=0')
chrome_options.add_argument('--v=99')
chrome_options.add_argument('--single-process')
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_argument('--remote-debugging-port=9222')
chrome_options.binary_location = "/tmp/chrome/google-chrome"
driver = webdriver.Chrome(
executable_path = "/tmp/chromedriver",
chrome_options=chrome_options
)
driver.get("https://www.google.com/")
html = driver.page_source
print(html)
Ich kann meine entpackten Dateien im /tmpPfad sehen.
Und mein Fehler:
{
"errorMessage": "Message: unknown error: unable to discover open pages\n",
"errorType": "WebDriverException",
"stackTrace": [
[
"/var/task/lib/observer.py",
69,
"handler",
"chrome_options=chrome_options"
],
[
"/var/task/selenium/webdriver/chrome/webdriver.py",
81,
"__init__",
"desired_capabilities=desired_capabilities)"
],
[
"/var/task/selenium/webdriver/remote/webdriver.py",
157,
"__init__",
"self.start_session(capabilities, browser_profile)"
],
[
"/var/task/selenium/webdriver/remote/webdriver.py",
252,
"start_session",
"response = self.execute(Command.NEW_SESSION, parameters)"
],
[
"/var/task/selenium/webdriver/remote/webdriver.py",
321,
"execute",
"self.error_handler.check_response(response)"
],
[
"/var/task/selenium/webdriver/remote/errorhandler.py",
242,
"check_response",
"raise exception_class(message, screen, stacktrace)"
]
]
}
EDIT: Ich bin bereit, an dieser Stelle alles auszuprobieren. Verschiedene Versionen von Chrome oder Chromium, Chromedriver, Python oder Selen.
EDIT2: Die Antwort unten hat das Problem nicht gelöst.
Antworten
Diese Fehlermeldung ...
"errorMessage": "Message: unknown error: unable to discover open pages\n",
"errorType": "WebDriverException"
... bedeutet , dass die ChromeDriver nicht in der Lage war , eine neue zu initiieren / laichen Browsing Context dh Chrome Browser - Sitzung.
Es scheint, dass das Problem bei ChromeDriver liegt , der Sicherheitsfunktion von Sandboxing .
Faustregel
Eine häufige Ursache für einen Absturz von Chrome beim Start ist das Ausführen von Chrome als
rootuser (administrator) unter Linux. Während es möglich ist, dieses Problem zu--no-sandboxumgehen, indem Sie beim Erstellen Ihrer WebDriver-Sitzung das Flag übergeben, wird eine solche Konfiguration nicht unterstützt und dringend empfohlen. Sie müssen Ihre Umgebung so konfigurieren, dass Chrome stattdessen als normaler Benutzer ausgeführt wird.
Einzelheiten
Ein bisschen mehr Details zu Ihrem Anwendungsfall hätten uns geholfen, die Verwendung der von Ihnen verwendeten Argumente und die Grundursache des Fehlers besser zu analysieren. Ein paar Gedanken:
- Was ist der Sandkasten? : Die Sandbox ist eine C ++ - Bibliothek, mit der Sandbox-Prozesse erstellt werden können - Prozesse, die in einer sehr restriktiven Umgebung ausgeführt werden. Die einzigen Ressourcen, die Sandbox-Prozesse frei nutzen können, sind CPU-Zyklen und Speicher. Beispielsweise können Sandbox-Prozesse nicht auf die Festplatte schreiben oder ihre eigenen Fenster anzeigen. Was genau sie tun können, wird durch eine explizite Richtlinie gesteuert. Chrom-Renderer sind Sandbox-Prozesse.
- Wovor schützt und schützt es nicht? : Die Sandbox begrenzt die Schwere von Fehlern im Code, der in der Sandbox ausgeführt wird. Solche Fehler können keine dauerhafte Malware im Benutzerkonto installieren (da das Schreiben in das Dateisystem verboten ist). Solche Fehler können auch keine beliebigen Dateien vom Computer des Benutzers lesen und stehlen. (In Chromium sind die Renderer-Prozesse in einer Sandbox gespeichert und verfügen über diesen Schutz. Nach dem Entfernen des NPAPI werden auch alle verbleibenden Plugins in einer Sandbox gespeichert. Beachten Sie außerdem, dass Chromium-Renderer-Prozesse vom System, jedoch noch nicht vom Web isoliert sind. Daher domänenbasiert Datenisolation ist noch nicht vorgesehen.). Die Sandbox kann keinen Schutz gegen Fehler in Systemkomponenten wie dem Kernel bieten, auf dem sie ausgeführt wird.
- Wie kann ein Sandbox-Prozess wie ein Renderer etwas erreichen? : Bestimmte Kommunikationskanäle sind explizit für Sandbox-Prozesse geöffnet. Die Prozesse können aus diesen Kanälen schreiben und lesen. Ein privilegierterer Prozess kann diese Kanäle verwenden, um bestimmte Aktionen im Namen des Sandbox-Prozesses auszuführen. In Chromium ist der privilegierte Prozess normalerweise der Browserprozess.
Daher müssen Sie möglicherweise die --no-sandboxOption löschen. Hier ist der Link zur Sandbox- Geschichte.
Weitere Überlegungen
Einige weitere Überlegungen:
- Während Sie die
--headlessOption verwenden, können Sie sie--window-size=1280x1696aufgrund bestimmter Einschränkungen nicht verwenden.
Einige relevante ausführliche Diskussionen finden Sie in:
- Vollbild in Headless Chrome mit Selen
- Chrome Window kann im Headless-Modus nicht maximiert werden
- Das Argument
--disable-gpuwar, Google-Chrome-Headless auf Windows- Plattform zu aktivieren . Es wurde benötigt, da SwiftShader eine Bestätigung unter Windows im Headless-Modus früher nicht bestanden hat. Dieses Problem wurde durch Headless behoben : Machen Sie das Flag --disable-gpu unnötig
Eine relevante ausführliche Diskussion finden Sie in ERROR: gpu_process_transport_factory.cc (1007) - Verlust des freigegebenen UI-Kontexts: Beim Initialisieren des Chrome-Browsers über ChromeDriver im Headless-Modus
- Des Weiteren haben Sie keine spezielle Anforderung der Verwendung erwähnt
--disable-dev-shm-usage,--hide-scrollbars,--enable-logging,--log-level=0,--v=99,--single-processund--remote-debugging-port=9222Argumente , die Sie sich für die Zeit Wesen und fügen Sie sie zurück nach Ihren Drop Test Specification .
Verweise
Einige relevante ausführliche Diskussionen finden Sie in:
- selenium.common.exceptions.WebDriverException: Meldung: unbekannter Fehler: Offene Seiten können mit ChromeDriver über Selenium nicht erkannt werden
- WebDriverException: Unbekannter Fehler: Fehler bei geöffneten Seiten mit ChromeDriver 80.0.3987.106 und Chrome 80.0.3987.122 konnte nicht erkannt werden
Ich konnte es endlich zum Laufen bringen
Python 3.7
selenium==3.14.0
headless-chromium v1.0.0-55
chromedriver 2.43
Headless-Chrom
https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-55/stable-headless-chromium-amazonlinux-2017-03.zip
Chromedriver
https://chromedriver.storage.googleapis.com/2.43/chromedriver_linux64.zip
Ich habe a Headless-Chrom und Chromedriver hinzugefügt Lambda Layer
Berechtigungen 755für beide Werke
Lambda
Die Lambda-Funktion sieht so aus
import os
import selenium
from selenium import webdriver
def handler(event, context):
print(os.listdir('/opt'))
#
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--single-process')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.binary_location = f"/opt/headless-chromium"
driver = webdriver.Chrome(
executable_path = f"/opt/chromedriver",
chrome_options=chrome_options
)
driver.get("https://www.google.com/")
html = driver.page_source
driver.close()
driver.quit()
print(html)
Hoffe das hilft jemandem im vierten Quartal 2020 und danach.