Selenium, AWS EC2'de çalışır ancak AWS Lambda'da çalışmaz

Nov 16 2020

Bu konudaki hemen hemen her gönderiye baktım ve şansım olmadan denedim.

EC2

Kullanıyorum, python 3.6bu yüzden aşağıdaki AMI'yi kullanıyorum amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2( buraya bakın ). EC2'ye SSH uyguladığımda, Chrome'u şu şekilde indiriyorum:

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 

Ve eşleşen Chromedriver'ı indirip açın:

sudo wget https://chromedriver.storage.googleapis.com/86.0.4240.22/chromedriver_linux64.zip
sudo unzip chromedriver_linux64.zip

Kurarım python36ve seleniumşunlarla:

sudo yum install python36 -y
sudo /usr/bin/pip-3.6 install selenium

Ardından komut dosyasını çalıştırın:

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)

Bu çalışıyor

Lambda

Daha sonra Chromedriver ve Chrome dosyalarımı sıkıştırıyorum:

mkdir tmp
mv chromedriver tmp
mv chrome tmp
cd tmp
zip -r9 ../chrome.zip chromedriver chrome

Ve bir Sıkıştırılmış dosyayı kopyalamak S3kova

Bu benim lambda işlevim:

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)

Açılmış dosyalarımı /tmpyolda görebiliyorum.

Ve benim hatam:

{
  "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)"
    ]
  ]
}

DÜZENLEME: Bu noktada her şeyi denemeye hazırım. Chrome veya Chromium, Chromedriver, Python veya Selenium'un farklı sürümleri.

DÜZENLEME2: Aşağıdaki cevap sorunu çözmedi.

Yanıtlar

5 DebanjanB Nov 18 2020 at 21:13

Bu hata mesajı ...

"errorMessage": "Message: unknown error: unable to discover open pages\n",
"errorType": "WebDriverException"

... ChromeDriver'ın yeni bir Tarama Bağlamı, yani Chrome Tarayıcı oturumu başlatamadığı / oluşturamadığı anlamına gelir .

Konu ile görünüyor ChromeDriver , s güvenlik özelliğinin ait korumalı alan .


Temel kural

Başlatma sırasında Chrome'un kilitlenmesinin yaygın bir nedeni, Chrome'un Linux'ta rootkullanıcı olarak ( administrator) çalıştırılmasıdır . --no-sandboxWebDriver oturumunuzu oluştururken bayrağı ileterek bu sorunu aşmak mümkün olsa da , böyle bir yapılandırma desteklenmez ve kesinlikle önerilmez. Ortamınızı bunun yerine Chrome'u normal bir kullanıcı olarak çalıştıracak şekilde yapılandırmanız gerekir.


Detaylar

Kullanım durumunuz hakkında biraz daha fazla ayrıntı, kullandığınız argümanların kullanımını ve hatanın temel nedenini daha iyi bir şekilde analiz etmemize yardımcı olabilirdi. Ancak birkaç düşünce:

  • Korumalı alan nedir? : Korumalı alan, çok kısıtlayıcı bir ortamda yürütülen işlemler olan korumalı alandaki işlemlerin oluşturulmasına izin veren bir C ++ kitaplığıdır. Korumalı alandaki işlemlerin serbestçe kullanabileceği tek kaynak CPU döngüleri ve bellektir. Örneğin, sanal alan işlemleri diske yazamaz veya kendi pencerelerini görüntüleyemez. Tam olarak yapabilecekleri, açık bir politika tarafından kontrol edilir. Chromium oluşturucular, korumalı alandaki işlemlerdir.
  • Neye karşı korur ve korumaz? : Sanal alan, korumalı alan içinde çalışan koddaki hataların önem derecesini sınırlar. Bu tür hatalar, kullanıcının hesabına kalıcı kötü amaçlı yazılım yükleyemez (çünkü dosya sistemine yazmak yasaklanmıştır). Bu tür hatalar ayrıca kullanıcının makinesinden rastgele dosyaları okuyamaz ve çalamaz. (Chromium'da, oluşturucu işlemleri korumalı alana alınır ve bu korumaya sahiptir. NPAPI kaldırıldıktan sonra, kalan tüm eklentiler de korumalı alana alınır. Ayrıca Chromium oluşturucu işlemlerinin sistemden izole edildiğini, ancak henüz web'den ayrılmadığını unutmayın. Bu nedenle, veri izolasyonu henüz sağlanmamaktadır.). Sanal alan, üzerinde çalıştığı çekirdek gibi sistem bileşenlerindeki hatalara karşı herhangi bir koruma sağlayamaz.
  • Öyleyse, oluşturucu gibi korumalı alana alınmış bir işlem nasıl her şeyi başarabilir? : Belirli iletişim kanalları, korumalı alandaki işlemler için açıkça açıktır; işlemler bu kanallardan yazıp okuyabilir. Daha ayrıcalıklı bir süreç, korumalı alandaki işlem adına belirli eylemleri gerçekleştirmek için bu kanalları kullanabilir. Chromium'da, ayrıcalıklı süreç genellikle tarayıcı işlemidir.

Bu yüzden --no-sandboxseçeneği kaldırmanız gerekebilir . İşte Sandbox hikayesinin bağlantısı .


Ek Hususlar

Bazı noktalar daha:

  • Kullanırken --headlessseçeneği kullanmak mümkün olmayacaktır --window-size=1280x1696bazı kısıtlamaları nedeniyle.

Birkaç ilgili ayrıntılı tartışmayı şurada bulabilirsiniz:

  • Selenium kullanarak Başsız Chrome'da tam ekran
  • Başsız modda Chrome Penceresini büyütemiyor
  • Argüman --disable-gpusağlamak amacıyla oluşturulan google-krom başsız üzerinde pencereleri platformu. SwiftShader daha önce Windows'ta başsız modda bir iddiada başarısız olduğu için gerekliydi . Bu sorun oldu çözülmesi yoluyla Headless: yapmak disable-gpu bayrak gereksiz

İlgili ayrıntılı tartışmayı ERROR'da bulabilirsiniz : gpu_process_transport_factory.cc (1007) -Kayıp UI paylaşılan bağlamı: Başsız modda ChromeDriver aracılığıyla Chrome tarayıcısını başlatırken

  • Ayrıca size herhangi özel gereksinimi bahsetmedim kullanarak --disable-dev-shm-usage, --hide-scrollbars, --enable-logging, --log-level=0, --v=99, --single-processve --remote-debugging-port=9222size zaman varlık için açılan ve başına geri eklemek için tercih argümanlar Testi Şartname .

Referanslar

Birkaç ilgili ayrıntılı tartışmayı şurada bulabilirsiniz:

  • selenium.common.exceptions.WebDriverException: Mesaj: bilinmeyen hata: Selenium aracılığıyla ChromeDriver kullanılarak açık sayfalar bulunamıyor
  • WebDriverException: bilinmeyen hata: ChromeDriver 80.0.3987.106 ve Chrome 80.0.3987.122 ile açık sayfalar bulunamıyor hatası
CPak Dec 13 2020 at 20:28

Sonunda işe yarayabildim

Python 3.7
selenium==3.14.0
headless-chromium v1.0.0-55
chromedriver 2.43

Başsız-Krom

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

Başsız krom ve krom sürücü ekledim Lambda Layer

755Her iki eser için izinler

Lambda

Lambda işlevi şuna benzer

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)

Umarım bu, Q4 2020'de ve sonrasında birine yardımcı olur.