ConnectionResetError:[Errno 104]由对等端和ERR_NAME_NOT_RESOLVED在heroku上重置连接,并通过Selenium进行了移动测试

时间:2018-07-15 14:37:54

标签: python selenium selenium-webdriver heroku selenium-chromedriver

我想用硒和铬测试多个移动用户代理。我正在使用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,硒是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

2 个答案:

答案 0 :(得分:6)

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

通常,当客户端突然终止而不关闭连接时,基础操作系统的 TCP / IP 堆栈会发送RST packet。 Python将其转换为带有文本由对等方重置的连接的异常。根据您的错误堆栈跟踪,这意味着一旦self._read_status()被(内部)调用, Python 就会假定收到了某些东西,但是连接突然中断了,并且 Python 通过引发异常来通知您该错误:

ConnectionResetError: [Errno 104] Connection reset by peer

情况与this expression类似:

  

“由对等方重置连接”是TCP / IP的等效功能,它相当于将电话猛击回挂机。礼貌比不回信,挂个电话更礼貌。但这不是真正礼貌的TCP / IP转换程序的FIN-ACK。

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


解决方案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" (不是{ {1}})
  • 您可以通过以下两种方法之一来调整代码以调用"deviceName": "Nexus 5"-

    • 通过Remote()调用Remote()

      DesiredCapabilities()
    • 您在How to add selenium chrome options to '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()调用Remote()

      ChromeOptions()
    • 您在Remote WebDriver UnreachableBrowserException: Could not start a new session

      中找到了关于通过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()的类似讨论

  • 供您参考的是Webdriver.android
  • 上文档的链接
  • 供您参考的是Getting started with Selendroid
  • 上文档的链接

解决方案阶段C

如果仍然看到错误,请执行以下升级/清理任务:

  • 升级到当前水平Version 3.13.0
  • ChromeDriver 升级到当前的ChromeDriver v2.40级别。
  • Chrome 版本保持在 Chrome v66-68 级别之间。 (as per ChromeDriver v2.40 release notes
  • 通过您的 IDE
  • 清理您的项目工作区重建您的项目,并且仅具有必需的依赖项。
  • (仅适用于 WindowsOS )使用CCleaner工具清除执行 Test Suite 前后的所有操作系统琐事。
  • (仅仅LinuxOS Free Up and Release the Unused/Cached Memory in Ubuntu/Linux Mint在执行 Test Suite 之前和之后。
  • 如果您的基本 Web客户端版本过旧,请通过Revo Uninstaller进行卸载,并安装最新版本的 Web客户端。 li>
  • 进行系统重启
  • 始终在ChromeOptions()方法内调用driver.quit(),以优雅地关闭和销毁 WebDriver Web Client 实例。
  • 执行您的tearDown(){}

解决方案阶段D

寻找针对特定错误的精细解决方案,我走进了Amazon S3 and "Connection Reset by Peer",其中Garry Dolley将问题原因归纳为以下提到的因素的组合:

  • TCP窗口缩放比例
  • Linux内核2.6.17或更高版本
  

Linux内核2.6.17+增加了TCP窗口/缓冲区的最大大小,如果它不能处理足够大的TCP窗口,这开始引起其他麻烦。齿轮将重置连接,我们将其视为“对等连接重置”消息。

可能的解决方案是将以下条目放入@Test中:

  • net.ipv4.tcp_wmem = 4096 16384 512000
  • net.ipv4.tcp_rmem = 4096 87380 512000

注意:此修补程序很简单,但会减慢最大下载速度的最大交换速度。


PS

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

/etc/sysctl.conf

相关讨论

以下是一些相关讨论:


参考

以下是此讨论的参考:

答案 1 :(得分:2)

具体错误消息说

  找不到

android 的服务器IP地址。

对我来说,这表明浏览器正在尝试为android查找DNS条目,该条目不是有效的TLD。偶然地,浏览器是否尝试访问http://android,而不是https://www.google.com之类的东西?通过在地址栏中键入http://android,可以在自己的Chrome浏览器中复制相同的错误消息。这使我相信为浏览器指定正确的URL应该可以解决问题。