在Python中使用Bing或Google API获取位置信息坐标

3 投票
3 回答
9329 浏览
提问于 2025-04-17 14:02

我遇到的问题是这样的。我有一个示例文本文件,里面存储了我通过爬取各种网页获得的文本数据。这些文本包含了关于各种活动的信息,包括时间和地点。我想获取这些地点的坐标,但我不知道怎么用Python来实现这个功能。我正在使用nltk来识别这些文本中的命名实体。以下是我的代码:

import nltk

with open('sample.txt', 'r') as f:
    sample = f.read()

sentences = nltk.sent_tokenize(sample)
tokenized_sentences = [nltk.word_tokenize(sentence) for sentence in sentences]
tagged_sentences = [nltk.pos_tag(sentence) for sentence in tokenized_sentences]
chunked_sentences = nltk.batch_ne_chunk(tagged_sentences, binary=True)

#print chunked_sentences
#print tokenized_sentences
#print tagged_sentences

def extract_entity_names(t):
    entity_names = []

    if hasattr(t, 'node') and t.node:
        if t.node == 'NE':
            entity_names.append(' '.join([child[0] for child in t]))
        else:
            for child in t:
                entity_names.extend(extract_entity_names(child))

    return entity_names

entity_names = []
for tree in chunked_sentences:
    # Print results per sentence
    # print extract_entity_names(tree)

    entity_names.extend(extract_entity_names(tree))

# Print all entity names
#print entity_names

# Print unique entity names
print set(entity_names)

示例文件的内容大致是这样的:

《波希米亚人》在科文特花园

时间:2013年1月18日(还有其他日期),晚上7:30 地点:科文特花园,伦敦,约翰·科普利的经典皇家歌剧院制作的普契尼的《波希米亚人》将在这个季节的两次演出中首次复排,正好是在圣诞期间。马克·埃尔德爵士指挥,罗兰多·维拉松饰演罗道夫,玛雅·科瓦列夫斯卡饰演米咪。米咪在寒冷的圣诞夜与诗人罗道夫相遇(德米特罗·波波夫在1月5日和18日演出这个角色),他们在巴黎的拉丁区的黑暗中相遇,米咪的蜡烛熄灭了,他们相爱了。罗道夫和另外三个小伙子住在一起:哲学家科林(纳胡埃尔·迪·皮耶罗/金志勋在1月18日演出),音乐家肖纳德(大卫·比齐克)和画家马塞洛(奥登·伊弗森),他爱着穆塞塔(斯特凡尼亚·多夫汉)。这对情侣都分手了,歌剧以悲剧收场,罗道夫发现米咪在一个冰冷的阁楼里因肺结核而奄奄一息。

我想从这段文本中获取科文特花园,伦敦的坐标。我该怎么做呢?

3 个回答

1

你想做的操作叫做地理编码操作。简单来说,就是从一段文字信息中提取出“位置”相关的信息。

你可以使用以下服务来实现这个功能:

请记得,根据你的使用情况,可能需要考虑相关的许可证问题。

6

自2013年9月起,Google Maps API v2 已经不再可用。这里有一个更新版的代码,适用于API v3,是来自@jimhark的优秀代码(我省略了__main__部分):

import urllib
import simplejson

googleGeocodeUrl = 'http://maps.googleapis.com/maps/api/geocode/json?'

def get_coordinates(query, from_sensor=False):
    query = query.encode('utf-8')
    params = {
        'address': query,
        'sensor': "true" if from_sensor else "false"
    }
    url = googleGeocodeUrl + urllib.urlencode(params)
    json_response = urllib.urlopen(url)
    response = simplejson.loads(json_response.read())
    if response['results']:
        location = response['results'][0]['geometry']['location']
        latitude, longitude = location['lat'], location['lng']
        print query, latitude, longitude
    else:
        latitude, longitude = None, None
        print query, "<no results>"
    return latitude, longitude

想要了解完整的参数列表和更多信息,可以查看官方文档

5

你其实有两个问题:

  1. 如何提取位置文本(或者可能的位置文本)。
  2. 如何通过调用地理编码服务,用位置文本获取经纬度(纬度和经度)。

我可以帮你解决第二个问题。(不过下面的编辑部分也会给你第一问题一些帮助。)

在旧版的谷歌地图API中(现在仍然可以用),你可以用一行代码完成地理编码(虽然这一行代码看起来不太好):

def geocode(address):
    return tuple([float(s) for s in list(urllib.urlopen('http://maps.google.com/maps/geo?' + urllib.urlencode({'output': 'csv','q': address})))[0].split(',')[2:]])

你可以查看一下 谷歌地图API地理编码文档

这里有一个可读性更好的7行版本,还有一些包装代码(在命令行调用时记得把地址用引号括起来):

import sys
import urllib

googleGeocodeUrl = 'http://maps.google.com/maps/geo?'

def geocode(address):
    parms = {
        'output': 'csv',
        'q': address}

    url = googleGeocodeUrl + urllib.urlencode(parms)
    resp = urllib.urlopen(url)
    resplist = list(resp)
    line = resplist[0]
    status, accuracy, latitude, longitude = line.split(',')
    return latitude, longitude

def main():
    if 1 < len(sys.argv):
        address = sys.argv[1]
    else:
        address = '1600 Amphitheatre Parkway, Mountain View, CA 94043, USA'

    coordinates = geocode(address)
    print coordinates

if __name__ ==  '__main__':
    main()

解析CSV格式很简单,但XML格式的错误报告更好。

编辑 - 帮助你解决第一个问题

我查了一下 nltk。这不是一件简单的事,但我可以推荐 自然语言工具包文档,第7章 - 从文本中提取信息,特别是 7.5 命名实体识别。在这一节的最后,他们提到:

NLTK提供了一个已经训练好的分类器,可以识别命名实体,通过函数nltk.ne_chunk()访问。如果我们设置参数binary=True,那么命名实体就会被标记为NE;否则,分类器会添加类别标签,比如PERSON(人名)、ORGANIZATION(组织名)和GPE(地理位置名)。

你设置的是 True,但你可能想要类别标签,所以:

chunked_sentences = nltk.batch_ne_chunk(tagged_sentences)

这样可以提供类别标签(命名实体类型),看起来很有希望。但是在你提供的文本和一些简单的地点短语上尝试后,明显需要更多的规则。可以查看文档获取更多信息。

撰写回答