You need to enable JavaScript to run this app. 调用Teleport API遇正则类型错误,如何正确提取首个geonameid
优惠活动
大模型
产品
解决方案
定价
更多

调用Teleport API遇正则类型错误,如何正确提取首个geonameid

报错根因说明

你触发TypeError: expected string or bytes-like object的核心原因非常直接:

  • re.search()方法要求第二个入参必须是字符串或字节类对象,但你的代码里调用这个方法时,传入的api变量是json.loads()解析完成的Python嵌套字典对象,类型完全不匹配
  • 哪怕注释掉后续的强制类型转换行也没用,因为报错发生在re.search()调用的瞬间,和后面的转换逻辑没有任何关联
原有实现的逻辑偏差

你想从API返回结果里提取geonameid的思路存在不必要的冗余:

  • 既然已经把接口返回的JSON文本解析成了结构化字典,完全不需要用正则去逆向匹配文本内容,直接按字典的固定层级取值可靠性更高
  • 针对多结果返回的城市重名场景,Teleport搜索接口的返回结果是按匹配度从高到低排序的,直接取列表首个元素的逻辑本身符合业务需求,不需要额外调整匹配优先级
正确实现步骤

按照接口返回的固定嵌套结构,按层级取值即可,不需要引入正则做匹配:

  • 解析接口返回的字典后,先定位到_embedded键,再取对应的city:search-results列表(所有匹配城市的集合)
  • 取列表索引为0的元素,就是匹配度最高的首个城市结果
  • 顺着该结果的层级依次取值:结果对象内的_links → city:item → href字段,拿到格式为https://api.teleport.org/api/cities/geonameid:5809844/的详情链接
  • 对链接字符串做简单分割,提取geonameid:后的数字部分,去掉末尾的斜杠,就能得到最终的城市ID
修正后的完整代码
import urllib.request
import json

area = input("What's the city you'd like to see? ")
area = area.lower().replace(' ', '-')
if area == 'new-york-city':
    area = 'new-york'

with urllib.request.urlopen(f'https://api.teleport.org/api/cities/?search={area}') as url:
    api_resp = json.loads(url.read().decode())
    search_results = api_resp['_embedded']['city:search-results']
    
    # 增加空结果兜底判断
    if not search_results:
        print("未匹配到对应城市,请调整输入关键词重试")
    else:
        # 取首个匹配城市
        first_city = search_results[0]
        city_detail_url = first_city['_links']['city:item']['href']
        # 拆分提取geonameid
        geonameid = city_detail_url.split('geonameid:')[1].rstrip('/')
        print(f"首个匹配城市的geonameid为:{geonameid}")
补充说明
  • 这种结构化取值的方式比正则匹配更稳定:后续如果API调整返回的文本格式(比如修改URL的拼接规则、在JSON文本里加入额外的注释类内容),正则匹配很容易失效,而按字典键名取值的逻辑只要和API文档约定的结构一致,就不会出问题
  • 如果后续需要支持用户从多个重名结果里手动选择城市,只需要把search_results列表遍历打印出来让用户选索引值即可,不需要额外改动取值逻辑

内容的提问来源于stack exchange,提问作者ESarousi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.30 18:06:04