【问题标题】:How to download csv file with QWebEngineView and QUrl如何使用 QWebEngineView 和 QUrl 下载 csv 文件
【发布时间】:2019-09-21 15:40:56
【问题描述】:

我正在构建一个程序,它使用 QWebEngineViewQUrl 在我的 PyQt5 应用程序(在 Windows 10 上运行)中显示一个网站。但是,我现在希望能够从同一个网站下载 CSV 文件,但作为菜鸟,我似乎无法弄清楚如何。

我熟悉使用requestsurllib.requesturllib3 等来下载文件,但为此,我特别想使用 QWebEngineView 来完成,因为用户之前已经验证了请求在 pyqt5 窗口中。 首先显示网站的代码如下:

self.view = QWebEngineView(self)
self.view.load(QUrl(url))
self.view.loadFinished.connect(self._on_load_finished)
self.hbox.addWidget(self.view)

有人对如何实现这一点有任何建议吗?

【问题讨论】:

  • 您可以提供网址,如有必要,还可以提供凭据。 QWebEngineView 用作浏览器,您只需点击文件即可下载
  • 网站是link,但很遗憾我无法提供凭据。没有可单击的按钮,只有在我的程序中创建的 url,如果我打印它并复制并粘贴到 chrome 中,如果我已经与我的程序在同一页面上,则下载文件(有趣的是,它也会关闭选项卡,不t 显示任何内容)。我试过只做一个.load(QUrl(url)),但它什么也没做......我想我需要以某种方式设置一个下载目录?
  • 好的,但是当你得到 url 时就不再需要认证了
  • 我最初是这么认为的,但是如果我尝试运行 urllib.request.urlretrieve(url, "test.csv") 它只会使程序崩溃(尽管该代码适用于我尝试过的图像)。
  • 您指定的网页是生成下载网址还是您的脚本生成的?

标签: python pyqt pyqt5 qtwebengine qwebengineview


【解决方案1】:

在 QWebEngineView 中,默认情况下不处理下载,要启用它,您必须使用 QWebEngineProfile 的 downloadRequested 信号,这会传输一个 QWebEngineDownloadItem,如果您希望开始下载,您必须接受它:

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.view = QtWebEngineWidgets.QWebEngineView()
        self.view.page().profile().downloadRequested.connect(
            self.on_downloadRequested
        )
        url = "https://domain/your.csv"
        self.view.load(QtCore.QUrl(url))
        hbox = QtWidgets.QHBoxLayout(self)
        hbox.addWidget(self.view)

    @QtCore.pyqtSlot("QWebEngineDownloadItem*")
    def on_downloadRequested(self, download):
        old_path = download.url().path()  # download.path()
        suffix = QtCore.QFileInfo(old_path).suffix()
        path, _ = QtWidgets.QFileDialog.getSaveFileName(
            self, "Save File", old_path, "*." + suffix
        )
        if path:
            download.setPath(path)
            download.accept()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

如果要直接下载可以使用QWebEnginePage的下载方法:

self.view.page().download(QtCore.QUrl("https://domain/your.csv"))

更新:

@QtCore.pyqtSlot("QWebEngineDownloadItem*")
def on_downloadRequested(self, download):
    old_path = download.url().path()  # download.path()
    suffix = QtCore.QFileInfo(old_path).suffix()
    path, _ = QtWidgets.QFileDialog.getSaveFileName(
        self, "Save File", old_path, "*." + suffix
    )
    if path:
        download.setPath(path)
        download.accept()
        download.finished.connect(self.foo)

def foo(self):
    print("finished")

【讨论】:

  • 感谢您的回答,非常感谢。为了完整起见,您能否包含一个在下载完成时触发的函数?
  • @codeacker 使用 download.finished.connect(foo_function) doc.qt.io/qt-5/qwebenginedownloaditem.html#finished
  • 我在download.accept() 之后直接添加了它,它完美运行并运行该功能(只是打印),但随后程序立即崩溃并且文件不再下载。如果我注释掉该行,文件下载但(显然)不运行该功能。我在正确的地方有那条线吗?请原谅菜鸟的问题!
  • @codeacker 没有minimal reproducible example 我无法告诉你错误在哪里,我只会限制自己在我的答案更新中展示一个例子。如果它不适合您,那么如果您需要帮助,则必须提供 MCVE。
  • 看来我们现在在 Qt 6.2 中为 QWebEngineDownloadRequest 类设置了 setDownloadDirectory() / setDownloadFileName() 而不是 setPath()。
猜你喜欢
  • 2018-10-14
  • 2014-01-17
  • 2015-10-12
  • 1970-01-01
  • 1970-01-01
  • 2019-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多