在本地 Python 3 下将扩展安装到 Selenium Grid(远程驱动程序)到在 docker 下运行的远程服务器

Posted

技术标签:

【中文标题】在本地 Python 3 下将扩展安装到 Selenium Grid(远程驱动程序)到在 docker 下运行的远程服务器【英文标题】:Installing extensions into Selenium Grid (remote driver) under local Python 3 to a remote server running under docker 【发布时间】:2021-06-06 21:34:21 【问题描述】:

我已更改此帖子的标题以使其更易于查找,并已解决该问题。请参阅下面的答案。

旧标题 - Selenium Grid 4.0.0.Beta-1 Docker 驱动程序在 Selenium local 不添加 chrome 扩展时使我的 python 应用程序崩溃

我一直在寻找最近的答案并尝试了大多数较旧的答案(所以请不要将其标记为重复)以及谷歌向我展示的每个网站..到目前为止没有任何效果。我想使用最新版本的 Selenium Grid (Docker image) ,我已经设置好并且可以正常工作了,只要我没有安装扩展或定义用户目录,我就可以远程抓取数据,如下...

此代码确实有效,但它在本地浏览器上运行,而不是在 docker Selenium Grid 上运行。

from selenium import webdriver
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

class sgrid:    
       
    def init_chrome_with_cookies_local(self):
        chrome_options = Options()
        chrome_options.add_extension(r'C:\Users\charl\OneDrive\python\vidiqext\3.41.0_0.crx')
        chrome_options.add_argument("user-data-dir=C:/Users/charl/OneDrive/python/userdata") 
        driver = webdriver.Chrome(options=chrome_options) 
        return driver
    

但是当我切换到这个

    def init_chrome_with_cookies_remote(self):
        chrome_options = Options()
        chrome_options.add_extension(r'C:\Users\charl\OneDrive\python\vidiqext\3.41.0_0.crx')
        chrome_options.add_argument(r'user-data-dir=C:/Users/charl/OneDrive/python/userdata')
        driver = webdriver.Remote(command_executor='http://x.x.x.x:4444/wd/hub',options=chrome_options)
        return driver

....它崩溃了,如果同时尝试 add_extension 和 add_argument 或者一个然后另一个都没有关系,它们都会导致应用程序崩溃。

文件“c:/Users/charl/OneDrive/python/sgrid.py”,第 183 行,在迭代中 driver.get('about:blank') UnboundLocalError:分配前引用的局部变量“驱动程序” PS C:\Users\charl\OneDrive\dataharvest\visualstudio>

这个错误实际上只是意味着驱动程序没有正确配置,因为所有其他代码都是相同的。现在我知道 *** 上的一些解决方案使用 DesiredCapabilities 方式,但我被告知这是不推荐使用的,并且没有一个工作过,所以如果有人在 Python 3、Docker 上的 Selenium Grid 4 中有这个工作,我将非常感激知道.

编辑:可能值得注意的是,我的本地机器是 Windows Anaconda,而我的远程机器是运行 Docker 的 Debian,它们不在同一台机器上。我需要在本地或远程机器上规定这些文件/目录的路径吗?

编辑 2:crx 文件或 user-data-dir 的路径应该是远程机器的本地路径,我已经解决了,在我的情况下是 /dev/shm,它必须在内部和外部都可用docker 容器,而不是本地机器。它仍然崩溃,但在远程添加用户数据后,现在找到了部分解决方案。这并不明显,因为例如命令 driver.save_screenshot(...) 将文件保存在本地。

在这种情况下

chrome_options.add_argument("user-data-dir=/dev/shm/vidiq")

似乎可以工作(文件由chrome正常创建,它不会崩溃,并且因为没有VidIQ扩展而会刮掉空白数据),但是...

chrome_options.add_extension('/dev/shm/3.41.0_0.crx')

立即使驱动程序崩溃。我检查了远程权限,分别是 777 和 666。

编辑 3:可以确认 crx 文件和用户数据应该有一个远程路径,但仍然无法使用扩展名启动远程 Selenium Grid。

【问题讨论】:

【参考方案1】:

首先,让我们澄清一下设置。我的 Windows 笔记本电脑正在运行 Python 3(使用 Anaconda)并且所有应用程序代码都是本地的。我的 Selenium Grid 在 docker 下的云中运行一个 VM,我有 Selenium Grid、Portainer(用于管理 docker)和偶然的 mongdb 以保存抓取的结果。现在一切正常。

目标是在远程 Selenium Grid 上安装扩展,它本质上无法直接与 chrome 交互。所以你不能只是暂停脚本,手动添加扩展,然后继续。通常我们几乎盲目地运行 chrome。

这里有几个对我不起作用的方法。

    训练 Selenium 使用例如 send.keys 通过按键添加扩展。这不起作用,因为安装扩展程序之前的最后一个弹出窗口有“你想安装扩展程序”和“取消”按钮。此弹出窗口来自 chrome.exe 和 Windows 之间的交互,并且不能从 chromedriver 自动执行。它在本地 Windows GUI 中,而不是网页的 DOM 中。

    在本地创建用户数据配置文件,与 chrome 交互以安装扩展程序,并将该配置文件复制到远程计算机。 Chromedriver/Selenium 将使用配置文件,但不会启动扩展。

    使用 crx 文件安装扩展(最常引用的方法)在应用于远程运行的 Selenium Grid 时似乎不起作用。它崩溃了。

我不清楚用户数据和扩展的路径应该在本地 python 机器上还是远程 Selenium 机器上。奇怪的是,当扩展程序的路径是本地的时,有一些异常指的是密钥错误,答案是两者都应该是远程的。

由于我在 docker 下运行,我们需要一个可以上传文件的路径,并且该路径也可用于 docker 内的容器。通过进入 portainer 并检查绑定到该容器的驱动器,我能够确定该驱动器是 dev/shm/ 并且容器和我的 SSH 连接都将通过相同的路径引用它(在 docker 中并非总是如此)。 dev 文件夹位于我的 debian/docker 设置的根目录中。

所以这对我有用

from selenium import webdriver
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
import time


chrome_options = Options()
chrome_options.add_argument("user-data-dir=/dev/shm/vidiqa")
unpacked_extension_path = '/dev/shm/vidiqa/Default/Extensions/pachckjkecffpdphbpmfolblodfkgbhl/3.43.1_0'
chrome_options.add_argument('--load-extension='.format(unpacked_extension_path))
#chrome_options.headless = True
driver = webdriver.Remote(command_executor='http://x.x.x.x:4444/wd/hub', options=chrome_options)
time.sleep(5)
driver.get("chrome://extensions")
driver.save_screenshot('sdriver.png')
print('driver loaded sucessfully')

但是,还需要几个步骤。你会注意到我们没有使用正常的crx

chrome_options.add_extension(path/to/remote/extension/ext.crx)

但是解压文件夹方法

        unpacked_extension_path = '/dev/shm/vidiqa/Default/Extensions/pachckjkecffpdphbpmfolblodfkgbhl/3.43.1_0'
        chrome_options.add_argument('--load-extension='.format(unpacked_extension_path))

要获取此文件夹和内容,请在本地用户数据配置文件中识别该文件夹,然后找到并复制该文件夹。我的文件夹在这里....

C:\Users\charl\OneDrive\python\newuserdata\Default\Extensions\pachckjkecffpdphbpmfolblodfkgbhl

...因为这是我在使用它运行 Selenium 时选择放置它的地方

chrome_options.add_argument("user-data-dir=C:/Users/charl/OneDrive/python/newuserdata")

但还有其他方法。关键是它来自您在本地安装插件的用户数据,在我的情况下,通过使用 time.sleep(120) 行暂停运行并手动安装。

然后您需要将其全部内容复制到您的远程服务器。现在第一次运行上面的代码时,Selenium 将在远程驱动器上创建文件夹...

dev/shm/your_directory_name_for_the_userdata

...它将填充大约 50meg 或更多的数据。什么都不会崩溃,但它不会加载扩展。因此,运行一次以填充用户数据,然后通过 SSH 进入远程目录,并将上面复制的目录发布到

/dev/shm/your_directory_name_for_the_userdata/Default/Extensions/

您需要创建 Extensions 文件夹。当您研究线条时,所有这些都会变得更有意义......

chrome_options.add_argument("user-data-dir=/dev/shm/vidiqa")
unpacked_extension_path = '/dev/shm/vidiqa/Default/Extensions/pachckjkecffpdphbpmfolblodfkgbhl/3.43.1_0'
chrome_options.add_argument('--load-extension='.format(unpacked_extension_path))

然后弄清楚我们在做什么。

    远程创建文件夹以保存用户数据 将扩展(首次运行)复制到 Extensions 文件夹中,如果您手动安装扩展,这将自动完成。 加载扩展。

所以诀窍是您需要手动将扩展复制到用户数据。

每次您希望加载扩展时都必须运行加载扩展代码,它不会像您手动安装时那样记住它。虽然如果扩展程序需要登录,我就是这样做的,这可以使用 selenium 来完成,并且在随后加载驱动程序时会记住该 cookie。我的代码提供了一个快速截图来检查它是否正在工作,它保存在本地的位置蟒蛇。

希望所有这一切都可以节省我花了 10 天时间才弄清楚这一切的过程。顺便说一句,Selenium Grid 是值得的,它会根据运行它的机器自动增加同时运行的驱动程序的数量,每个核心处理器一个。

【讨论】:

谢谢,我觉得这很有帮助。我想知道为什么 add_extension 不起作用。感谢您 10 天的工作 :) ?

以上是关于在本地 Python 3 下将扩展安装到 Selenium Grid(远程驱动程序)到在 docker 下运行的远程服务器的主要内容,如果未能解决你的问题,请参考以下文章

Ubuntu 12.04 LTS:在不破坏依赖关系的情况下将 python 2.7.3 更新到 2.7.6 [关闭]

如何在不使用包的情况下将BERT模型下载到本地?

pycharm环境下将python项目提交到github

linux 服务器下将文件上传到svn服务器

Windows平台下将项目提交到Github上

上传本地代码到github