如何突破Google Maps API限制获取开罗所有كشري餐厅
解决Google Maps Places Nearby API仅返回20条结果的问题
为什么只返回20条?
Google Places Nearby API默认单次请求返回20条结果,最多支持通过3次分页请求获取总计60条结果。要拿到全部符合条件的餐厅,需要处理API的分页机制;若结果超过60条,还得拆分搜索区域覆盖整个开罗。
第一步:处理分页,获取最多60条结果
修改代码,循环检查响应中的next_page_token,直到没有更多结果为止。注意,获取下一页前需要添加短暂延迟(建议2秒以上),因为token不会立即生效。
修改后的代码示例:
import time import gmaps # 获取开罗的经纬度与区域信息 geocode_result = gmaps.geocode('Cairo')[0] latitude = geocode_result['geometry']['location']['lat'] longitude = geocode_result['geometry']['location']['lng'] district = geocode_result['address_components'][2]['long_name'] restaurants = [] next_page_token = None # 循环获取所有分页结果 while True: # 根据是否存在分页token构造请求参数 if next_page_token: results = gmaps.places_nearby(page_token=next_page_token) else: results = gmaps.places_nearby( location=(latitude, longitude), radius=10000, keyword='كشري', type='restaurant' ) # 存储当前页的餐厅信息,新增place_id用于后续去重 for result in results['results']: restaurants.append({ 'name': result['name'], 'long': result['geometry']['location']['lng'], 'lat': result['geometry']['location']['lat'], 'district': district, 'place_id': result['place_id'], 'polygon': result['geometry'] }) # 检查是否有下一页 next_page_token = results.get('next_page_token') if not next_page_token: break # 等待token生效,避免API报错 time.sleep(2) # 格式化打印结果 print('Name\t\tLongitude\tLatitude\tDistrict\tPlace ID') for restaurant in restaurants: print(f"{restaurant['name']}\t{restaurant['long']}\t{restaurant['lat']}\t{restaurant['district']}\t{restaurant['place_id']}")
第二步:处理超过60条的情况
如果开罗境内的كشري餐厅数量超过60条,上述方法无法获取全部结果,需要拆分搜索区域:
- 按行政分区搜索:先通过Geocoding API获取开罗的各个子行政区,再逐个在每个行政区范围内执行分页搜索。
- 网格覆盖搜索:将开罗区域划分为多个小半径的搜索点(比如把10000米半径拆分为多个2000米半径的搜索点),分别发起请求后合并结果,并用
place_id去重。
示例思路(按行政分区搜索):
# 获取开罗的子行政区列表 cairo_subdistricts = gmaps.geocode('Cairo, Egypt', components={'administrative_area_level_2': 'Cairo'}) all_restaurants = [] # 遍历每个子行政区执行搜索 for subdistrict in cairo_subdistricts: sub_lat = subdistrict['geometry']['location']['lat'] sub_lng = subdistrict['geometry']['location']['lng'] sub_district_name = subdistrict['address_components'][0]['long_name'] # 复用之前的分页搜索逻辑,替换当前子行政区的经纬度和区域名称 next_token = None while True: if next_token: sub_results = gmaps.places_nearby(page_token=next_token) else: sub_results = gmaps.places_nearby( location=(sub_lat, sub_lng), radius=5000, keyword='كشري', type='restaurant' ) for res in sub_results['results']: all_restaurants.append({ 'name': res['name'], 'long': res['geometry']['location']['lng'], 'lat': res['geometry']['location']['lat'], 'district': sub_district_name, 'place_id': res['place_id'], 'polygon': res['geometry'] }) next_token = sub_results.get('next_page_token') if not next_token: break time.sleep(2) # 基于place_id去重 unique_restaurants = list({r['place_id']: r for r in all_restaurants}.values())
注意事项
- API调用会产生费用,请关注Google Cloud的配额和计费规则。
- 必须用
place_id作为唯一标识去重,避免同一餐厅被多次抓取。 - 不要缩短分页请求的延迟时间,否则会触发API的速率限制报错。
内容的提问来源于stack exchange,提问作者Esmael Maher
相关产品推荐
相关产品推荐

