多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# PyQt 中的`QNetworkAccessManager` > 原文: [http://zetcode.com/pyqt/qnetworkaccessmanager/](http://zetcode.com/pyqt/qnetworkaccessmanager/) PyQt 教程中的`QNetworkAccessManager`展示了如何显示如何使用`QNetworkAccessManager`发送请求和接收响应。 ## `QNetworkAccessManager` `QNetworkAccessManager`允许应用发送网络请求和接收回复。 `QNetworkRequest`保留要与网络管理器发送的请求,`QNetworkReply`包含返回的数据和响应头。 `QNetworkAccessManager`具有异步 API,这意味着其方法总是立即返回,并且不等到完成时才返回。 而是在请求完成时发出信号。 我们通过附加到完成信号的方法来处理响应。 ## HTTP GET 请求 HTTP GET 方法请求指定资源的表示形式。 `get_request.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- ''' QNetworkAccessManager in PyQt In this example we get a web page. Author: Jan Bodnar Website: zetcode.com Last edited: September 2017 ''' from PyQt5 import QtNetwork from PyQt5.QtCore import QCoreApplication, QUrl import sys class Example: def __init__(self): self.doRequest() def doRequest(self): url = "http://www.something.com" req = QtNetwork.QNetworkRequest(QUrl(url)) self.nam = QtNetwork.QNetworkAccessManager() self.nam.finished.connect(self.handleResponse) self.nam.get(req) def handleResponse(self, reply): er = reply.error() if er == QtNetwork.QNetworkReply.NoError: bytes_string = reply.readAll() print(str(bytes_string, 'utf-8')) else: print("Error occured: ", er) print(reply.errorString()) QCoreApplication.quit() app = QCoreApplication([]) ex = Example() sys.exit(app.exec_()) ``` 该示例检索指定网页的 HTML 代码。 ```py url = "http://www.something.com" req = QtNetwork.QNetworkRequest(QUrl(url)) ``` 使用`QNetworkRequest`,我们将请求发送到指定的 URL。 ```py self.nam = QtNetwork.QNetworkAccessManager() self.nam.finished.connect(self.handleResponse) self.nam.get(req) ``` 创建一个`QNetworkAccessManager`对象。 请求完成后,将调用`handleResponse()`方法。 使用`get()`方法触发该请求。 ```py def handleResponse(self, reply): er = reply.error() if er == QtNetwork.QNetworkReply.NoError: bytes_string = reply.readAll() print(str(bytes_string, 'utf-8')) else: print("Error occured: ", er) print(reply.errorString()) QCoreApplication.quit() ``` `handleResponse()`接收`QNetworkReply`对象。 它包含已发送请求的数据和标头。 如果网络回复中没有错误,我们将使用`readAll()`方法读取所有数据; 否则,我们将显示错误消息。 `errorString()`返回人类可读的最后发生的错误的描述。 `readAll()`返回`QByteArray`中必须解码的数据。 ```py $ ./get_request.py <html><head><title>Something.</title></head> <body>Something.</body> </html> ``` 这是输出。 ## HTTP POST 请求 HTTP POST 方法将数据发送到服务器。 请求正文的类型由`Content-Type`标头指示。 POST 请求通常通过 HTML 表单发送。 请求中发送的数据可以采用不同的方式进行编码。 在`application/x-www-form-urlencoded`中,值被编码为以`'&'`分隔的键值元组,键和值之间带有`'='`。 非字母数字字符采用百分比编码。 `multipart/form-data`用于二进制数据和文件上传。 `post_request.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- ''' QNetworkAccessManager in PyQt In this example we post data to a web page. Author: Jan Bodnar Website: zetcode.com Last edited: September 2017 ''' from PyQt5 import QtCore, QtGui, QtNetwork import sys, json class Example: def __init__(self): self.doRequest() def doRequest(self): data = QtCore.QByteArray() data.append("name=Peter&") data.append("age=34") url = "https://httpbin.org/post" req = QtNetwork.QNetworkRequest(QtCore.QUrl(url)) req.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, "application/x-www-form-urlencoded") self.nam = QtNetwork.QNetworkAccessManager() self.nam.finished.connect(self.handleResponse) self.nam.post(req, data) def handleResponse(self, reply): er = reply.error() if er == QtNetwork.QNetworkReply.NoError: bytes_string = reply.readAll() json_ar = json.loads(str(bytes_string, 'utf-8')) data = json_ar['form'] print('Name: {0}'.format(data['name'])) print('Age: {0}'.format(data['age'])) print() else: print("Error occurred: ", er) print(reply.errorString()) QtCore.QCoreApplication.quit() app = QtCore.QCoreApplication([]) ex = Example() sys.exit(app.exec_()) ``` 该示例将发布请求发送到`https://httpbin.org/post`测试站点,该站点将数据以 JSON 格式发送回。 ```py data = QtCore.QByteArray() data.append("name=Peter&") data.append("age=34") ``` 根据规范,我们对`QByteArray`中发送的数据进行编码。 ```py url = "https://httpbin.org/post" req = QtNetwork.QNetworkRequest(QtCore.QUrl(url)) req.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, "application/x-www-form-urlencoded") ``` 我们指定`application/x-www-form-urlencoded`编码类型。 ```py bytes_string = reply.readAll() json_ar = json.loads(str(bytes_string, 'utf-8')) data = json_ar['form'] print('Name: {0}'.format(data['name'])) print('Age: {0}'.format(data['age'])) print() ``` 在处理器方法中,我们读取响应数据并将其解码。 使用内置的`json`模块,我们提取发布的数据。 ```py $ ./post_request.py Name: Peter Age: 34 ``` 这是输出。 ## 使用`QNetworkAccessManager`进行认证 每当最终服务器在传递所请求的内容之前请求认证时,都会发出`authenticationRequired`信号。 `authenticate.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- ''' QNetworkAccessManager in PyQt In this example, we show how to authenticate to a web page. Author: Jan Bodnar Website: zetcode.com Last edited: September 2017 ''' from PyQt5 import QtCore, QtGui, QtNetwork import sys, json class Example: def __init__(self): self.doRequest() def doRequest(self): self.auth = 0 url = "https://httpbin.org/basic-auth/user7/passwd7" req = QtNetwork.QNetworkRequest(QtCore.QUrl(url)) self.nam = QtNetwork.QNetworkAccessManager() self.nam.authenticationRequired.connect(self.authenticate) self.nam.finished.connect(self.handleResponse) self.nam.get(req) def authenticate(self, reply, auth): print("Authenticating") self.auth += 1 if self.auth >= 3: reply.abort() auth.setUser("user7") auth.setPassword("passwd7") def handleResponse(self, reply): er = reply.error() if er == QtNetwork.QNetworkReply.NoError: bytes_string = reply.readAll() data = json.loads(str(bytes_string, 'utf-8')) print('Authenticated: {0}'.format(data['authenticated'])) print('User: {0}'.format(data['user'])) print() else: print("Error occurred: ", er) print(reply.errorString()) QtCore.QCoreApplication.quit() app = QtCore.QCoreApplication([]) ex = Example() sys.exit(app.exec_()) ``` 在示例中,使用`https://httpbin.org`网站显示如何使用`QNetworkAccessManager`进行认证。 ```py self.nam.authenticationRequired.connect(self.authenticate) ``` 我们将`authenticationRequired`信号连接到`authenticate()`方法。 ```py def authenticate(self, reply, auth): print("Authenticating") ... ``` `authenticate()`方法的第三个参数是`QAuthenticator`,用于传递所需的认证信息。 ```py self.auth += 1 if self.auth >= 3: reply.abort() ``` 如果验证失败,则`QNetworkAccessManager`会继续发出`authenticationRequired`信号。 在三次失败的尝试之后,我们中止了该过程。 ```py auth.setUser("user7") auth.setPassword("passwd7") ``` 我们将用户和密码设置为`QAuthenticator`。 ```py bytes_string = reply.readAll() data = json.loads(str(bytes_string, 'utf-8')) print('Authenticated: {0}'.format(data['authenticated'])) print('User: {0}'.format(data['user'])) print() ``` `https://httpbin.org`用 JSON 数据响应,该数据包含用户名和指示认证成功的布尔值。 ```py $ ./authenticate.py Authenticating Authenticated: True User: user7 ``` 这是输出。 ## 提取一个网站图标 网站图标是与特定网站相关的小图标。 在以下示例中,我们将从网站上下载网站图标。 `fetch_icon.py` ```py #!/usr/bin/python3 # -*- coding: utf-8 -*- ''' QNetworkAccessManager in PyQt In this example we fetch a favicon from a website. Author: Jan Bodnar Website: zetcode.com Last edited: September 2017 ''' from PyQt5 import QtCore, QtGui, QtNetwork import sys class Example: def __init__(self): self.doRequest() def doRequest(self): url = "http://www.google.com/favicon.ico" req = QtNetwork.QNetworkRequest(QtCore.QUrl(url)) self.nam = QtNetwork.QNetworkAccessManager() self.nam.finished.connect(self.handleResponse) self.nam.get(req) def handleResponse(self, reply): er = reply.error() if er == QtNetwork.QNetworkReply.NoError: data = reply.readAll() self.saveFile(data) else: print("Error occured: ", er) print(reply.errorString()) QtCore.QCoreApplication.quit() def saveFile(self, data): f = open('favicon.ico', 'wb') with f: f.write(data) app = QtCore.QCoreApplication([]) ex = Example() sys.exit(app.exec_()) ``` 该代码示例下载了 Google 的收藏夹图标。 ```py self.nam.get(req) ``` 我们使用`get()`方法下载图标。 ```py data = reply.readAll() self.saveFile(data) ``` 在`handleResponse()`方法中,我们读取数据并将其保存到文件中。 ```py def saveFile(self, data): f = open('favicon.ico', 'wb') with f: f.write(data) ``` 图像数据以`saveFile()`方法保存在磁盘上。 在本教程中,我们使用了`QNetworkAccessManager`。 您可能也对以下相关教程感兴趣: [`QPropertyAnimation`教程](/pyqt/qpropertyanimation/), [PyQt5 教程](/gui/pyqt5/)和 [Python 教程](/lang/python/)。