如何用脚本将KML文件上传到谷歌地图?

2 投票
1 回答
4277 浏览
提问于 2025-04-16 04:43

我有一个Python脚本,可以生成kml文件。现在我想在这个脚本里自动上传这个kml文件到谷歌地图的“我的地图”部分,而不是手动上传。有没有人能提供一个Python或者其他语言的脚本/代码来实现这个功能?

1 个回答

1

总结:问题2590解决之前,你无法做到这一点。这个问题可能需要一段时间才能解决,因为谷歌已经将其标记为不修复。虽然有一些替代方法可以尝试达到相同的效果,但目前你不能直接通过谷歌地图数据API上传KML文件。

详细说明:

我之前没有任何Python代码来实现这个功能,但谷歌地图数据API允许你通过一系列HTTP请求来完成这项工作。你可以查看上传KML部分,了解如何操作。所以一个可能的Python解决方案是使用标准库中的httplib来为你发送合适的HTTP请求。

经过多次编辑和你们在评论中的反馈,这里有一个脚本,它通过命令行获取谷歌用户名和密码(使用时要小心!),通过发起ClientLogin身份验证请求来获取authorization_token变量。使用有效的用户名和密码后,可以在Authorization头中使用这个授权令牌,将KML数据POST到地图数据API。

#!/usr/bin/env python
import httplib
import optparse
import sys
import urllib

class GoogleMaps(object):
    source = "daybarr.com-kmluploader-0.1"

    def __init__(self, email, passwd):
        self.email = email
        self.passwd = passwd
        self._conn = None
        self._auth_token = None

    def _get_connection(self):
        if not self._auth_token:
            conn = httplib.HTTPSConnection("www.google.com")
            params = urllib.urlencode({
                "accountType": "HOSTED_OR_GOOGLE",
                "Email": self.email,
                "Passwd": self.passwd,
                "service": "local",
                "source": self.source,
            })
            headers = {
                "Content-type": "application/x-www-form-urlencoded",
                "Accept": "text/plain",
            }
            conn.request("POST", "/accounts/ClientLogin", params, headers)
            response = conn.getresponse()
            if response.status != 200:
                raise Exception("Failed to login: %s %s" % (
                    response.status,
                    response.reason))
            body = response.read()
            for line in body.splitlines():
                if line.startswith("Auth="):
                    self._auth_token = line[5:]
                    break
            if not self._auth_token:
                raise Exception("Cannot find auth token in response %s" % body)
        if not self._conn:
            self._conn = httplib.HTTPConnection("maps.google.com")
        return self._conn

    connection = property(_get_connection)

    def upload(self, kml_data):
        conn = self.connection
        headers = {
            "GData-Version": "2.0",
            "Authorization": 'GoogleLogin auth=%s' % (self._auth_token,),
            "Content-Type": "application/vnd.google-earth.kml+xml",
        }
        conn.request("POST", "/maps/feeds/maps/default/full", kml_data, headers)
        response = conn.getresponse()
        if response.status != 200:
            raise Exception("Failed to upload kml: %s %s" % (
                response.status,
                response.reason))
        return response.read()

if __name__ == "__main__":
    parser = optparse.OptionParser()
    parser.add_option("-e", "--email", help="Email address for login")
    parser.add_option("-p", "--passwd", help="Password for login")
    options, args = parser.parse_args()
    if not (options.email and options.passwd):
        parser.error("email and passwd required")
    if args:
        kml_file = open(args[0], "r")
    else:
        kml_file = sys.stdin
    maps = GoogleMaps(options.email, options.passwd)
    print maps.upload(kml_file.read())

不幸的是,即使使用有效的登录凭据获得有效的授权令牌,并且使用包含文档中给出的示例的有效KML文件,API在处理KML请求时仍然返回400 Bad Request。显然,这是一个已知问题(2590,报告于2010年7月22日),如果你希望谷歌修复这个问题,请为其投票并发表评论。

在此期间,如果这个bug没有修复,你可以尝试:

  1. 先创建地图,而不上传KML,然后根据需要上传KML特征,正如谷歌在问题的第9条评论中建议的那样,他们确认了这个bug的存在。
  2. 如果这些方法支持你需要完成的工作,可以尝试上传XML上传CSV,而不是KML。
  3. 调整你的KML数据格式。谷歌API小组中的这篇帖子建议这可能有帮助,但看起来有点复杂。

祝你好运

撰写回答