在Go语言中使用pagetoken循环遍历Google Places API时遇到了问题。

huangapple go评论81阅读模式
英文:

trouble looping through google places API with pagetoken in Go

问题

我在Go语言中遍历Google Places API时遇到了问题。

Google的Places API最多返回20个结果,并使用pagetoken参数将其添加到查询中,以返回下一个20个结果,直到没有剩余结果为止。

我目前能够发送查询请求,返回JSON并在终端中输出,但是当我尝试循环并将pagetoken参数添加到查询中时,它会运行,但只返回第一页的结果,并附带另一个页面令牌。有什么想法我做错了什么?

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	// "os"
)

type GooglePlaces struct {
	HTMLAttributions []interface{} `json:"html_attributions"`
	NextPageToken    string        `json:"next_page_token"`
	Results          []struct {
		Geometry struct {
			Location struct {
				Lat float64 `json:"lat"`
				Lng float64 `json:"lng"`
			} `json:"location"`
			Viewport struct {
				Northeast struct {
					Lat float64 `json:"lat"`
					Lng float64 `json:"lng"`
				} `json:"northeast"`
				Southwest struct {
					Lat float64 `json:"lat"`
					Lng float64 `json:"lng"`
				} `json:"southwest"`
			} `json:"viewport"`
		} `json:"geometry"`
		Icon         string `json:"icon"`
		ID           string `json:"id"`
		Name         string `json:"name"`
		OpeningHours struct {
			OpenNow     bool          `json:"open_now"`
			WeekdayText []interface{} `json:"weekday_text"`
		} `json:"opening_hours,omitempty"`
		Photos []struct {
			Height           int      `json:"height"`
			HTMLAttributions []string `json:"html_attributions"`
			PhotoReference   string   `json:"photo_reference"`
			Width            int      `json:"width"`
		} `json:"photos,omitempty"`
		PlaceID   string   `json:"place_id"`
		Reference string   `json:"reference"`
		Scope     string   `json:"scope"`
		Types     []string `json:"types"`
		Vicinity  string   `json:"vicinity"`
		Rating    float64  `json:"rating,omitempty"`
	} `json:"results"`
	Status string `json:"status"`
}

func searchPlaces(page string) {
	apiKey := "API_KEY_HERE"
	keyword := "residential+bank+33131"
	latLong := "25.766144,-80.190589"
	pageToken := page
	var buffer bytes.Buffer

	buffer.WriteString("https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=")
	buffer.WriteString(latLong)
	buffer.WriteString("&radius=50000&keyword=")
	buffer.WriteString(keyword)
	buffer.WriteString("&key=")
	buffer.WriteString(apiKey)
	buffer.WriteString("&pagetoken=")
	buffer.WriteString(pageToken)

	query := buffer.String()

	// 打印当前搜索
	println("query is ", query)
	println("\n")

	// 使用查询发送请求
	resp, err := http.Get(query)
	if err != nil {
		log.Fatal(err)
	}
	// 关闭HTTP响应返回的预关闭器
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	res := GooglePlaces{}
	json.Unmarshal([]byte(body), &res)

	var listings bytes.Buffer
	for i := 0; i < len(res.Results); i++ {
		listings.WriteString(strconv.Itoa(i + 1))
		listings.WriteString("\nName: ")
		listings.WriteString(res.Results[i].Name)
		listings.WriteString("\nAddress: ")
		listings.WriteString(res.Results[i].Vicinity)
		listings.WriteString("\nPlace ID: ")
		listings.WriteString(res.Results[i].PlaceID)
		listings.WriteString("\n---------------------------------------------\n\n")
	}
	listings.WriteString("\npagetoken is now:\n")
	listings.WriteString(res.NextPageToken)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(listings.String())
	fmt.Printf("\n\n\n")

	// 循环调用函数
	searchPlaces(res.NextPageToken)

}

func main() {
	searchPlaces("")
}
英文:

Im having trouble looping through the Google Places API in Go.

Google's Places API returns 20 results max with a pagetoken parameter to add to the query to return the next 20 results until theres none left.

I currently am able to send a query request, return the json and output it in terminal, but when i try to loop back through and add the pagetoken parameter to the query, it runs but only returns the first page results again but with another page token. Any Idea what im doing wrong?

<!-- language: go -->
package main

import (
&quot;bytes&quot;
&quot;encoding/json&quot;
&quot;fmt&quot;
&quot;io/ioutil&quot;
&quot;log&quot;
&quot;net/http&quot;
&quot;strconv&quot;
// &quot;os&quot;
)
type GooglePlaces struct {
HTMLAttributions []interface{} `json:&quot;html_attributions&quot;`
NextPageToken    string        `json:&quot;next_page_token&quot;`
Results          []struct {
Geometry struct {
Location struct {
Lat float64 `json:&quot;lat&quot;`
Lng float64 `json:&quot;lng&quot;`
} `json:&quot;location&quot;`
Viewport struct {
Northeast struct {
Lat float64 `json:&quot;lat&quot;`
Lng float64 `json:&quot;lng&quot;`
} `json:&quot;northeast&quot;`
Southwest struct {
Lat float64 `json:&quot;lat&quot;`
Lng float64 `json:&quot;lng&quot;`
} `json:&quot;southwest&quot;`
} `json:&quot;viewport&quot;`
} `json:&quot;geometry&quot;`
Icon         string `json:&quot;icon&quot;`
ID           string `json:&quot;id&quot;`
Name         string `json:&quot;name&quot;`
OpeningHours struct {
OpenNow     bool          `json:&quot;open_now&quot;`
WeekdayText []interface{} `json:&quot;weekday_text&quot;`
} `json:&quot;opening_hours,omitempty&quot;`
Photos []struct {
Height           int      `json:&quot;height&quot;`
HTMLAttributions []string `json:&quot;html_attributions&quot;`
PhotoReference   string   `json:&quot;photo_reference&quot;`
Width            int      `json:&quot;width&quot;`
} `json:&quot;photos,omitempty&quot;`
PlaceID   string   `json:&quot;place_id&quot;`
Reference string   `json:&quot;reference&quot;`
Scope     string   `json:&quot;scope&quot;`
Types     []string `json:&quot;types&quot;`
Vicinity  string   `json:&quot;vicinity&quot;`
Rating    float64  `json:&quot;rating,omitempty&quot;`
} `json:&quot;results&quot;`
Status string `json:&quot;status&quot;`
}
func searchPlaces(page string) {
apiKey := &quot;API_KEY_HERE&quot;
keyword := &quot;residential+bank+33131&quot;
latLong := &quot;25.766144,-80.190589&quot;
pageToken := page
var buffer bytes.Buffer
buffer.WriteString(&quot;https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=&quot;)
buffer.WriteString(latLong)
buffer.WriteString(&quot;&amp;radius=50000&amp;keyword=&quot;)
buffer.WriteString(keyword)
buffer.WriteString(&quot;&amp;key=&quot;)
buffer.WriteString(apiKey)
buffer.WriteString(&quot;&amp;pagetoken=&quot;)
buffer.WriteString(pageToken)
query := buffer.String()
// PRINT CURRENT SEARCH
println(&quot;query is &quot;, query)
println(&quot;\n&quot;)
// SEND REQUEST WITH QUERY
resp, err := http.Get(query)
if err != nil {
log.Fatal(err)
}
// CLOSE THE PRECLOSER THATS RETURNED WITH HTTP RESPONSE
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
res := GooglePlaces{}
json.Unmarshal([]byte(body), &amp;res)
var listings bytes.Buffer
for i := 0; i &lt; len(res.Results); i++ {
listings.WriteString(strconv.Itoa(i + 1))
listings.WriteString(&quot;\nName: &quot;)
listings.WriteString(res.Results[i].Name)
listings.WriteString(&quot;\nAddress: &quot;)
listings.WriteString(res.Results[i].Vicinity)
listings.WriteString(&quot;\nPlace ID: &quot;)
listings.WriteString(res.Results[i].PlaceID)
listings.WriteString(&quot;\n---------------------------------------------\n\n&quot;)
}
listings.WriteString(&quot;\npagetoken is now:\n&quot;)
listings.WriteString(res.NextPageToken)
if err != nil {
log.Fatal(err)
}
fmt.Println(listings.String())
fmt.Printf(&quot;\n\n\n&quot;)
// LOOP BACK THROUGH FUNCTION
searchPlaces(res.NextPageToken)
}
func main() {
searchPlaces(&quot;&quot;)
}

答案1

得分: 2

请注意,在Google Place Search的文档中,他们指出:

> 在发出next_page_token之后,它将变为有效之前会有一段短暂的延迟。

但是在你的代码中,你立即使用了新的token发送请求。

在使用token之前,添加几秒钟的延迟可以解决我的问题。我将你的代码更改为:

	if res.NextPageToken != &quot;&quot; {
time.Sleep(3000 * time.Millisecond)
searchPlaces(res.NextPageToken)
} else {
fmt.Println(&quot;没有更多的pagetoken,我们完成了。&quot;)
}

不幸的是,没有关于token有效期的文档说明。

英文:

Note that in the documentation for Google Place Search they state:

> There is a short delay between when a next_page_token is issued, and when it will become valid.

But in your code you immediately send a request with the new token.

Adding a sleep for a few seconds before using the token solves the problem for me. I changed your code to

	if res.NextPageToken != &quot;&quot; {
time.Sleep(3000 * time.Millisecond)
searchPlaces(res.NextPageToken)
} else {
fmt.Println(&quot;No more pagetoken, we&#39;re done.&quot;)
}

Unfortunately there's no documentation about for how long a token is valid.

huangapple
  • 本文由 发表于 2017年2月2日 12:38:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/41994292.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定