-
Notifications
You must be signed in to change notification settings - Fork 2
/
client.go
151 lines (131 loc) · 6.02 KB
/
client.go
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package seomoz
import (
"math"
"os"
"sync"
)
var (
// DefaultCols is the sum of the numeric values for columns: Page Authority, Domain Authority, Links and Canonical URL
// See https://moz.com/help/guides/moz-api/mozscape/api-reference/url-metrics for more info
DefaultCols = 103079217156
defaultMaxBatchURLs = 10
)
// SpamScore represents the spam score for a subdomain
// the fields of which are described at https://moz.com/help/guides/moz-api/mozscape/getting-started-with-mozscape/spam-score
// This will eventually, according to moz at least, be replaces with the same 0-100 score the browser shows.
// Until then, SpamScore is an empty interface. Partially because the columns it describes aren't documented, and also
// to allow for type switches to provide some backwards compatability in code for when Moz change their API
type SpamScore interface{}
// URLMetrics is the basic structure returned by the API
type URLMetrics struct {
Title string `json:"ut"`
URL string `json:"uu"`
Subdomain string `json:"ufq"`
RootDomain string `json:"upl"`
ExternalEquityLinks float64 `json:"ueid"`
SubdomainExternalLinks float64 `json:"feid"`
RootDomainExternalLinks float64 `json:"peid"`
EquityLinksSubdomains float64 `json:"ujid"`
SubdomainsLinking float64 `json:"uifq"`
RootDomainsLinking float64 `json:"uipl"`
Links float64 `json:"uid"`
SubdomainSubdomainsLinking float64 `json:"fid"`
RootDomainRootDomainsLinking float64 `json:"pid"`
MozRankURLNormalized float64 `json:"umrp"`
MozRankURLRaw float64 `json:"umrr"`
MozRankSubdomainNormalized float64 `json:"fmrp"`
MozRankSubdomainRaw float64 `json:"fmrr"`
MozTrustNormalized float64 `json:"utrp"`
MozTrustRaw float64 `json:"utrr"`
MozTrustSubdomainNormalized float64 `json:"ftrp"`
MozTrustSubdomainRaw float64 `json:"ftrr"`
MozTrustDomainNormalized float64 `json:"ptrp"`
MozTrustDomainRaw float64 `json:"ptrr"`
MozRankExternalEquityNormalized float64 `json:"uemrp"`
MozRankExternalEquityRaw float64 `json:"uemrr"`
MozRankSubdomainExternalEquityNormalized float64 `json:"fejp"`
MozRankSubdomainExternalEquityRaw float64 `json:"fejr"`
MozRankRootDomainExternalEquityNormalized float64 `json:"pejp"`
MozRankRootDomainExternalEquityRaw float64 `json:"pejr"`
MozRankSubdomainCombinedNormalized float64 `json:"pjp"`
MozRankSubdomainCombinedRaw float64 `json:"pjr"`
MozRankRootDomainCombinedNormalized float64 `json:"fjp"`
MozRankRootDomainCombinedRaw float64 `json:"fjr"`
SubdomainSpamScore SpamScore `json:"fspsc"`
HTTPStatusCode float64 `json:"us"`
LinksToSubdomain float64 `json:"fuid"`
LinksToRootDomain float64 `json:"puid"`
RootDomainsLinkingToSubdomain float64 `json:"fipl"`
PageAuthority float64 `json:"upa"`
DomainAuthority float64 `json:"pda"`
ExternalLinks float64 `json:"ued"`
ExternalLinksToSubdomain float64 `json:"fed"`
ExternalLinksToRootDomain float64 `json:"ped"`
LinkingCBlocks float64 `json:"pid"`
LastCrawlTime int64 `json:"ulc"`
}
type mozAPI interface {
GetURLMetrics(link string, cols int) (*URLMetrics, error)
GetBatchURLMetrics(urls []string, cols int) (map[string]*URLMetrics, error)
}
// Client is the main object used to interact with the SeoMoz API
type Client struct {
moz mozAPI
MaxBatchURLs int
}
// NewEnvClient instantiates a new Client configured from the environment variables SEOMOZ_ACCESS_ID and SEOMOZ_SECRET_KEY
func NewEnvClient() *Client {
return NewClient(os.Getenv("SEOMOZ_ACCESS_ID"), os.Getenv("SEOMOZ_SECRET_KEY"))
}
// NewClient instantiates a new Client
func NewClient(accessID, secretKey string) *Client {
return &Client{moz: &MOZ{AccessID: accessID, SecretKey: secretKey}}
}
// GetURLMetrics fetches the metrics for the given urls
func (s *Client) GetURLMetrics(link string, cols int) (*URLMetrics, error) {
return s.moz.GetURLMetrics(link, cols)
}
// GetBatchURLMetrics executes a batch API call. At most 10 URLs are allowed in a batch call.
func (s *Client) GetBatchURLMetrics(urls []string, cols int) (map[string]*URLMetrics, error) {
return s.moz.GetBatchURLMetrics(urls, cols)
}
// GetBulkURLMetrics executes as many batch calls as required in order to analyze all the URLs.
func (s *Client) GetBulkURLMetrics(urls []string, cols int) (map[string]*URLMetrics, error) {
maxBatchURLs := s.MaxBatchURLs
if maxBatchURLs == 0 {
maxBatchURLs = defaultMaxBatchURLs
}
batchesNo := int(math.Ceil(float64(len(urls)) / float64(maxBatchURLs)))
responses := make(chan batchResponse, batchesNo)
var wg sync.WaitGroup
for i := 0; i < len(urls); i += maxBatchURLs {
var batchURLs []string
if i+maxBatchURLs >= len(urls) {
batchURLs = urls[i:]
} else {
batchURLs = urls[i : i+maxBatchURLs]
}
wg.Add(1)
go func() {
defer wg.Done()
batch, err := s.moz.GetBatchURLMetrics(batchURLs, cols)
responses <- batchResponse{batch, err}
}()
}
wg.Wait()
close(responses)
results := map[string]*URLMetrics{}
for resp := range responses {
if resp.err != nil {
return nil, resp.err
}
for link, metrics := range resp.batch {
results[link] = metrics
}
}
return results, nil
}
type batchResponse struct {
batch map[string]*URLMetrics
err error
}