python - 连接重置错误 : [Errno 104] Connection reset by peer and ERR_NAME_NOT_RESOLVED on heroku with mobile testing through Selenium

标签 python selenium selenium-webdriver heroku selenium-chromedriver

我想用 selenium 和 chrome 测试多个移动用户代理。我正在使用 python 3.6 并部署到 heroku。基于 http://chromedriver.chromium.org/mobile-emulation .

您可以在以下位置下载我用于 windows 和 heroku 的项目:

https://github.com/kc1/mobiletest

(请记住,如果您部署到 heroku,则必须将 FLASK_CONFIG 设置为生产。另请注意,项目中的代码与此问题中的代码略有不同,因为我在过去一周一直在使用这些代码。)

我有:
def some_long_calculation():
    driver = create_chromedriver('kkk')
    # driver = create_chromedriver()

    driver.get("https://www.yahoo.com/")
    .....

和 :
def create_chromedriver(ua=False):
    options = webdriver.ChromeOptions()
    CHROMEDRIVER_PATH = os.getenv('$HOME') or basedir+'/chromedriver.exe'
    FLASK_CONFIG = os.getenv('FLASK_CONFIG')

    if ua:

        mobile_emulation = {"deviceName": "Nexus 5"}
        options.add_experimental_option("mobileEmulation", mobile_emulation)


    if FLASK_CONFIG and FLASK_CONFIG == "production":
        CHROMEDRIVER_PATH = '/app/.chromedriver/bin/chromedriver'
        GOOGLE_CHROME_SHIM = os.getenv('$GOOGLE_CHROME_SHIM') or 'no path found'
        options.binary_location = '/app/.apt/usr/bin/google-chrome-stable'

        options.add_argument('--disable-gpu')
        options.add_argument('--no-sandbox')

    return webdriver.Chrome(executable_path=CHROMEDRIVER_PATH, options=options)  

如果我在启用移动浏览器的情况下在本地运行它,它会按预期工作:

enter image description here

如果我在启用移动浏览器的 heroku 上运行它:

enter image description here

然后我在禁用移动用户的情况下在 heroku 上尝试了我得到:

enter image description here

所以至少我知道设置在 chrome 和 chromedriver 中是有效的。

heroku 日志:
2018-07-15T17:37:53.967643+00:00 app[web.1]:     driver = create_chromedriver('kkk')
2018-07-15T17:37:53.967637+00:00 app[web.1]:     png = some_long_calculation()
2018-07-15T17:37:53.967645+00:00 app[web.1]:   File "/app/app/main/cl.py", line 120, in create_chromedriver
2018-07-15T17:37:53.967640+00:00 app[web.1]:   File "/app/app/main/cl.py", line 123, in some_long_calculation
2018-07-15T17:37:53.967648+00:00 app[web.1]:     return webdriver.Chrome(executable_path=CHROMEDRIVER_PATH, options=options)
2018-07-15T17:37:53.967651+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/selenium/webdriver/chrome/webdriver.py", line 75, in __init__
2018-07-15T17:37:53.967654+00:00 app[web.1]:     desired_capabilities=desired_capabilities)
2018-07-15T17:37:53.967656+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py", line 156, in __init__
2018-07-15T17:37:53.967659+00:00 app[web.1]:     self.start_session(capabilities, browser_profile)
2018-07-15T17:37:53.967661+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py", line 251, in start_session
2018-07-15T17:37:53.967669+00:00 app[web.1]:     response = self.command_executor.execute(driver_command, params)
2018-07-15T17:37:53.967664+00:00 app[web.1]:     response = self.execute(Command.NEW_SESSION, parameters)
2018-07-15T17:37:53.967667+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py", line 318, in execute
2018-07-15T17:37:53.967672+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/selenium/webdriver/remote/remote_connection.py", line 472, in execute
2018-07-15T17:37:53.967674+00:00 app[web.1]:     return self._request(command_info[0], url, body=data)
2018-07-15T17:37:53.967677+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/selenium/webdriver/remote/remote_connection.py", line 496, in _request
2018-07-15T17:37:53.967679+00:00 app[web.1]:     resp = self._conn.getresponse()
2018-07-15T17:37:53.967682+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/http/client.py", line 1331, in getresponse
2018-07-15T17:37:53.967685+00:00 app[web.1]:     response.begin()
2018-07-15T17:37:53.967687+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/http/client.py", line 297, in begin
2018-07-15T17:37:53.967695+00:00 app[web.1]:     line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
2018-07-15T17:37:53.967690+00:00 app[web.1]:     version, status, reason = self._read_status()
2018-07-15T17:37:53.967698+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/socket.py", line 586, in readinto
2018-07-15T17:37:53.967692+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/http/client.py", line 258, in _read_status
2018-07-15T17:37:53.967700+00:00 app[web.1]:     return self._sock.recv_into(b)
2018-07-15T17:37:53.967712+00:00 app[web.1]: ConnectionResetError: [Errno 104] Connection reset by peer

我怎样才能解决这个问题?

编辑:

感谢您的详细回答。我已经更改了代码以包含您提到的标志。 Chrome 版本为 67.0.3396.99。 Chromedriver 是 2.40,而 selenium 是 3.13。不幸的是,结果没有变化。我仍然遇到同样的错误。至于你的第 2 阶段和第 3 阶段的建议。我目前正在部署到 heroku,所以我无法完全控制环境变量。有没有办法使用 python 进行这些更改?

编辑2:

当我在 https://sites.google.com/a/chromium.org/chromedriver/mobile-emulation 上想得更多时该示例使用
from selenium import webdriver
mobile_emulation = { "deviceName": "Nexus 5" }
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Remote(command_executor='http://127.0.0.1:4444/wd/hub',
                  desired_capabilities = chrome_options.to_capabilities())

您是否建议浏览器位于' http://127.0.0.1:4444/wd/hub '

最佳答案

ConnectionResetError: [Errno 104] 对等方重置连接

通常,当客户端在没有关闭连接的情况下突然终止时 RST packet由底层操作系统的 TCP/IP 堆栈发送。 Python 将其转换为带有文本 的异常对等方重置连接 .根据您的错误堆栈跟踪,这意味着一次 self._read_status()被调用(内部)Python 假定接收某些东西,但连接突然断开,Python 通过引发异常通知您此错误:

ConnectionResetError: [Errno 104] Connection reset by peer

情况有点类似于this expression :

"Connection reset by peer" is the TCP/IP equivalent of slamming the phone back on the hook. It's more polite than merely not replying, leaving one hanging. But it's not the FIN-ACK expected of the truly polite TCP/IP converseur.



此错误背后可能有多种可能性,如下所示。

解决方案 A 阶段

一种快速而精确的解决方案是添加一些推荐的 ChromeOptions 以及现有的,如下所示:
options.add_argument("start-maximized"); // open Browser in maximized mode
options.add_argument("disable-infobars"); // disabling infobars
options.add_argument("--disable-extensions"); // disabling extensions
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage"); // overcome limited resource problems

进而
return webdriver.Chrome(executable_path=CHROMEDRIVER_PATH, options=options) 

备注 : 您需要删除参数 options.add_argument('--disable-gpu')因为它仅适用于 Windows 操作系统。

解决方案阶段 B

几点:
  • 根据 Python Chrome Mobile Emulation 中的文档键和值对似乎是 "deviceName": "Google Nexus 5" (不是 "deviceName": "Nexus 5")
  • 您可以调整代码以调用 Remote()通过以下任一方式——
  • 调用 Remote()通过 DesiredCapabilities() :
    from selenium import webdriver
    # import DesiredCapabilities was missing in your program
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    
    mobile_emulation = { "deviceName": "Google Nexus 5" }
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
    capabilities = DesiredCapabilities.CHROME
    capabilities = options.to_capabilities()
    driver = webdriver.Remote(command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities = capabilities)
    
  • 您会发现有关调用 Remote() 的类似讨论。通过 ChromeOptions()How to add selenium chrome options to 'desiredCapabilities'?
  • 调用 Remote()通过 ChromeOptions() :
    from selenium import webdriver
    mobile_emulation = { "deviceName": "Google Nexus 5" }
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
    driver = webdriver.Remote(command_executor='http://127.0.0.1:4444/wd/hub', options=chrome_options)
    
  • 您会发现有关调用 Remote() 的类似讨论。通过 ChromeOptions()Remote WebDriver UnreachableBrowserException: Could not start a new session
  • 供您引用,这里是 Webdriver.android 上的文档链接。
  • 供您引用,这里是 Getting started with Selendroid 上的文档链接。


  • 解决方案阶段 C

    如果您仍然看到错误,请执行以下升级/清理任务:
  • 将 Selenium 升级到当前级别 Version 3.13.0 .
  • 将 ChromeDriver 升级到当前版本 ChromeDriver v2.40等级。
  • 将 Chrome 版本保持在 之间Chrome v66-68 水平。 ( as per ChromeDriver v2.40 release notes )
  • 通过 IDE 清理项目工作区并仅使用所需的依赖项重建项目。
  • (仅限 Windows 操作系统)使用 CCleaner在执行测试套件之前和之后清除所有操作系统杂务的工具。
  • (仅限 Linux 操作系统)Free Up and Release the Unused/Cached Memory in Ubuntu/Linux Mint在执行测试套件之前和之后。
  • 如果您的基本 Web 客户端版本太旧,请通过 Revo Uninstaller 卸载它并安装最新的 GA 和发布版本的 Web Client。
  • 进行系统重启。
  • 始终调用 driver.quit()tearDown(){}优雅地关闭和销毁 WebDriver 和 Web Client 实例的方法。
  • 执行您的 @Test .


  • 解决方案阶段 D

    寻找针对特定错误的精细解决方案,我进入了 Amazon S3 and "Connection Reset by Peer" Garry Dolley 将问题的原因概括为以下提到的因素的组合:
  • TCP 窗口缩放
  • Linux 内核 2.6.17 或更新版本

  • Linux kernels 2.6.17+ increased the maximum size of the TCP window/buffer, and this started to cause other gear to wig out, if it couldn’t handle sufficiently large TCP windows. The gear would reset the connection, and we see this as a “Connection reset by peer” message.



    一个潜在的解决方案是将以下条目放在 /etc/sysctl.conf 中:
  • net.ipv4.tcp_wmem = 4096 16384 512000
  • net.ipv4.tcp_rmem = 4096 87380 512000

  • 备注 :这个修复很容易,但它会降低你的最大吞吐量,而不是更快的下载。

    聚苯乙烯

    如果适用,请确保系统上的/etc/hosts 包含以下条目:
    127.0.0.1               localhost.localdomain localhost
    

    相关讨论

    以下是一些相关的讨论:
  • Python socket.error: [Errno 104] Connection reset by peer
  • Yet Another 'Connection reset by peer' Error
  • Connection reset by peer [errno 104] in Python 2.7
  • Remote WebDriver UnreachableBrowserException: Could not start a new session
  • How to add selenium chrome options to 'desiredCapabilities'?


  • 引用

    以下是本次讨论的引用资料:
  • Example Python Chrome Mobile Emulation Automated Unit Testing Using Selenium 2 WebDriver ChromeDriver
  • Amazon S3 and "Connection Reset by Peer"
  • How To: Network / TCP / UDP Tuning
  • How To : Free Up and Release the Unused/Cached Memory in Ubuntu/Linux Mint
  • Mobile Emulation
  • selenium.webdriver.android.webdriver
  • Getting started with Selendroid
  • 关于python - 连接重置错误 : [Errno 104] Connection reset by peer and ERR_NAME_NOT_RESOLVED on heroku with mobile testing through Selenium,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51349410/

    相关文章:

    java - Jenkins 将浏览器 URL 作为 Maven Selenium Java 测试的参数传递

    c# - 如何在 C# 中创建转发方法调用的代理对象?

    javascript - 有/没有 Selenium 运行 Protractor 的区别?

    selenium-webdriver - Selenium 网络驱动程序 : How to get All cookies in the Current page

    python - 使用列表理解表达式用对象填充列表

    python - 通过 pip 安装的 spyder-kernels 模块的 ModuleNotFoundError

    python - 使用 Python/PIL 比较(相似)图像

    python - Pandas :在列上添加重复指标

    java - 自动化框架 - 如何使用 TestNG 和 selenium java 自动化测试生成简单的表格形式 html 报告

    java - Selenium WebDriver 和 InternetExplorer