尝试下载fi时,使用python的无头chrome会挂起

2024-04-26 00:37:56 发布

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

我在Mac上使用Python、Jupyter、Selenium webdriver和headless chrome(带金丝雀)。在

我写了一个脚本,把一个很旧的网站, 为了从那个网站下载一个文件,我需要点击几个按钮,这最终导致我进入一个按钮,一旦点击它下载一个CSV文件

问题是当headless chrome试图下载目标文件时,它会挂起并且什么也不做(即不下载所需的文件),即使脚本已经运行完毕(是的,我确实在脚本末尾关闭了它)

我试过了:

  • 下载其他文件(从不同的网站)和headless chrome似乎下载它们没有任何问题(我启用了headless chrome选项成功下载文件)
  • 拍下网站的快照以确保它能正确地导航到下载页面(是的,它的导航是正确的)
  • 修改用户代理(它似乎在使用我希望它使用的用户代理)
  • 运行完全相同的代码,没有headless选项-它下载文件成功与普通chrome
  • 使用driver.execute_script(js_that_changes_plugins_and_langs)更改驱动程序上的插件和语言JS脚本,但我不太确定如何检查它是否真正执行了它(它仍然不工作)

我面临的问题:

  • 我找不到一种方法来获取最后一个下载的URL,因为它似乎使用了一些沿途生成的独特id(当你进入主页和在站点中的页面之间导航时会给出它),所以对于每个会话,它都会发生变化
  • 导航url似乎来自主页内的iframes(以及以下url),我不太确定如何检查Javascript的生成

我没有任何问题提供网站网址,但:

  • 你必须在不同的页面上点击大约6次,才能通过下载按钮到达最后一页。这些点击不是直观的,它将需要很多来解释如何导航到我想要的地方
  • 这个网站不是英文的,这将使解释如何导航更加困难

我需要它是无头的,而不是普通的chrome,因为我们要运行代码的机器非常弱,不能运行chrome GUI

所以我的问题是:有人知道问题出在哪里吗?或者至少,我如何调试它?在

这或多或少就是我使用的代码: 在

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def enable_download_in_headless_chrome(driver, download_dir):
        """
        there is currently a "feature" in chrome where
        headless does not allow file download: https://bugs.chromium.org/p/chromium/issues/detail?id=696481
        This method is a hacky work-around until the official chromedriver support for this.
        Requires chrome version 62.0.3196.0 or above.
        """

        # add missing support for chrome "send_command"  to selenium webdriver
        driver.command_executor._commands["send_command"] = ("POST", '/session/' + driver.session_id + '/chromium/send_command')

        params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': download_dir}}
        command_result = driver.execute("send_command", params)
        print("response from browser:")
        for key in command_result:
            print("result:" + key + ":" + str(command_result[key]))

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('headless')
chrome_options.add_argument('no-sandbox')
chrome_options.add_argument('disable-gpu')
chrome_options.add_argument('remote-deubgging-port=9222')
chrome_options.add_argument('disable-popup-blocking')
chrome_options.add_argument('enable-logging')
download_dir = # some path here
driver = webdriver.Chrome(chrome_options=chrome_options)
enable_download_in_headless_chrome(driver, download_dir)
ok_button = driver.find_element_by_id('the-button-name')
ok_button.click()

谢谢你的帮助


Tags: 文件in脚本addid网站downloaddriver
3条回答

在没有具体信息的情况下,我们能给你的唯一建议似乎与你如何理解正在发生的事情有关。在

头模式下,以为调试目的,一步一步地进行手动怎么样?这里的赌注是你的问题在于自动化你的任务而不是无头。在

使用您的所有导入和函数定义(例如enable_download_in_headless_chrome)执行脚本,不使用这些定义。实际上,一直这样做直到download_dir = # some path here,然后在pythonshell中输入

>>> driver = webdriver.Chrome(chrome_options=chrome_options)

现在手动与浏览器交互,打开Chrome DevTools,然后转到Console。确保错误will be displayed。让我们继续并键入其余命令

^{pr2}$

上面写着什么?在

我觉得这里的活动部件太多了。如果你真的需要硒,还有其他的-好吧-没关系。不过,我会从尽可能简单的事情开始。在

在Python2.7上,我使用mechanize-这样我就可以模拟与服务器的整个通信。今天,这并不是最好的选择,因为Python3.X是最好的选择。我来描述一下我是如何处理这类问题的。只是为了给你一个更好的描述,然后我将试着描述可能的工具。在

所以典型的例子是登录,浏览页面,打开一些开关,触发下载,或者获取内容并用beautiful soup处理。首先,您需要查看交换了哪些信息。转到web浏览器中的“开发工具”,然后选择“网络”选项卡。也许你知道这一点,但这一步是强制性的,我想写下一般的答案。然后做你的正常工作-只需登录,然后执行其他步骤。服务器需要处理的所有内容都必须被传输,因此您可以将其视为网络请求。Mechanize很好,因为我可以准备dict,并将其作为post请求发送到页面。这是一个典型的错误。所以,如果您访问了index.html,那么您正在该页面上执行post,而服务器希望它被发送到add_user_data.html,然后您将被重定向。像session id这样的东西,可以由header entry或cookie来支持——只需看看网络通信的模式。在

正如我所写的,Python2.7即将停产。Mechanize不适用于python3.x,因此应该使用其他工具。你可以寻找机械化的替代品,看看什么是适合你的。典型的答案是scrapy。这是一个有点不同的工具,更多的是用来废弃网页。所以,若你们计划更大的计划,也许这是最好的选择。如果您需要单个脚本-我将从httpie开始。命令行工具/python包,良好的OSX支持,可以send formsession management也可用。我每天都在使用它,但是我的服务器是无状态的。在

我会更乐意提供确切的例子,但没有服务器信息,这是不可能的。你能附上你的样本会话的转储吗?匿名,我会提供样本,或者其他工具也可以是peter?在

因为你不提供网址,你从那里下载它的猜测工作。目标很可能安装了一个类似repta的墙来防止刮擦。因此,请确保您没有碰到这个“重述”墙,如果您实现了代码,通知您执行手动任务以授予访问权。在

对于js,此解决方案由zavodnyuk here

try to set custom User-Agent with compatible one (e.g. from your real browser). capabilities: { 'browserName': 'chrome', chromeOptions: {args: [ "user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36", " headless", " disable-gpu" ] } worked for selenium/protractor on js

我希望这能给你一个正确的方向,因为互联网上没有太多关于python的描述。在

根据注释1编辑:

在基本调试模式下,我依赖于可能的候选def开头的print语句。我说的printstatement也可以是文件的一个写行。不依赖第三方花哨的软件包,因为我想学习代码的大多数时候,然后是以上方法耗时,但很值得努力花时间。例如,我如何直接调试:

def header_inspect(self, ID, action, data):
    print  'header_inspect, ID : %s\n, action : %s\nprocess-data : %s' % (ID, action, data)

相关问题 更多 >