iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
0

簡單動手寫個小程式:使用http去抓取MOTC Transport API V2 公車資訊,再使用json套件解析出資訊會列印出來。

1.先新增個可以爬蟲首頁的簡單code,裡面使用到了http套件去抓google首頁的資料,然後把response資料印出來

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	var (
		resp *http.Response
		err  error
		body []byte
	)
	client := &http.Client{}

	url := "https://www.google.com/?hl=zh_tw"

	reqest, err := http.NewRequest("GET", url, nil)

	if err != nil {
		panic(err)
	}
	
	resp, _ = client.Do(reqest)
	defer resp.Body.Close()

	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("ioutil.ReadAll error:", err)
		return
	}

	fmt.Println(string(body))
}

執行後應該可以順利取得google首頁的html資料

2.使用go module

go mod init

裡面空無一物

module internal/test3

go 1.14

2.原本是取google首頁,改打odata api

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	var (
		resp *http.Response
		err  error
		body []byte
	)
	client := &http.Client{}

url := "https://ptx.transportdata.tw/MOTC/v2/Bus/RealTimeByFrequency/City/Taipei?$top=30&$format=JSON"

	reqest, err := http.NewRequest("GET", url, nil)

	//增加header
	reqest.Header.Add("Accept", "application/json")
	reqest.Header.Add("Authorization", `hmac username="FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF", algorithm="hmac-sha1", headers="x-date", signature="o68jC/8QXQxWz9QW6uut0VxJKCQ="`)
	reqest.Header.Add("x-date", `Mon, 21 Sep 2020 05:56:45 GMT`)
	if err != nil {
		panic(err)
	}

	resp, _ = client.Do(reqest)
	defer resp.Body.Close()

	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("ioutil.ReadAll error:", err)
		return
	}

	fmt.Println(string(body))

}

執行成功後應該會回傳json,例如下面的資料

[{"PlateNumb":"049-FV","OperatorID":"18","RouteUID":"HSZ0007","RouteID":"0007","RouteName":{"Zh_tw":"81","En":"81"},"SubRouteUID":"HSZ000701","SubRouteID":"000701","SubRouteName":{"Zh_tw":"81","En":"81"},"Direction":0,"BusPosition":{"PositionLat":24.7699483333333,"PositionLon":120.988136666667,"GeoHash":"wsqhcjhz7"},"Speed":0.0,"Azimuth":0.0,"DutyStatus":0,"BusStatus":0,"MessageType":1,"GPSTime":"2020-09-21T13:59:33+08:00","SrcRecTime":"2020-09-21T13:59:32+08:00","SrcTransTime":"2020-09-21T13:59:32+08:00","UpdateTime":"2020-09-21T13:59:35+08:00"},{"PlateNumb":"097-FN","OperatorID":"13","RouteUID":"HSZ0010","RouteID":"0010","RouteName":{"Zh_tw":"藍線1區","En":"藍線1區"},"SubRouteUID":"HSZ001001","SubRouteID":"001001","SubRouteName":{"Zh_tw":"藍線1區","En":"藍線1區"},"Direction":0,"BusPosition":{"PositionLat":24.7882566666667,"PositionLon":121.008413333333,"GeoHash":"wsqj18edh"},"Speed":5.0,"Azimuth":133.0,"DutyStatus":0,"BusStatus":0,"MessageType":1,"GPSTime":"2020-09-21T13:59:36+08:00","SrcRecTime":"2020-09-21T13:59:36+08:00","SrcTransTime":"2020-09-21T13:59:36+08:00","UpdateTime":"2020-09-21T13:59:40+08:00"},{"PlateNumb":"099-FN","OperatorID":"13","RouteUID":"HSZ0743","RouteID":"0743","RouteName":{"Zh_tw":"藍線","En":"藍線"},"SubRouteUID":"HSZ074302","SubRouteID":"074302","SubRouteName":{"Zh_tw":"藍線","En":"藍線"},"Direction":1,"BusPosition":{"PositionLat":24.7541816666667,"PositionLon":121.73931,"GeoHash":"wsqsf4rge"}...

3.因為回傳值為json,就來用個套件gjson來解析

go get github.com/tidwall/gjson

這時候go.mod就會新增了一筆套件

require github.com/tidwall/gjson v1.6.1

把gjson套件複製到project的vendor底下

go mod vendor

這時候就可以在程式裡面import gjson套件來解析json,這次的目標是取得RouteName底下的Zh_tw的值

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	gjson "github.com/tidwall/gjson"
)

func main() {
	var (
		resp *http.Response
		err  error
		body []byte
	)
	client := &http.Client{}

	url := "https://ptx.transportdata.tw/MOTC/v2/Bus/RealTimeByFrequency/City/Taipei?$top=30&$format=JSON"

	reqest, err := http.NewRequest("GET", url, nil)

	//增加header选项
	reqest.Header.Add("Accept", "application/json")
	reqest.Header.Add("Authorization", `hmac username="FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF", algorithm="hmac-sha1", headers="x-date", signature="9wk7knxmeIOECQIBAoHUatzFwUY="`)
	reqest.Header.Add("x-date", `Mon, 21 Sep 2020 06:51:37 GMT`)
	if err != nil {
		panic(err)
	}
	//处理返回结果
	resp, _ = client.Do(reqest)
	defer resp.Body.Close()

	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("ioutil.ReadAll error:", err)
		return
	}
    //把body透過gjson.ParseBytes轉成gjson.Result的型態,因為回傳值是slice,所以用他的function Array()轉成[]gjson.Result
	gg := gjson.ParseBytes(body).Array()
    
    //使用for range遍歷整個slice,並印出資料
	for _, g := range gg {
		fmt.Println("g:", g)
		zhtw := getRouteName(g)
		fmt.Println("zhtw:", zhtw)
	}
}
func getRouteName(g gjson.Result) string {
	zhtw := g.Get("RouteName.Zh_tw").String()
	return zhtw
}

執行結果

g: {"PlateNumb":"009-U5","OperatorID":"200","RouteUID":"TPE16111","RouteID":"16111","RouteName":{"Zh_tw":"307","En":"307"},"SubRouteUID":"TPE157462","SubRouteID":"157462","SubRouteName":{"Zh_tw":"307莒光往板橋前站","En":"307"},"Direction":1,"BusPosition":{"PositionLat":25.051583,"PositionLon":121.558462,"GeoHash":"wsqqw0s0j"},"Speed":0.0,"Azimuth":267.0,"DutyStatus":1,"BusStatus":0,"MessageType":0,"GPSTime":"2020-09-21T14:54:00+08:00","SrcUpdateTime":"2020-09-21T14:54:00+08:00","UpdateTime":"2020-09-21T14:54:01+08:00"}
zhtw: 307

是不是很簡單阿~~~


上一篇
[DAY13]使用套件
下一篇
[DAY15]golang常用套件(字串類與型態轉換)
系列文
欸你這週GO了嘛30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言