/
playstore.go
100 lines (77 loc) · 2.11 KB
/
playstore.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
package appcrawl
import (
"net/http"
"net/url"
"strconv"
"strings"
"github.com/PuerkitoBio/goquery"
)
type PlayStore struct {
}
func (a PlayStore) searchUrl(sr SearchRequest) (playUrl string, postData string) {
u, _ := url.Parse("https://play.google.com/store/search")
q := u.Query()
if sr.Query != "" {
q.Set("q", sr.Query)
}
q.Set("c", "apps")
u.RawQuery = q.Encode()
playUrl = u.String()
post := url.Values{}
post.Set("start", "0")
if sr.Limit > 0 {
post.Set("num", strconv.Itoa(sr.Limit))
}
post.Set("numChildren", "0")
post.Set("ipf", "1")
post.Set("xhr", "1")
postData = post.Encode()
return
}
func (a PlayStore) Search(sr SearchRequest) ([]App, error) {
playurl, post := a.searchUrl(sr)
body := strings.NewReader(post)
req, err := http.NewRequest("POST", playurl, body)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36")
client := sr.Client
resp, err := client.Do(req)
if err != nil {
return nil, err
}
doc, err := goquery.NewDocumentFromResponse(resp)
if err != nil {
return nil, err
}
cards := doc.Find(".card")
apps := make([]App, cards.Length())
cards.Each(func(i int, s *goquery.Selection) {
if val, ok := s.Attr("data-docid"); ok {
apps[i].Package = val
}
if val, ok := s.Find(".title").Attr("title"); ok {
apps[i].Name = val
}
if val, ok := s.Find(".subtitle").Attr("title"); ok {
apps[i].PublisherName = val
}
if val, ok := s.Find(".card-click-target").Attr("href"); ok {
apps[i].StoreUrl = "https://play.google.com" + val
}
if val, ok := s.Find(".cover-image").Attr("src"); ok {
apps[i].IconUrl = val
}
if val, ok := s.Find(".current-rating").Attr("style"); ok {
rating := strings.Split(val, " ")
if len(rating) >= 2 {
if rating_perc, err := strconv.ParseFloat(strings.TrimRight(rating[1], "%;"), 32); err == nil {
apps[i].Rating = float32(rating_perc * 5.0 / 100.0)
}
}
}
})
return apps, nil
}