未知错误:会话因页面崩溃而删除,来源于未知错误:无法确定标签页的加载状态,使用ChromeDriver Selenium时标签页崩溃。

107

我正在使用InstaPy,它使用Python和Selenium。我通过Cron启动脚本,但有时会崩溃。所以这真的很不规则,有时它可以正常运行。我已经在GitHub Repo上发布过了,但那里没有得到答案,所以现在我在这里问是否有人知道原因。

这是一个数字海洋Ubuntu服务器,并且我正在无头模式下使用它。驱动程序版本在日志中可见。以下是错误信息:

ERROR [2018-12-10 09:53:54] [user]  Error occurred while deleting cookies from web browser!
b'Message: invalid session id\n  (Driver info: chromedriver=2.44.609551 (5d576e9a44fe4c5b6a07e568f1ebc753f1214634),platform=Linux 4.15.0-42-generic x86_64)\n'
Traceback (most recent call last):
  File "/root/InstaPy/instapy/util.py", line 1410, in smart_run
    yield
  File "./my_config.py", line 43, in <module>
    session.follow_user_followers(['xxxx','xxxx','xxxx','xxxx'], amount=100, randomize=True, interact=True)
  File "/root/InstaPy/instapy/instapy.py", line 2907, in follow_user_followers
    self.logfolder)
  File "/root/InstaPy/instapy/unfollow_util.py", line 883, in get_given_user_followers
    channel, jumps, logger, logfolder)
  File "/root/InstaPy/instapy/unfollow_util.py", line 722, in get_users_through_dialog
    person_list = dialog_username_extractor(buttons)
  File "/root/InstaPy/instapy/unfollow_util.py", line 747, in dialog_username_extractor
    person_list.append(person.find_element_by_xpath("../../../*")
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/webelement.py", line 351, in find_element_by_xpath
    return self.find_element(by=By.XPATH, value=xpath)
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/webelement.py", line 659, in find_element
    {"using": by, "value": value})['value']
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: session deleted because of page crash
from unknown error: cannot determine loading status
from tab crashed
  (Session info: headless chrome=70.0.3538.110)
  (Driver info: chromedriver=2.44.609551 (5d576e9a44fe4c5b6a07e568f1ebc753f1214634),platform=Linux 4.15.0-42-generic x86_64)

During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
  File "/root/InstaPy/instapy/instapy.py", line 3845, in end
    self.browser.delete_all_cookies()
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/webdriver.py", line 878, in delete_all_cookies
    self.execute(Command.DELETE_ALL_COOKIES)
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: chrome not reachable
  (Session info: headless chrome=71.0.3578.80)
  (Driver info: chromedriver=2.44.609551 (5d576e9a44fe4c5b6a07e568f1ebc753f1214634),platform=Linux 4.15.0-42-generic x86_64)

你有任何想法原因可能是什么以及如何解决?

感谢提供意见。那些来自http://treestones.ch/的人帮了我。

9个回答

235

虽然您看到的错误是:

Error occurred while deleting cookies from web browser!
b'Message: invalid session id\n  (Driver info: chromedriver=2.44.609551 (5d576e9a44fe4c5b6a07e568f1ebc753f1214634),platform=Linux 4.15.0-42-generic x86_64)\n'

主要的例外是:
selenium.common.exceptions.WebDriverException: Message: unknown error: session deleted because of page crash
from unknown error: cannot determine loading status
from tab crashed

您的代码试验可能会给我们一些线索,了解出现了什么问题。


解决方案

有很多种解决此问题的方法。但是根据UnknownError: session deleted because of page crash from tab crashed,可以通过以下任何一种解决方案来解决该问题:

  • Add the following chrome_options:

    chrome_options.add_argument('--no-sandbox')         
    
  • Chrome seem to crash in Docker containers on certain pages due to too small /dev/shm. So you may have to fix the small /dev/shm size.

  • An example:

    sudo mount -t tmpfs -o rw,nosuid,nodev,noexec,relatime,size=512M tmpfs /dev/shm
    
  • It also works if you use -v /dev/shm:/dev/shm option to share host /dev/shm

  • Another way to make it work would be to add the chrome_options as --disable-dev-shm-usage. This will force Chrome to use the /tmp directory instead. This may slow down the execution though since disk will be used instead of memory.

    chrome_options.add_argument('--disable-dev-shm-usage')        
    

来自标签崩溃

来自标签崩溃 是与Chromium团队相当长时间的WIP (Work In Progress) 相关,这涉及到Linux尝试始终使用/dev/shm作为非可执行内存。以下是参考资料:


参考资料

您可以在以下位置找到一些相关讨论:


5
我也遇到了同样的错误,按照建议尝试了一切,但问题仍然无法解决,错误还在持续。还有其他不同的建议吗? - JB_
14
使用 chrome_options.add_argument('--disable-dev-shm-usage') 参数后,我终于解决了长达5小时的标签崩溃问题。非常感谢您的分享! - Thomas Luijken
4
这是我第二次重新查看此SO解决方案。总的来说,似乎添加这些选项确实能够减少“无法确定加载状态”和“来自选项卡的崩溃”的可能性,但偶尔我仍会遇到这个问题,不过很少,像在10-20次测试中只有1次,所以我只需重新尝试测试即可。我正在使用最新版本的Chrome和Selenium,因此真的希望这个问题能够得到很好的调查。好吧,也许我的/dev/shm对于Selenium来说有时太小了,即使有--disable-dev-shm-usage - Shawn
3
这个解决方案解决了我的问题。我在一个 Docker 容器内,并使用 -v /dev/shm:/dev/shm 解决了这个问题。 - Rafael
4
options.addArguments("--disable-dev-shm-usage") 可以正常工作! - Smart Coder
显示剩余6条评论

23

如果有人遇到使用Docker容器时出现以下问题:

在创建容器时使用标志--shm-size=2g,错误将会消失。

此标志使容器使用主机的共享内存。

例如:

$ docker run -d --net gridNet2020 --shm-size="2g" -e SE_OPTS="-browser applicationName=zChromeNodePdf30,browserName=chrome,maxInstances=1,version=78.0_debug_pdf" -e HUB_HOST=selenium-hub-3.141.59 -P -p 5700:5555 --name zChromeNodePdf30 -v /var/lib/docker/sharedFolder:/home/seluser/Downloads selenium/node-chrome:3.141.59-xenon

来源: https://github.com/SeleniumHQ/docker-selenium


我认为--shm-size='64m'是默认值,因此请尽量将其保持最小化。 - MortenB
7
docker-compose.yml 文件中,可以通过为每个服务指定 shm_size: 2g 来设置共享内存大小。 - fiedl

3
我在我的Ubuntu服务器上遇到了以下错误: 原来这个错误的原因是服务器磁盘空间不足,解决方法是 扩展磁盘空间。您可以查看this question以获取更多信息。

2

上面的回答解决了我的问题,但由于我需要从docker-compose.yml运行它,我使用了这个配置,它调用了我的常规未更改的DockerFile。

docker-compose.yml

version: '1.0'
services:
  my_app:
    build:
      context: .
      #when building
      shm_size: 1gb
    #when running  
    shm_size: 1gb

DockerFile (selenium on Ubuntu -WSL-)

FROM python:3.10

# install google chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
RUN apt-get -y update
RUN apt-get install -y google-chrome-stable

# install chromedriver
RUN apt-get install -yqq unzip
RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/

# set display port to avoid crash
ENV DISPLAY=:99

# install selenium
RUN pip install selenium==3.8.0


#install and prepar app

COPY ./requirements.txt ./
# COPY . /app
RUN pip3 install -r requirements.txt
RUN apt-get install -y libnss3

ENV APP_DIR=/app/my_app
RUN mkdir -p ${APP_DIR}
WORKDIR ${APP_DIR}

# COPY . ${APP_DIR} #not needed since we are mapping the volume in docker-compose

CMD [ "my_app.py" ]
ENTRYPOINT [ "python" ]

1
shm_size: 1gb添加到docker-compose.yml文件中对我解决了问题。 - Mark7888

1
我们需要单独指定shm内存,--shm-size=2g。在Docker的情况下,使用以下配置 - 这对我来说很好用。

服务: chrome: 图像:selenium/node-chrome:4.0.0-rc-1-prerelease-20210823 shm_size:2gb


0

这件事发生在我尝试使用相同的驱动程序Chromium中打开一个新网页时。在我使用Chrome的本地机器上,它运行良好。

没有成功:

driver = webdriver.Chrome(options=options)
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
driver.execute_cdp_cmd('Network.setUserAgentOverride', {
        "userAgent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.53 Safari/537.36'})

driver.get('url1')
# Do operations with url1

driver.get('url2')
# Do operations with url2 -> did not work and crashed

以下是我的解决方案,我正在使用它并且它对我有效。即重新初始化驱动程序
def setup_driver():
    global driver
    driver = webdriver.Chrome(options=options)
    driver.maximize_window()
    driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
    driver.execute_cdp_cmd('Network.setUserAgentOverride', {
        "userAgent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.53 Safari/537.36'})


setup_driver()
driver.get('url1')
# Do operations with url1
driver.close()

setup_driver()
driver.get('url2')
# Do operations with url2
driver.close()

在你的“没有工作”的例子中,你关闭了驱动程序吗?而且你是否一直收到错误?如果你根本没有关闭驱动程序并且这不是一致的,那么也许你遇到的是我在答案中描述的情况,所以只需要在最后关闭一次。 - Arnon Axelrod
是的,实际上我在 try 结尾处关闭了它,但它仍然没有起作用。而且崩溃是一致的,甚至没有通过一次。 - Praveen

0
Message: unknown error: session deleted because of page crash from unknown error: cannot determine loading status from tab crashed
(Session info: headless chrome=95.0.4638.69)

这个错误是因为网页加载的等待时间不够所致。

2
你是怎么得出那个错误信息的结论的? - Christian

0

我不确定这是否是唯一的可能原因和解决方案,但在彻底调查了我经常遇到的错误后,我发现了以下证据:

  1. 在 Selenium Grid 节点的日志中(您可以通过在 docker 主机上执行以下命令来显示:sudo docker logs <container-id>),我发现许多错误信息: [SEVERE]: bind() failed: Cannot assign requested address (99)。从我所读的内容来看,这个错误通常意味着没有可用的端口。
  2. 当显示节点内运行的进程时(sudo docker exec -it bash 然后 ps aux),我发现有超过 300 个 chrome-driver 进程(您可以使用 ps aux|grep driver|wc -l 计算它们)

当在本地运行时,我知道当您创建 ChromeDriver 实例时通常会调用 chrome-driver 进程,并且在调用 driver.Quit() 时终止该进程(我使用 C#,而不是 Python)。因此,我得出结论,某些测试未调用 drive.Quit()

结论

在我的情况下,我发现即使我们在 [TearDown] 方法中调用了 driver.Quit()(我们使用 NUnit),但在该行代码之前还有一些可能会抛出异常的代码。当其中一个前面的行抛出异常时,调用 driver.Quit() 的行就不会被执行,因此随着时间的推移,我们在 Selenium Grid 节点上“泄漏”了chrome-driver进程。这些孤立的进程导致可用端口的资源泄漏(可能还包括内存),从而导致浏览器页面崩溃。

解决方案

鉴于上述结论,解决方案非常简单。我们必须将 driver.Quit() 之前的代码放在 try/finally 中,并将调用 driver.Quit() 的语句放在 finally 子句中,如下所示:
[TearDown]
public void MyTearDown()
{
       try
       {
              // Perform any tear down code you like, like saving screenshots, page source, etc.
       }
       finally
       {
              _driver?.Quit();
       }
}

-2

我曾经遇到过同样的问题,我检查了我的脚本日志,找到了出错的位置,并在出错前加入了一些等待时间,例如:time.sleep(2),这样我的问题就解决了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接