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

Installing extensions into Selenium Grid (remote driver) under local Python 3 to a remote server running under docker

我已经更改了这个 post 的标题以便于查找,并且已经解决了这个问题。请参阅下面我的回答。

旧标题 - Selenium Grid 4.0.0.Beta-1 Docker driver 在添加 chrome 扩展时崩溃我的 python 应用程序,而 Selenium local 没有

我到处寻找最近的答案并尝试了大部分旧的答案(所以请不要将其标记为重复)和 google 向我展示的每个网站..目前没有任何效果.我想使用最新版本的 Selenium Grid(Docker 图像),我已经设置好它并可以正常工作,只要我没有安装扩展或定义用户目录,我就可以远程抓取数据,因为跟随...

此代码确实有效,但它在本地浏览器上运行,而不是在 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.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.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:赋值前引用的局部变量'driver' PS C:\Users\charl\OneDrive\dataharvest\visualstudio>

这个错误实际上只是意味着 driver 没有正确配置,因为所有其他代码都是相同的。现在我明白 Whosebug 上的一些解决方案使用 DesiredCapabilities 方式,但我被告知这已被弃用,并且 none 已经工作所以如果有人在 Python 3,Selenium Grid 4 docker,如果知道我将不胜感激。

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

编辑 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')

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

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

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

objective,将扩展安装到远程 Selenium Grid 上,其本质上无法直接与 chrome 交互。所以你不能只是暂停脚本,手动添加扩展,然后继续。通常我们 运行 chrome 几乎失明了。

这里有一些方法对我不起作用。

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

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

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

我不清楚文档是用户数据和扩展的路径应该在本地 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")

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

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

dev/shm/your_directory_name_for_the_userdata

...它将填充大约 50 兆或更多的数据。什么都不应该崩溃,但它不会加载扩展。所以运行它一次填充用户数据,SSH到远程目录和post你上面复制的目录到

/dev/shm/your_directory_name_for_the_userdata/Default/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))

并弄清楚我们在做什么。

  1. 正在远程创建文件夹以将用户数据保存到
  2. 将扩展(第一次 运行)复制到 Extensions 文件夹中,如果您手动安装扩展,该操作会自动完成。
  3. 加载扩展程序。

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

加载扩展代码必须是 运行 每次你想要加载扩展时,它不会像你手动安装时那样记住它。尽管如果扩展需要登录(我的也是如此),这可以使用 selenium 完成,并且在后续加载 driver.My 代码时会记住该 cookie 提供快速屏幕截图以检查它是否正常工作,并保存在本地位置你的 python.

希望所有这一切将节省我花了 10 天的时间来解决所有这些问题。 Selenium Grid 是值得的 顺便说一句,它会根据机器 运行ning 自动增加并发驱动程序的数量 运行ning,每个核心处理器一个。