原文: http://zetcode.com/pyqt/qnetworkaccessmanager/

PyQt 教程中的QNetworkAccessManager展示了如何显示如何使用QNetworkAccessManager发送请求和接收响应。

QNetworkAccessManager

QNetworkAccessManager允许应用发送网络请求和接收回复。 QNetworkRequest保留要与网络管理器发送的请求,QNetworkReply包含返回的数据和响应头。

QNetworkAccessManager具有异步 API,这意味着其方法总是立即返回,并且不等到完成时才返回。 而是在请求完成时发出信号。 我们通过附加到完成信号的方法来处理响应。

HTTP GET 请求

HTTP GET 方法请求指定资源的表示形式。

get_request.py

  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. '''
  4. QNetworkAccessManager in PyQt
  5. In this example we get a web page.
  6. Author: Jan Bodnar
  7. Website: zetcode.com
  8. Last edited: September 2017
  9. '''
  10. from PyQt5 import QtNetwork
  11. from PyQt5.QtCore import QCoreApplication, QUrl
  12. import sys
  13. class Example:
  14. def __init__(self):
  15. self.doRequest()
  16. def doRequest(self):
  17. url = "http://www.something.com"
  18. req = QtNetwork.QNetworkRequest(QUrl(url))
  19. self.nam = QtNetwork.QNetworkAccessManager()
  20. self.nam.finished.connect(self.handleResponse)
  21. self.nam.get(req)
  22. def handleResponse(self, reply):
  23. er = reply.error()
  24. if er == QtNetwork.QNetworkReply.NoError:
  25. bytes_string = reply.readAll()
  26. print(str(bytes_string, 'utf-8'))
  27. else:
  28. print("Error occured: ", er)
  29. print(reply.errorString())
  30. QCoreApplication.quit()
  31. app = QCoreApplication([])
  32. ex = Example()
  33. sys.exit(app.exec_())

该示例检索指定网页的 HTML 代码。

  1. url = "http://www.something.com"
  2. req = QtNetwork.QNetworkRequest(QUrl(url))

使用QNetworkRequest,我们将请求发送到指定的 URL。

  1. self.nam = QtNetwork.QNetworkAccessManager()
  2. self.nam.finished.connect(self.handleResponse)
  3. self.nam.get(req)

创建一个QNetworkAccessManager对象。 请求完成后,将调用handleResponse()方法。 使用get()方法触发该请求。

  1. def handleResponse(self, reply):
  2. er = reply.error()
  3. if er == QtNetwork.QNetworkReply.NoError:
  4. bytes_string = reply.readAll()
  5. print(str(bytes_string, 'utf-8'))
  6. else:
  7. print("Error occured: ", er)
  8. print(reply.errorString())
  9. QCoreApplication.quit()

handleResponse()接收QNetworkReply对象。 它包含已发送请求的数据和标头。 如果网络回复中没有错误,我们将使用readAll()方法读取所有数据; 否则,我们将显示错误消息。 errorString()返回人类可读的最后发生的错误的描述。 readAll()返回QByteArray中必须解码的数据。

  1. $ ./get_request.py
  2. <html><head><title>Something.</title></head>
  3. <body>Something.</body>
  4. </html>

这是输出。

HTTP POST 请求

HTTP POST 方法将数据发送到服务器。 请求正文的类型由Content-Type标头指示。 POST 请求通常通过 HTML 表单发送。 请求中发送的数据可以采用不同的方式进行编码。 在application/x-www-form-urlencoded中,值被编码为以'&'分隔的键值元组,键和值之间带有'='。 非字母数字字符采用百分比编码。 multipart/form-data用于二进制数据和文件上传。

post_request.py

  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. '''
  4. QNetworkAccessManager in PyQt
  5. In this example we post data to a web page.
  6. Author: Jan Bodnar
  7. Website: zetcode.com
  8. Last edited: September 2017
  9. '''
  10. from PyQt5 import QtCore, QtGui, QtNetwork
  11. import sys, json
  12. class Example:
  13. def __init__(self):
  14. self.doRequest()
  15. def doRequest(self):
  16. data = QtCore.QByteArray()
  17. data.append("name=Peter&")
  18. data.append("age=34")
  19. url = "https://httpbin.org/post"
  20. req = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
  21. req.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
  22. "application/x-www-form-urlencoded")
  23. self.nam = QtNetwork.QNetworkAccessManager()
  24. self.nam.finished.connect(self.handleResponse)
  25. self.nam.post(req, data)
  26. def handleResponse(self, reply):
  27. er = reply.error()
  28. if er == QtNetwork.QNetworkReply.NoError:
  29. bytes_string = reply.readAll()
  30. json_ar = json.loads(str(bytes_string, 'utf-8'))
  31. data = json_ar['form']
  32. print('Name: {0}'.format(data['name']))
  33. print('Age: {0}'.format(data['age']))
  34. print()
  35. else:
  36. print("Error occurred: ", er)
  37. print(reply.errorString())
  38. QtCore.QCoreApplication.quit()
  39. app = QtCore.QCoreApplication([])
  40. ex = Example()
  41. sys.exit(app.exec_())

该示例将发布请求发送到https://httpbin.org/post测试站点,该站点将数据以 JSON 格式发送回。

  1. data = QtCore.QByteArray()
  2. data.append("name=Peter&")
  3. data.append("age=34")

根据规范,我们对QByteArray中发送的数据进行编码。

  1. url = "https://httpbin.org/post"
  2. req = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
  3. req.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
  4. "application/x-www-form-urlencoded")

我们指定application/x-www-form-urlencoded编码类型。

  1. bytes_string = reply.readAll()
  2. json_ar = json.loads(str(bytes_string, 'utf-8'))
  3. data = json_ar['form']
  4. print('Name: {0}'.format(data['name']))
  5. print('Age: {0}'.format(data['age']))
  6. print()

在处理器方法中,我们读取响应数据并将其解码。 使用内置的json模块,我们提取发布的数据。

  1. $ ./post_request.py
  2. Name: Peter
  3. Age: 34

这是输出。

使用QNetworkAccessManager进行认证

每当最终服务器在传递所请求的内容之前请求认证时,都会发出authenticationRequired信号。

authenticate.py

  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. '''
  4. QNetworkAccessManager in PyQt
  5. In this example, we show how to authenticate
  6. to a web page.
  7. Author: Jan Bodnar
  8. Website: zetcode.com
  9. Last edited: September 2017
  10. '''
  11. from PyQt5 import QtCore, QtGui, QtNetwork
  12. import sys, json
  13. class Example:
  14. def __init__(self):
  15. self.doRequest()
  16. def doRequest(self):
  17. self.auth = 0
  18. url = "https://httpbin.org/basic-auth/user7/passwd7"
  19. req = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
  20. self.nam = QtNetwork.QNetworkAccessManager()
  21. self.nam.authenticationRequired.connect(self.authenticate)
  22. self.nam.finished.connect(self.handleResponse)
  23. self.nam.get(req)
  24. def authenticate(self, reply, auth):
  25. print("Authenticating")
  26. self.auth += 1
  27. if self.auth >= 3:
  28. reply.abort()
  29. auth.setUser("user7")
  30. auth.setPassword("passwd7")
  31. def handleResponse(self, reply):
  32. er = reply.error()
  33. if er == QtNetwork.QNetworkReply.NoError:
  34. bytes_string = reply.readAll()
  35. data = json.loads(str(bytes_string, 'utf-8'))
  36. print('Authenticated: {0}'.format(data['authenticated']))
  37. print('User: {0}'.format(data['user']))
  38. print()
  39. else:
  40. print("Error occurred: ", er)
  41. print(reply.errorString())
  42. QtCore.QCoreApplication.quit()
  43. app = QtCore.QCoreApplication([])
  44. ex = Example()
  45. sys.exit(app.exec_())

在示例中,使用https://httpbin.org网站显示如何使用QNetworkAccessManager进行认证。

  1. self.nam.authenticationRequired.connect(self.authenticate)

我们将authenticationRequired信号连接到authenticate()方法。

  1. def authenticate(self, reply, auth):
  2. print("Authenticating")
  3. ...

authenticate()方法的第三个参数是QAuthenticator,用于传递所需的认证信息。

  1. self.auth += 1
  2. if self.auth >= 3:
  3. reply.abort()

如果验证失败,则QNetworkAccessManager会继续发出authenticationRequired信号。 在三次失败的尝试之后,我们中止了该过程。

  1. auth.setUser("user7")
  2. auth.setPassword("passwd7")

我们将用户和密码设置为QAuthenticator

  1. bytes_string = reply.readAll()
  2. data = json.loads(str(bytes_string, 'utf-8'))
  3. print('Authenticated: {0}'.format(data['authenticated']))
  4. print('User: {0}'.format(data['user']))
  5. print()

https://httpbin.org用 JSON 数据响应,该数据包含用户名和指示认证成功的布尔值。

  1. $ ./authenticate.py
  2. Authenticating
  3. Authenticated: True
  4. User: user7

这是输出。

提取一个网站图标

网站图标是与特定网站相关的小图标。 在以下示例中,我们将从网站上下载网站图标。

fetch_icon.py

  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. '''
  4. QNetworkAccessManager in PyQt
  5. In this example we fetch a favicon from
  6. a website.
  7. Author: Jan Bodnar
  8. Website: zetcode.com
  9. Last edited: September 2017
  10. '''
  11. from PyQt5 import QtCore, QtGui, QtNetwork
  12. import sys
  13. class Example:
  14. def __init__(self):
  15. self.doRequest()
  16. def doRequest(self):
  17. url = "http://www.google.com/favicon.ico"
  18. req = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
  19. self.nam = QtNetwork.QNetworkAccessManager()
  20. self.nam.finished.connect(self.handleResponse)
  21. self.nam.get(req)
  22. def handleResponse(self, reply):
  23. er = reply.error()
  24. if er == QtNetwork.QNetworkReply.NoError:
  25. data = reply.readAll()
  26. self.saveFile(data)
  27. else:
  28. print("Error occured: ", er)
  29. print(reply.errorString())
  30. QtCore.QCoreApplication.quit()
  31. def saveFile(self, data):
  32. f = open('favicon.ico', 'wb')
  33. with f:
  34. f.write(data)
  35. app = QtCore.QCoreApplication([])
  36. ex = Example()
  37. sys.exit(app.exec_())

该代码示例下载了 Google 的收藏夹图标。

  1. self.nam.get(req)

我们使用get()方法下载图标。

  1. data = reply.readAll()
  2. self.saveFile(data)

handleResponse()方法中,我们读取数据并将其保存到文件中。

  1. def saveFile(self, data):
  2. f = open('favicon.ico', 'wb')
  3. with f:
  4. f.write(data)

图像数据以saveFile()方法保存在磁盘上。

在本教程中,我们使用了QNetworkAccessManager

您可能也对以下相关教程感兴趣: QPropertyAnimation教程PyQt5 教程Python 教程