使用Google Places API获取超过20个结果

45

我想开发一个地图应用程序,它可以显示给定地点附近的银行。

我使用Places库进行搜索,但每次只返回20个结果。如果我想要更多的结果,我该怎么做?

7个回答

24

更新: 自从我最初写下这篇答案以来,API已经进行了增强,使得这个答案已经过时(或者至少是不完整的)。请参见如何从Google Places API获取20个以上的结果?以获取更多信息。

原始答案:

文档显示Places API返回最多20个结果。它没有表明有任何改变那个限制的方法。所以,简短的答案似乎是:你不能。

当然,你可能能够通过查询几个位置来模拟它,并合并/去重结果。虽然这是一种廉价的hack,但可能效果不佳。在此之前,我会先检查一下它是否违反了服务条款。


谢谢你的回答。我也曾想过那个 hack :) 我再次检查了文档,但找不到可以更改限制的参数。我只是想知道是否有更好的来源来获取结果? - Demon
@Trott,你好Trott,我也遇到了同样的问题。我该如何获取更多的数据?如果你看过Google的Places应用程序,它会在Listview滚动到底部时获取数据。那么它是不是再次触发查询呢?如果你有任何建议,请帮忙提供一下... - Scorpion
@Scorpion,你可以尝试像这样做:当半径小于最大限制时,增加半径并发送查询,最后删除重复项。这会有所帮助,但目前的Google Places API几乎没用。 - Eduardo

20

现在API支持更多的结果(最多60个),使用一个参数page_token可以获取前面搜索结果的下一批20个结果。

使用page_token参数可以获取之前搜索相同条件的下一批20个结果,其他所有参数除了page_token都会被忽略。

你还可以参考访问额外的结果部分来查看如何进行分页的示例。


10
值得补充的是,使用这种方法最大的结果数量为60,参考https://dev59.com/vGkw5IYBdhLWcg3w1eC7#9627664。 - HischT
@HischT,是的,我知道这个限制,对我来说很遗憾,但当我发布答案时忘记写了。已编辑,谢谢! :) - Eduardo

6
作为回应Eduardo的问题,谷歌现在已经添加了这个功能。但是Places文档也指出:
最多只能返回60个结果。
因此仍然有上限。另外,需要注意的是,“next_page_token”变成有效令牌之间存在一定的延迟,正如谷歌所述:
发出“next_page_token”令牌和其变为有效令牌之间存在短暂延迟。
以下是官方Places API文档:

https://developers.google.com/places/documentation/


2
这里是一个代码示例,它将寻找更多的结果。
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Web.Script.Serialization;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var url = $"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location={args[0]}&radius={args[1]}&type=restaurant&keyword={args[2]}&key={args[3]}";

            dynamic res = null;
            var places = new List<PlacesAPIRestaurants>();
            using (var client = new HttpClient())
            {
                while (res == null || HasProperty(res, "next_page_token"))
                {
                    if (res != null && HasProperty(res, "next_page_token"))
                    {
                        if (url.Contains("pagetoken"))
                            url = url.Split(new string[] { "&pagetoken=" }, StringSplitOptions.None)[0];
                        url += "&pagetoken=" + res["next_page_token"];

                    }
                    var response = client.GetStringAsync(url).Result;
                    JavaScriptSerializer json = new JavaScriptSerializer();
                    res = json.Deserialize<dynamic>(response);
                    if (res["status"] == "OK")
                    {
                        foreach (var place in res["results"])
                        {
                            var name = place["name"];
                            var rating = HasProperty(place,"rating") ? place["rating"] : null;
                            var address = place["vicinity"];
                            places.Add(new PlacesAPIRestaurants
                            {
                                Address = address,
                                Name = name,
                                Rating = rating
                            });
                        }
                    }
                    else if (res["status"] == "OVER_QUERY_LIMIT")
                    {
                        return;
                    }
                }
            }
        }

        public static bool HasProperty(dynamic obj, string name)
        {
            try
            {
                var value = obj[name];
                return true;
            }
            catch (KeyNotFoundException)
            {
                return false;
            }
        }
    }
}

希望这能为您节省一些时间。

1

您可以爬取Google Places的结果并跟随分页,以获取特定位置的200-300个地点(从10到15页的搜索结果)。

或者,您可以使用SerpApi访问从Google Places提取的数据。它有一个免费试用版。

完整示例

# Package: https://pypi.org/project/google-search-results

from serpapi import GoogleSearch
import os

params = {
    "api_key": os.getenv("API_KEY"),
    "engine": "google",
    "q": "restaurants",
    "location": "United States",
    "tbm": "lcl",
    "start": 0
}

search = GoogleSearch(params)
data = search.get_dict()

for local_result in data['local_results']:
    print(
        f"Position: {local_result['position']}\nTitle: {local_result['title']}\n"
    )

while ('next' in data['serpapi_pagination']):
    search.params_dict["start"] += len(data['local_results'])
    data = search.get_dict()

    print(f"Current page: {data['serpapi_pagination']['current']}\n")

    for local_result in data['local_results']:
        print(
            f"Position: {local_result['position']}\nTitle: {local_result['title']}\n"
        )

输出

Current page: 11

Position: 1
Title: Carbone

Position: 2
Title: Elmer's Restaurant (Palm Springs, CA)

Position: 3
Title: The Table Vegetarian Restaurant

...

免责声明:我在SerpApi工作。


1

4
现在你可以了。但是两年前我回复时你还不能这样做。如果你因为这个给我投了反对票...那真的很不酷。但我理解;-) - Jason Gennaro

0
如果问题是在搜索半径内可能无法返回所有存在的银行,我建议限制搜索半径而不是发出多个自动查询。
将半径设置为某个值,使得不可能获得超过20(60)家银行。然后让用户轻松地(通过GUI)手动执行更多查询 - 类似于绘制查询。
在较大的区域中返回数千家银行可能需要依赖您自己的银行数据库 - 如果您系统地进行工作,则可以实现这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接