python - 尝试下载文件时,使用 Python 的 Headless Chrome 会暂停

标签 python python-3.x selenium-webdriver google-chrome-headless

我在 Mac 上使用 Python、Jupyter、Selenium webdriver 和 headless Chrome(带有 Canary)。

我写了一个脚本来抓取一个非常古老的网站, 为了从该网站下载文件,我需要点击几个按钮,这些按钮最终会引导我进入一个按钮,点击后会下载一个 CSV 文件

问题是,当 headless Chrome 尝试下载目标文件时,它会暂停并且什么都不做(即不下载所需的文件),即使脚本已完成运行(是的,我确实在脚本末尾关闭了它)

我试过:

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

我遇到的问题:

  • 我找不到只获取最后一个下载 URL 的方法,因为它似乎使用了一些在此过程中生成的唯一 ID(当您转到主页以及在网站的页面之间导航时会给出)所以每次 session 都会改变
  • 导航 URL 似乎源自主页内的 iframe(以及以下 URL),我不太确定如何检查它生成的 Javascript

我对提供网站 URL 没有任何问题,但是:

  • 您必须在不同的页面上点击大约 6 次,才能到达带有下载按钮的最后一页。这些点击不直观,需要花很多时间才能解释如何导航到我想要的地方
  • 这个网站不是英文的,这会让解释如何导航变得更加困难

我需要它是 headless 的,而不是普通的 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()

感谢帮助

最佳答案

我认为这里有太多事件部件。如果你真的需要 Selenium ,以及所有其他的——好吧——没关系。但是,我会从尽可能简单的事情开始。

在 Python 2.7 上我使用的是 mechanize - 这样我就能够模拟与服务器的整个通信。今天这不是最好的选择,因为 python 3.X 是要走的路。我将描述我是如何处理这类问题的。只是为了给你更好的画面,然后我会尝试描述可能的工具。

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

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

我会更乐意提供准确的示例,但没有服务器信息是不可能的。你能附上你的示例 session 的转储吗?将其匿名化,我将提供样本样本,或者其他工具可能会更好?

关于python - 尝试下载文件时,使用 Python 的 Headless Chrome 会暂停,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48630484/

相关文章:

java - 在运行时切换 WebDriver 的 native 事件功能

python - 使用 oauthlib python 获取 json 时出错

python - 从一行打印 2 个列表

python - 在 Pandas 中使用 group by 进行转换

java - 无法使用 Selenium 在 IE 11 的关闭窗口中找到元素

java - TestNG 中的并行执行

python unhashable 类型 - 发布 xml 数据

python - 使用套接字 API 编写基本的 HTTP 服务器

python-3.x - 用于 3d 数组的 Numpy dstack

python - python中字典值的条件计算