在Python中使用Bing或Google API获取位置信息坐标
我遇到的问题是这样的。我有一个示例文本文件,里面存储了我通过爬取各种网页获得的文本数据。这些文本包含了关于各种活动的信息,包括时间和地点。我想获取这些地点的坐标,但我不知道怎么用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 个回答
你想做的操作叫做地理编码操作。简单来说,就是从一段文字信息中提取出“位置”相关的信息。
你可以使用以下服务来实现这个功能:
- 必应地图:http://msdn.microsoft.com/en-us/library/ff701714.aspx
- 谷歌地图:https://developers.google.com/maps/documentation/geocoding/
- 诺基亚地图:http://developer.here.net/javascript_api_explorer
请记得,根据你的使用情况,可能需要考虑相关的许可证问题。
自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
想要了解完整的参数列表和更多信息,可以查看官方文档。
你其实有两个问题:
- 如何提取位置文本(或者可能的位置文本)。
- 如何通过调用地理编码服务,用位置文本获取经纬度(纬度和经度)。
我可以帮你解决第二个问题。(不过下面的编辑部分也会给你第一问题一些帮助。)
在旧版的谷歌地图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)
这样可以提供类别标签(命名实体类型),看起来很有希望。但是在你提供的文本和一些简单的地点短语上尝试后,明显需要更多的规则。可以查看文档获取更多信息。