问题

最近需要使用 Google Api Go Client 获取 Google Adsense的数据,由于常规 generate 接口返回的数据是有10w行的限制,不满足目前的使用需要,于是使用了 csv的生成方法 generateCsv,和 generate 相比 generateCsv 能返回更多的数据并且不需要改动太多参数。

img.png

在调用 generateCsv 接口时,发现接口不能返回正确数据,提示错误,错误信息如下:

1
panic: invalid character 'D' looking for beginning of value

根据错误信息可以得知错误应该是解析错误,通过方法接口和源代码看出,接口返回的是csv类型的数据,但 api 只针对 json 进行解析,没有判断数据类型,导致解析失败。

img_1.png

解决

找到问题后,我立即就想到一个方法,就是在decode代码里添加csv格式的判断,尝试了一下,由于对csv解析方法不熟悉,并且修改 Client 代码会导致模块更新不方便(客户端代码都是生成的,于是决定另寻它法。 通过寻找各种资料issue后,找到了一个可能可行的方法,就是创建手动创建http连接发送请求。 img_2.png

根据相应的文档,很快就写好了相应的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package main

import (
	"context"
	"fmt"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/adsense/v2"
	"google.golang.org/api/option"
	"google.golang.org/api/transport/http"
	"io"
	"net/url"
)

func main() {
	ctx := context.Background()
	var config = &oauth2.Config{
		ClientID:     "xxx.apps.googleusercontent.com", // from https://console.developers.google.com/project/<your-project-id>/apiui/credential
		ClientSecret: "GOCSPX-xxxxxx",                                      // from https://console.developers.google.com/project/<your-project-id>/apiui/credential
		Endpoint:     google.Endpoint,
		Scopes:       []string{adsense.AdsenseReadonlyScope},
		RedirectURL:  "https://developers.google.com",
	}
	//token := newOAuthClient(ctx, config)
	client, _, err := http.NewClient(ctx, option.WithTokenSource(config.TokenSource(ctx, &oauth2.Token{RefreshToken: "code"})))
	if err != nil {
		return
	}
	URL, err := url.Parse(fmt.Sprintf("https://adsense.googleapis.com/v2/accounts/pub-123123/reports:generateCsv"))
	if err != nil {
		return
	}
	query := URL.Query()
	query.Set("dateRange", "YESTERDAY")
	query.Set("dimensions", "URL_CHANNEL_NAME")
	query.Set("metrics", "PAGE_VIEWS")

	URL.RawQuery = query.Encode()
	resp, err := client.Get(URL.String())
	if err != nil {
		return
	}
	defer resp.Body.Close()
	all, err := io.ReadAll(resp.Body)
	if err != nil {
		return
	}
	fmt.Println(string(all))
}

主要逻辑就是创建到google cloud service 的连接,调用 generateCsv 接口即可。

小结

本文讲述了使用 google api go client 调用AdSense接口遇到的问题及解决方法。

参考