ConnectionResetError:[Errno 104]通过Selenium进行移动测试的heroku上的对等方和ERR_NAME_未解决的连接重置

2024-06-02 07:17:09 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

https://github.com/kc1/mobiletest

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

我有:

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。铬离子浓度为2.40,硒离子浓度为3.13。不幸的是,结果没有变化。我还是犯了同样的错误。至于你的第二和第三阶段建议。我目前正在部署到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


Tags: inpyselfapphttpherokuremotelib
2条回答

特定的错误信息显示

android's server IP address could not be found.

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

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

通常,当客户端在未关闭连接的情况下突然终止时,底层操作系统的TCP/IP堆栈将发送RST packet。Python将此转换为一个异常,其文本为peer重置的连接。根据您的错误堆栈跟踪这意味着,一旦调用了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

一个快速而精确的解决方案是在现有方案的基础上添加一些推荐的色度,如下所示:

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

几点:

  • 根据^{}中的文档,对似乎是"deviceName": "Google Nexus 5"(不是"deviceName": "Nexus 5"
  • 您可以通过以下任一方式调整代码以调用Remote()-

    • 通过DesiredCapabilities()调用Remote()

      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)
      
    • 您可以在How to add selenium chrome options to 'desiredCapabilities'?中找到关于调用Remote()ChromeOptions()的类似讨论

    • 通过ChromeOptions()调用Remote()

      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 UnreachableBrowserException: Could not start a new session中找到关于调用Remote()ChromeOptions()的类似讨论

  • 这里是^{}上文档的链接,供您参考
  • 这里是指向^{}文档的链接,供您参考

解决方案阶段C

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


解决方案阶段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.

pottential解决方案是将以下条目放入/etc/sysctl.conf

  • net.ipv4.tcp_wmem=4096 16384 512000
  • net.ipv4.tcp\u rmem=4096 87380 512000

注意:这个修复很简单,但它会降低您的最大吞吐量和更快的下载速度。


聚苯乙烯

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

127.0.0.1               localhost.localdomain localhost

相关讨论

以下是一些相关的讨论:


参考文献

以下是本次讨论的参考资料:

相关问题 更多 >