尝试下载文件时,无头chrome与python挂起

Gid*_*eon 8 python python-3.x selenium-webdriver google-chrome-headless

我在Mac上使用Python,Jupyter,Selenium webdriver和无头镀铬(带Canary).

我写了一个脚本来刮擦一个非常古老的网站,为了从该网站下载文件,我需要点击几个按钮,最终将我带到一个按钮,一旦点击它就下载一个CSV文件

问题是当无头镀铬尝试下载目标文件时,它会暂停并且什么也不做(即不下载所需的文件),即使脚本已经完成运行(是的,我确实在脚本结束时将其关闭)

我试过了:

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

我面临的问题:

  • 我找不到一种方法来获取最后一个下载URL,因为它似乎使用了一路上生成的一些唯一ID(当您转到主页时以及当您在站点中的页面之间导航时)会议将改变
  • 导航网址似乎来自主页内部的iframe(以及以下网址),我不太确定如何检查其生成的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()
Run Code Online (Sandbox Code Playgroud)

谢谢您的帮助

ZF0*_*007 0

因为您没有提供下载其猜测工作的 URL。Target 很可能安装了类似 recapta 的墙壁,以防止刮擦。因此,请确保您不会遇到“重述”墙,并且如果您确实实现了通知您执行手动任务以授予访问权限的代码。

对于 js,这个解决方案由 zavodnyuk在这里给出:

尝试设置兼容的自定义用户代理(例如从您真实的浏览器)。功能:{ 'browserName':'chrome',chromeOptions:{args:[“user-agent = Mozilla / 5.0(X11;Linux x86_64)AppleWebKit / 537.36(KHTML,如Gecko)Chrome / 60.0.3112.113 Safari / 537.36”, "--headless", "--disable-gpu" ] } 适用于 js 上的 selenium/protractor

我希望这能提示您正确的方向,因为互联网上没有太多关于 python 的描述。

根据评论1进行编辑:

在基本调试模式下,我依赖于可能的候选定义开始处的打印语句。我说的 printstatement 它也可以是写入文件的行。不依赖第三方精美的软件包,因为我大多数时候都想从代码中学习,然后上述方法很耗时,但非常值得花费时间。比如我如何直白地调试:

def header_inspect(self, ID, action, data):
    print  'header_inspect, ID : %s\n, action : %s\nprocess-data : %s' % (ID, action, data)
Run Code Online (Sandbox Code Playgroud)