Skip to content

Latest commit

 

History

History
298 lines (228 loc) · 19.1 KB

File metadata and controls

298 lines (228 loc) · 19.1 KB

二十二、使用谷歌地图

在本章中,您将学习在 Python 应用中使用 Google 地图,并探索 Google 提供的不同优势。您将学习执行以下任务:

  • 了解一个位置或地标的详细信息
  • 从纬度和经度值获取完整信息
  • 找出两个位置之间的距离
  • 在谷歌地图上显示一个位置

介绍

GoogleMapsAPI 是一组方法和工具,可用于查找任何位置的完整信息,包括经度和纬度值。您可以使用 Google Maps API 方法查找两个位置之间的距离或到任何位置的方向;你甚至可以显示谷歌地图,标记那个位置,等等。

更准确地说,谷歌地图服务有一个 Pythonclient库。有几个 GoogleMapsAPI,包括方向 API、距离矩阵 API、地理编码 API、地理位置 API 等等。要使用任何 GoogleMapsWeb 服务,您的 Python 脚本会向 Google 发送一个请求;要满足该请求,您需要一个 API 密钥。您需要按照以下步骤获取 API 密钥:

  1. 访问https://console.developers.google.com
  2. 使用您的 Google 帐户登录控制台
  3. 选择一个现有项目或创建一个新项目
  4. 启用要使用的 API
  5. 复制 API 密钥并在 Python 脚本中使用它

您需要访问谷歌 API 控制台https://console.developers.google.com ,并获取 API 密钥,以便您的应用通过身份验证,可以使用 Google Maps API web 服务。

API 键在几个方面都有帮助;首先,它们有助于识别您的应用。API 密钥包含在每个请求中,因此它可以帮助 Google 监控您的应用的 API 使用情况,知道您的应用是否消耗了其每日免费配额,并因此为您的应用计费

因此,为了在 Python 应用中使用 Google Maps API web 服务,您只需要启用所需的 API 并获得一个 API 密钥,以便在 Python 应用中使用。

找出一个地点或地标的细节

在此配方中,系统将提示您输入一个位置或地标,您希望了解其详细信息。例如,如果输入Buckingham Palace,配方将显示宫殿所在地的城市和邮政编码,以及经度和纬度值。

怎么做…

GoogleMaps类的搜索方法是这个配方中的关键角色。用户输入的地标或位置将传递给搜索方法。从搜索方法返回的对象的citypostal_codelatlng属性分别用于显示位置的城市、邮政编码、纬度和经度。让我们看看如何通过以下步骤来完成:

  1. 基于对话框创建应用,而不使用按钮模板。

  2. 通过在表单上拖放六个标签、一行编辑和一个按钮小部件,将六个QLabel、一个QLineEdit和一个QPushButton小部件添加到表单中。

  3. 将第一个标签小部件的文本属性设置为Find out the City, Postal Code, Longitude and Latitude,将第二个标签小部件的文本属性设置为Enter location

  4. 删除第三、第四、第五和第六标签小部件的文本属性,因为它们的文本属性将通过代码设置;也就是说,输入位置的城市、邮政编码、经度和纬度将通过代码获取,并通过这四个标签小部件显示。

  5. 将按钮小部件的文本属性设置为Search

  6. 将行编辑小部件的 objectName 属性设置为lineEditLocation

  7. 将按钮小部件的 objectName 属性设置为pushButtonSearch

  8. 将其余四个标签小部件的 objectName 属性设置为labelCitylabelPostalCodelabelLongitudelabelLatitude

  9. 按名称将应用保存为demoGoogleMap1.ui。该表单现在将显示,如以下屏幕截图所示:

使用 Qt Designer 创建的用户界面存储在一个.ui文件中,它是一个 XML 文件。通过应用pyuic5实用程序将 XML 文件转换为 Python 代码。您可以在本书的源代码包中找到生成的 Python 代码demoGoogleMap1.py

  1. demoGoogleMap1.py脚本视为头文件,并将其导入到将从中调用其用户界面设计的文件中。
  2. 创建另一个名为callGoogleMap1.pyw的 Python 文件,并将demoGoogleMap1.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from geolocation.main import GoogleMaps
from demoGoogleMap1 import *
class MyForm(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.pushButtonSearch.clicked.connect(self.
        displayDetails)
        self.show()
    def displayDetails(self):
        address = str(self.ui.lineEditLocation.text())
        google_maps = GoogleMaps(api_key=
        'xxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        location = google_maps.search(location=address)
        my_location = location.first()
        self.ui.labelCity.setText("City: 
        "+str(my_location.city))
        self.ui.labelPostalCode.setText("Postal Code: " 
        +str(my_location.postal_code))
        self.ui.labelLongitude.setText("Longitude: 
        "+str(my_location.lng))
        self.ui.labelLatitude.setText("Latitude: 
        "+str(my_location.lat))
if __name__=="__main__":
    app = QApplication(sys.argv)
    w = MyForm()
    w.show()
    sys.exit(app.exec_())

它是如何工作的…

您可以在脚本中看到,objectName 属性为pushButtonSearch的按钮的 click 事件连接到了displayDetails方法。这意味着,只要点击按钮,displayDetails方法就会被调用。在displayDetails方法中,您访问用户在 Line Edit 小部件中输入的位置,并将该位置分配给 address 变量。您可以通过传递在 Google 注册时获得的 API 密钥来定义 Google Maps 实例。在 Google Maps 实例上调用search方法,传递用户在此方法中输入的位置。search方法的结果分配给my_location结构。my_location结构的城市成员包含用户输入的城市。类似地,my_location结构的postal_codelnglat成员分别包含用户输入的位置的邮政编码、经度和纬度信息。城市、邮政编码、经度和纬度信息通过最后四个标签小部件显示。

运行应用时,系统将提示您输入要查找信息的位置。假设您在位置中输入Taj Mahal,然后单击搜索按钮。泰姬陵地标的城市、邮政编码、经度和纬度信息将显示在屏幕上,如以下屏幕截图所示:

从纬度和经度值获取完整信息

在本食谱中,您将学习如何找出您知道其经度和纬度值的位置的完整细节。将点位置(即经度和纬度值)转换为可读地址(地名、城市、国家名称等)的过程称为反向地理编码

应用将提示您输入经度和纬度值,然后显示匹配的位置名称、城市、国家和该位置的邮政编码。

怎么做…

让我们执行以下步骤,基于无按钮对话框模板创建一个应用:

  1. 通过在表单上拖放七个标签、两行编辑和一个按钮小部件,将七个QLabel、两个QLineEdit和一个QPushButton小部件添加到表单中。

  2. 将第一个标签小部件的文本属性设置为Find out the Location, City, Country and Postal Code,将第二个标签小部件的文本属性设置为Enter Longitude,将第三个标签小部件的文本属性设置为Enter Latitude

  3. 删除第四、第五、第六和第七标签小部件的文本属性,因为它们的文本属性将通过代码设置;也就是说,用户输入经度和纬度的位置的位置、城市、国家和邮政编码将通过代码访问,并通过这四个标签小部件显示。

  4. 将按钮小部件的文本属性设置为Search

  5. 将两行编辑小部件的 objectName 属性设置为lineEditLongitudelineEditLatitude

  6. 将按钮小部件的 objectName 属性设置为pushButtonSearch

  7. 将其他四个标签小部件的 objectName 属性设置为labelLocationlabelCitylabelCountrylabelPostalCode

  8. 按名称将应用保存为demoGoogleMap2.ui。该表单现在将显示,如以下屏幕截图所示:

使用 Qt Designer 创建的用户界面存储在一个.ui文件中,该文件是一个 XML 文件,需要转换为 Python 代码。pyuic5实用程序用于将 XML 文件转换为 Python 代码。生成的 Python 脚本demoGoogleMap2.py可以在本书的源代码包中看到。

  1. demoGoogleMap2.py脚本视为头文件,并将其导入到将从中调用其用户界面设计的文件中。
  2. 创建另一个名为callGoogleMap2.pyw的 Python 文件,并将demoGoogleMap2.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from geolocation.main import GoogleMaps
from demoGoogleMap2 import *
class MyForm(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.pushButtonSearch.clicked.connect(self.
        displayLocation)
        self.show()
    def displayLocation(self):
        lng = float(self.ui.lineEditLongitude.text())
        lat = float(self.ui.lineEditLatitude.text())
        google_maps = GoogleMaps(api_key=
        'AIzaSyDzCMD-JTg-IbJZZ9fKGE1lipbBiFRiGHA')
        my_location = google_maps.search(lat=lat, lng=lng).
        first()
        self.ui.labelLocation.setText("Location:   
        "+str(my_location))
        self.ui.labelCity.setText("City: 
        "+str(my_location.city))
        self.ui.labelCountry.setText("Country: 
        "+str(my_location.country))
        self.ui.labelPostalCode.setText("Postal Code: 
        "+str(my_location.postal_code))
if __name__=="__main__":
    app = QApplication(sys.argv)
    w = MyForm()
    w.show()
    sys.exit(app.exec_())

它是如何工作的…

在脚本中,您可以看到 objectName 属性为pushButtonSearch的按钮的 click()事件连接到displayLocation方法。这意味着,只要点击按钮,displayLocation方法就会被调用。在displayLocation方法中,您通过两个行编辑小部件访问用户输入的经度和纬度,并将它们分别分配给两个变量lnglat。Google 地图实例是通过传递您在 Google 注册时获得的 API 密钥来定义的。在 Google Maps 实例上调用search方法,传递用户提供的经度和纬度值。在检索到的搜索中调用first方法,并将与提供的经度和纬度值匹配的第一个位置分配给my_location结构。位置名称通过标签小部件显示。要显示位置的城市、国家和邮政编码,请使用my_location结构的citycountrypostal_code成员。

运行应用时,系统将提示您输入经度和纬度值。与提供的经度和纬度相关的位置名称、城市、国家和邮政编码将通过四个标签小部件显示在屏幕上,如以下屏幕截图所示:

找出两个位置之间的距离

在本配方中,您将学习如何找出用户输入的两个位置之间的距离(以公里为单位)。配方将简单地提示用户输入两个位置,然后单击“查找距离”按钮,并显示两个位置之间的距离。

怎么做…

让我们执行以下步骤,基于无按钮对话框模板创建一个应用:

  1. 通过在表单上拖放四个标签、两行编辑和一个按钮小部件,将四个QLabel、两个QLineEdit和一个QPushButton小部件添加到表单中。

  2. 将第一个标签小部件的文本属性设置为Find out the distance between two locations,将第二个标签小部件的文本属性设置为Enter first location,将第三个标签小部件的文本属性设置为Enter second location

  3. 删除第四个标签小部件的文本属性,因为其文本属性将通过代码设置;也就是说,两个输入位置之间的距离将通过代码计算并显示在第四个标签小部件中。

  4. 将按钮小部件的文本属性设置为Find Distance

  5. 将两行编辑小部件的 objectName 属性设置为lineEditFirstLocationlineEditSecondLocation

  6. 将按钮小部件的 objectName 属性设置为pushButtonFindDistance

  7. 将第四个标签小部件的 objectName 属性设置为labelDistance

  8. 按名称将应用保存为demoGoogleMap3.ui。该表单现在将显示,如以下屏幕截图所示:

使用 Qt Designer 创建的用户界面存储在一个.ui文件中,它是一个 XML 文件。通过应用pyuic5实用程序将 XML 文件转换为 Python 代码。您可以在本书的源代码包中找到生成的 Python 代码demoGoogleMap3.py

  1. 要使用在demoGoogleMap3.py文件中创建的 GUI,我们需要创建另一个 Python 脚本并在该脚本中导入demoGoogleMap3.py文件。
  2. 创建另一个名为callGoogleMap3.pyw的 Python 文件,并将demoGoogleMap3.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from googlemaps.client import Client
from googlemaps.distance_matrix import distance_matrix
from demoGoogleMap3 import *
class MyForm(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.pushButtonFindDistance.clicked.connect(self.
        displayDistance)
        self.show()
    def displayDistance(self):
        api_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
        gmaps = Client(api_key)
        data = distance_matrix(gmaps,  
        self.ui.lineEditFirstLocation.text(),         
        self.ui.lineEditSecondLocation.text())
        distance = data['rows'][0]['elements'][0]['distance']
        ['text']
        self.ui.labelDistance.setText("Distance between 
        "+self.ui.lineEditFirstLocation.text()+" 
        and "+self.ui.lineEditSecondLocation.text()+" is 
        "+str(distance))
if __name__=="__main__":
    app = QApplication(sys.argv)
    w = MyForm()
    w.show()
    sys.exit(app.exec_())

它是如何工作的…

您创建了一个Client类的实例,并将其命名为gmaps。创建Client实例时,需要传递在 Google 注册时获得的 API 密钥。objectName 为pushButtonFindDistance的按钮的 click()事件连接到displayDistance方法。这意味着,只要点击按钮,就会调用displayDistance方法。在displayDistance方法中,调用distance_matrix方法,传递Client实例和用户输入的两个位置,找出它们之间的距离。distance_matrix方法返回分配给数据数组的多维数组。从数据数组中,访问两个位置之间的距离并将其分配给distance变量。distance变量中的值最终通过标签小部件显示。

运行应用时,系统将提示您输入两个位置,您希望知道它们之间的距离。输入两个位置后,单击“查找距离”按钮,屏幕上将显示两个位置之间的距离,如以下屏幕截图所示:

在谷歌地图上显示位置

在本食谱中,如果您知道某个位置的经度和纬度值,您将学习如何在谷歌地图上显示该位置。系统将提示您只需输入经度和纬度值,当您单击“显示地图”按钮时,该位置将显示在谷歌地图上。

怎么做…

让我们执行以下步骤,基于无按钮对话框模板创建一个应用:

  1. 通过在表单上拖放两个标签、两行编辑、一个按钮和一个小部件容器,将两个QLabel、两个QLineEdit、一个QPushButton和一个QWidget小部件添加到表单中。

  2. 将两个标签小部件的文本属性设置为LongitudeLatitude

  3. 将按钮小部件的文本属性设置为Show Map

  4. 将两行编辑小部件的 objectName 属性设置为lineEditLongitudelineEditLatitude

  5. 将按钮小部件的 objectName 属性设置为pushButtonShowMap

  6. 按名称将应用保存为showGoogleMap.ui。该表单现在将显示,如以下屏幕截图所示:

  1. 下一步是将QWidget小部件升级为QWebEngineView,因为要显示谷歌地图,需要QWebEngineView,因为谷歌地图是一个 web 应用,我们需要一个 QWebEngineView 来显示谷歌地图并与之交互。

  2. 通过右键单击QWidget小部件并选择“升级到”。。。弹出菜单中的选项。在出现的对话框中,将基类名称选项保留为默认值 QWidget。

  3. 在提升的类名框中,输入QWebEngineView并在头文件框中键入PyQT5.QtWebEngineWidgets

  4. 点击升级按钮,将QWidget小部件升级到QWebEngineView类,如下图所示:

  1. 单击“关闭”按钮关闭“升级的小部件”对话框。使用 Qt Designer 创建的用户界面存储在一个.ui文件中,该文件是一个 XML 文件,需要转换为 Python 代码。pyuic5实用程序用于将 XML 文件转换为 Python 代码。生成的 Python 脚本showGoogleMap.py可以在本书的源代码包中看到。

  2. showGoogleMap.py脚本视为头文件,并将其导入到将从中调用其用户界面设计的文件中。

  3. 创建另一个名为callGoogleMap.pyw的 Python 文件,并将showGoogleMap.py代码导入其中:

import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QDialog
from PyQt5.QtWebEngineWidgets import QWebEngineView
from showGoogleMap import *
class MyForm(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.pushButtonShowMap.clicked.connect(self.dispSite)
        self.show()
    def dispSite(self):
        lng = float(self.ui.lineEditLongitude.text())
        lat = float(self.ui.lineEditLatitude.text())
        URL="https://www.google.com/maps/@"+self.ui.
        lineEditLatitude.text()+","
        +self.ui.lineEditLongitude.text()+",9z"
        self.ui.widget.load(QUrl(URL))
if __name__=="__main__":
    app = QApplication(sys.argv)
    w = MyForm()
    w.show()
    sys.exit(app.exec_())

它是如何工作的…

在脚本中,您可以看到 objectName 属性为pushButtonShowMap的按钮的点击事件连接到dispSite ()方法。这意味着,只要点击按钮,dispSite()方法就会被调用。在dispSite ()方法中,您通过两个行编辑小部件访问用户输入的经度和纬度,并将它们分别分配给两个变量lnglat。此后,您将创建一个 URL,从Google.com调用谷歌地图,并传递用户输入的纬度和经度值。

URL 最初是文本形式,并被类型转换为QUrl实例,并传递给小部件,该小部件被提升为QWebEngineView以显示网站。QUrl是来自 Qt 的一个类,它提供了几种方法和属性来管理 URL。然后通过QWebEngineView小部件显示具有指定纬度和经度值的谷歌地图。

运行应用时,系统将提示您输入要在 Google 地图上看到的位置的经度和纬度值。输入经度和纬度值后,单击“显示地图”按钮时,Google Maps 将显示该位置,如以下屏幕截图所示: