作为我去年提出的Neo4j演讲建议的一部分,我有一组脚本,这些脚本可以从metup.com API下载一些数据。
它们都是用Python编写的,但是我认为查看它们在Go中的外观将是一个有趣的练习。 我最终的目标是尝试并行化API调用。
这是脚本的Python版本:
import requests
import os
import json
key = os.environ['MEETUP_API_KEY']
lat = "51.5072"
lon = "0.1275"
seed_topic = "nosql"
uri = "https://api.meetup.com/2/groups?⊤ic={0}⪫={1}&lon={2}&key={3}".format(seed_topic, lat, lon, key)
r = requests.get(uri)
all_topics = [topic["urlkey"] for result in r.json()["results"] for topic in result["topics"]]
for topic in all_topics:
print topic
导入请求import os import json key = os.environ ['MEETUP_API_KEY'] lat =“ 51.5072” lon =“ 0.1275” seed_topic =“ nosql” uri =“ https://api.meetup.com/2/groups?&topic= {0}&lat = {1}&lon = {2}&key = {3}”。格式(seed_topic,lat,lon,key)r = request.get(uri)all_topics = [topic [“ urlkey”]用于结果r.json()[“ results”]表示all_topics中主题的结果[“ topics”]]:打印主题
我们正在使用请求库将请求发送到metup API,以获取伦敦区域中主题为“ nosql”的组。 然后,我们解析响应并打印出主题。
现在在Go中执行相同的操作! 脚本的第一部分几乎相同:
import (
"fmt"
"os"
"net/http"
"log"
"time"
)
func handleError(err error) {
if err != nil {
fmt.Println(err)
log.Fatal(err)
}
}
func main() {
var httpClient = &http.Client{Timeout: 10 * time.Second}
seedTopic := "nosql"
lat := "51.5072"
lon := "0.1275"
key := os.Getenv("MEETUP_API_KEY")
uri := fmt.Sprintf("https://api.meetup.com/2/groups?⊤ic=%s⪫=%s&lon=%s&key=%s", seedTopic, lat, lon, key)
response, err := httpClient.Get(uri)
handleError(err)
defer response.Body.Close()
fmt.Println(response)
}
import(“ fmt”“ os”“ net / http”“ log”“时间”)func handleError(err error){if err!= nil {fmt.Println(err)log.Fatal(err)}} func main( ){var httpClient =&http.Client {Timeout:10 * time.Second} seedTopic:=“ nosql” lat:=“ 51.5072” lon:=“ 0.1275” key:= os.Getenv(“ MEETUP_API_KEY”)uri:= fmt .Sprintf(“ https://api.meetup.com/2/groups?&topic=%s&lat=%s&lon=%s&key=%s”,seedTopic,lat,lon,key)响应,错误:= httpClient.Get( uri)handleError(err)延迟response.Body.Close()fmt.Println(response)}
如果运行,这是输出,我们将看到:
$ go cmd/blog/main.go
&{200 OK 200 HTTP/2.0 2 0 map[X-Meetup-Request-Id:[2d3be3c7-a393-4127-b7aa-076f150499e6] X-Ratelimit-Reset:[10] Cf-Ray:[324093a73f1135d2-LHR] X-Oauth-Scopes:[basic] Etag:["35a941c5ea3df9df4204d8a4a2d60150"] Server:[cloudflare-nginx] Set-Cookie:[__cfduid=d54db475299a62af4bb963039787e2e3d1484894864; expires=Sat, 20-Jan-18 06:47:44 GMT; path=/; domain=.meetup.com; HttpOnly] X-Meetup-Server:[api7] X-Ratelimit-Limit:[30] X-Ratelimit-Remaining:[29] X-Accepted-Oauth-Scopes:[basic] Vary:[Accept-Encoding,User-Agent,Accept-Language] Date:[Fri, 20 Jan 2017 06:47:45 GMT] Content-Type:[application/json;charset=utf-8]] 0xc420442260 -1 [] false true map[] 0xc4200d01e0 0xc4202b2420}
$ go cmd / blog / main.go&{200 OK 200 HTTP / 2.0 2 0 map [X-Meetup-Request-Id:[2d3be3c7-a393-4127-b7aa-076f150499e6] X-Ratelimit-Reset:[10] Cf -Ray:[324093a73f1135d2-LHR] X-Oauth-范围:[basic] Etag:[“ 35a941c5ea3df9df4204d8a4a2d60150”]服务器:[cloudflare-nginx] Set-Cookie:[__ cfduid = d54db475299a62af4bb9630397879484e expires =格林尼治标准时间18年1月20日星期六6:47:44; 路径= /; domain = .meetup.com; HttpOnly] X-Meetup-Server:[api7] X-Ratelimit-Limit:[30] X-Ratelimit-Remaining:[29] X-Accepted-Oauth-Scopes:[基本]变化:[Accept-Encoding,User-Agent ,Accept-Language]日期:[2017年1月20日星期五,格林尼治标准时间]内容类型:[application / json; charset = utf-8]] 0xc420442260 -1 []假真实地图[] 0xc4200d01e0 0xc4202b2420}
到目前为止,一切都很好。 现在我们需要解析返回的响应。
我碰到的大多数示例都建议使用您要从JSON文档中提取的所有字段创建一个结构,但是对于这样一个简单的脚本来说,这有点让人难以接受。
相反,我们可以只创建(string-> interface {})的映射,然后在适当的地方应用类型转换。 我最终得到了以下代码来提取主题:
import "encoding/json"
var target map[string]interface{}
decoder := json.NewDecoder(response.Body)
decoder.Decode(⌖)
for _, rawGroup := range target["results"].([]interface{}) {
group := rawGroup.(map[string]interface{})
for _, rawTopic := range group["topics"].([]interface{}) {
topic := rawTopic.(map[string]interface{})
fmt.Println(topic["urlkey"])
}
}
导入“ encoding / json” var目标映射[字符串]接口{}解码器:= json.NewDecoder(response.Body)解码器。_的原始解码器(&target),rawGroup:=范围目标[“结果”]。([]接口{}){group:= rawGroup。(map [string] interface {})for _,rawTopic:= range group [“ topics”]。([] interface {}){topic:= rawTopic。(map [string] interface {})fmt.Println(topic [“ urlkey”])}}
Python版本更加冗长,因为我们必须在每个阶段显式键入从地图中取出的所有内容,但这还不错。 这是完整的脚本:
package main
import (
"fmt"
"os"
"net/http"
"log"
"time"
"encoding/json"
)
func handleError(err error) {
if err != nil {
fmt.Println(err)
log.Fatal(err)
}
}
func main() {
var httpClient = &http.Client{Timeout: 10 * time.Second}
seedTopic := "nosql"
lat := "51.5072"
lon := "0.1275"
key := os.Getenv("MEETUP_API_KEY")
uri := fmt.Sprintf("https://api.meetup.com/2/groups?⊤ic=%s⪫=%s&lon=%s&key=%s", seedTopic, lat, lon, key)
response, err := httpClient.Get(uri)
handleError(err)
defer response.Body.Close()
var target map[string]interface{}
decoder := json.NewDecoder(response.Body)
decoder.Decode(⌖)
for _, rawGroup := range target["results"].([]interface{}) {
group := rawGroup.(map[string]interface{})
for _, rawTopic := range group["topics"].([]interface{}) {
topic := rawTopic.(map[string]interface{})
fmt.Println(topic["urlkey"])
}
}
}
包主要导入(“ fmt”“ os”“ net / http”“ log”“ time”“ encoding / json”)func handleError(err error){if err!= nil {fmt.Println(err)log.Fatal( err)}} func main(){var httpClient =&http.Client {Timeout:10 * time.Second} seedTopic:=“ nosql” lat:=“ 51.5072” lon:=“ 0.1275” key:= os.Getenv(“ MEETUP_API_KEY”)uri:= fmt.Sprintf(“ https://api.meetup.com/2/groups?&topic=%s&lat=%s&lon=%s&key=%s”,seedTopic,lat,lon,key)响应,错误:= httpClient.Get(uri)handleError(错误)延迟response.Body.Close()var target map [string] interface {}解码器:= json.NewDecoder(response.Body)解码器。Decode(&target)用于_, rawGroup:=范围目标[“结果”]。([] interface {}){group:= rawGroup。(map [string] interface {})for _,rawTopic:=范围组[“ topics”]。([[ interface {}){topic:= rawTopic。(map [string] interface {})fmt.Println(topic [“ urlkey”])}}}
一旦获得了这些主题,下一步就是进行更多的API调用以获取这些主题的组。
我想同时进行那些API调用,同时确保不超出API的速率限制限制,我认为我可以利用go例程,通道和计时器来做到这一点。 但这是另一篇文章!
翻译自: https://www.javacodegeeks.com/2017/01/go-vs-python-parsing-json-response-http-api.html