如何通过 QNetworkAccessManager 找出确切的 url 下载图像

How to find out the exact url for downloading images by QNetworkAccessManager

我正在使用 QNetworkAccessManager 下载图片。

第一次必须指定图片的url

但手段不同

例如,我从 Wikipedia Top Page Japanese.

的图像中获取

有一些正在上传的图片。

如果我复制文本和图像,然后将它们粘贴到我的编辑器中, html 文本包含 url.

即使我将它传递到 QNetworkRequest,我也无法下载图像。

在我深入研究 url 并到达 Wikipedia Commons 中的图像文件后, 如果我将 url 传递到 QNetworkRequest,我可以下载图像。

我已经明白url一定是准确的,但我不知道如何区分它们。

你知道如何以编程方式下载图片,每次都不会出错吗?

有没有办法提前知道确切的url?

我对网络了解不多

我经常接受UnknownContentError

示例代码如何使用

Ctrl+C复制文字和图片(请包含图片。) Ctrl+V 粘贴html & 下载图片

Q直接下载图片。我只能靠这个下载

示例代码

from PySide import QtCore, QtGui, QtNetwork
from bs4 import BeautifulSoup
import sys, os, re
class Widget(QtGui.QTextEdit):
    def __init__(self, parent=None):
        super(Widget, self).__init__()   

    def keyPressEvent(self, event):
        if event.modifiers() == QtCore.Qt.KeyboardModifier.ControlModifier and event.key() == QtCore.Qt.Key_C:
            tc = self.textCursor()                       
            mimedata = self.createMimeDataFromSelection()
            clipboard = QtGui.QApplication.clipboard()
            clipboard.setMimeData(mimedata)
            start = tc.selectionStart()
            end = tc.selectionEnd()                   
            char = tc.charFormat()
            char.clearBackground()
            tc.setCharFormat(char)             
            return 
        elif event.modifiers() == QtCore.Qt.KeyboardModifier.ControlModifier and event.key() == QtCore.Qt.Key_V:
            clipboard = QtGui.QApplication.clipboard()

            html = clipboard.mimeData().html()                      
            pous = BeautifulSoup(html,"lxml")
            image_items  = pous.find_all('a', href=re.compile('(\.jpg|\.png|\.svg|\.gif)$'))
            image_urls = [item.get('href') for item in image_items]      
            for i, url in enumerate(image_urls):                    
                #indirect url  https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Oguri_Cap_in_Yushun_Stallion_station.jpg
                print(url)
                request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))       
                self.nam = QtNetwork.QNetworkAccessManager() 
                self.nam.finished[QtNetwork.QNetworkReply].connect(self.doReply)
                self.nam.get(request)
        if event.key() == QtCore.Qt.Key_Q:
            self.doRequest()
    def doRequest(self):        
        # direct url & exact url
        url = "https://upload.wikimedia.org/wikipedia/commons/c/c3/Oguri_Cap_in_Yushun_Stallion_station.jpg"
        req = QtNetwork.QNetworkRequest(QtCore.QUrl(url))    
        self.nam = QtNetwork.QNetworkAccessManager()     
        self.nam.finished[QtNetwork.QNetworkReply].connect(self.doReply)       
        self.nam.get(req)    
    def doReply(self, reply):
        er = reply.error()
        if er == QtNetwork.QNetworkReply.NoError:    
            data = reply.readAll()            
            self.saveImage(data)                    
        else:
            print( "Error occured: ", er)
            print(  reply.errorString())
    def saveImage(self, data):
        try:           
            im = QtGui.QImageWriter()            
            im.setFileName(os.path.join(os.getcwd(),"wiki_topimage.png"))           
            imd = QtGui.QImage()
            imd_bool = imd.loadFromData(data.data())
            im.write(imd)
        except Exception as e:
            print(e)

def main():
    QtCore.QCoreApplication.addLibraryPath(os.path.join(os.getcwd(),"plugins"))  
    try:
        QtGui.QApplication([])

    except Exception as e:
        print("error", e)
    w = Widget()
    w.show()
    sys.exit(QtGui.QApplication.exec_())
if __name__ == "__main__":
    main()

您有以下错误:

  • 您应该使用的 url 在子 img 标签的 src 属性中。
  • 您只需创建一个 QNetworkAccessManager,否则新的 QNetworkAccessManager 将消除之前的 QNetworkAccessManager。
  • 您必须使用 QUrl::fromUserInput(),因为它处理 url 尝试多种配置,例如在这种情况下,它可以转换 url of:
https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Oguri_Cap_in_Yushun_Stallion_station.jpg

https://ja.wikipedia.org/wiki/ファイル:Oguri_Cap_in_Yushun_Stallion_station.jpg
import os
import sys
import re
from PySide import QtCore, QtGui, QtNetwork
from bs4 import BeautifulSoup


class Widget(QtGui.QTextEdit):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.nam = QtNetwork.QNetworkAccessManager(self)
        self.nam.finished[QtNetwork.QNetworkReply].connect(self.doReply)

    def keyPressEvent(self, event):
        if event.matches(QtGui.QKeySequence.Copy):
            tc = self.textCursor()
            mimedata = self.createMimeDataFromSelection()
            clipboard = QtGui.QApplication.clipboard()
            clipboard.setMimeData(mimedata)
            start = tc.selectionStart()
            end = tc.selectionEnd()
            char = tc.charFormat()
            char.clearBackground()
            tc.setCharFormat(char)
            return
        elif event.matches(QtGui.QKeySequence.Paste):
            clipboard = QtGui.QApplication.clipboard()

            html = clipboard.mimeData().html()
            pous = BeautifulSoup(html, "lxml")
            image_items = pous.find_all(
                "a", href=re.compile(r"(\.jpg|\.png|\.svg|\.gif)$")
            )
            for i, item in enumerate(image_items):
                url = item.find("img", recursive=False).get("src")
                print(i, url)
                request = QtNetwork.QNetworkRequest(
                    QtCore.QUrl.fromUserInput(url)
                )
                self.nam.get(request)

    @QtCore.Slot(QtNetwork.QNetworkReply)
    def doReply(self, reply):
        er = reply.error()
        if er == QtNetwork.QNetworkReply.NoError:
            print("ok", reply.url())
            name = reply.url().path().split("/")[-1]
            filename = os.path.join(os.getcwd(), name)
            file = QtCore.QFile(filename)
            if file.open(QtCore.QIODevice.WriteOnly):
                file.write(reply.readAll())
        else:
            print("Error occured: ", er, reply.url())
        reply.deleteLater()


def main():
    QtCore.QCoreApplication.addLibraryPath(os.path.join(os.getcwd(), "plugins"))
    app = QtGui.QApplication.instance()
    if app is None:
        app = QtGui.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(QtGui.QApplication.exec_())


if __name__ == "__main__":
    main()