kansou 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -3
- data/lib/kansou/app_store_review.rb +79 -62
- data/lib/kansou/google_play_review.rb +71 -59
- data/lib/kansou/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 029b4f087081edc3fdd7304ad0ae2364b80a8afc
|
4
|
+
data.tar.gz: 24b9bca74d79e325711f1d116e35e08c7d513e72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75b636e4715d588e2be2346de7b5e0b11aa9319112716bfa973e1549656169b2c4b48a4859c0dffe4ba9751e5fabd821aafc5c78e70b1a55a70c8cf6f66ba724
|
7
|
+
data.tar.gz: 0de5610e263b2f823ac935e240b826a43d884eb9ab7f53f343bc6865cac1aa03c0b53becbba0c1bdcb4737a2af94f353d320e80a968b080477203f20ddb13b59
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kansou (0.
|
4
|
+
kansou (0.2.0)
|
5
5
|
json
|
6
6
|
oga
|
7
7
|
|
@@ -9,7 +9,7 @@ GEM
|
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
11
|
ansi (1.5.0)
|
12
|
-
ast (2.
|
12
|
+
ast (2.2.0)
|
13
13
|
diff-lcs (1.2.5)
|
14
14
|
json (1.8.3)
|
15
15
|
oga (1.3.1)
|
@@ -43,4 +43,4 @@ DEPENDENCIES
|
|
43
43
|
rspec
|
44
44
|
|
45
45
|
BUNDLED WITH
|
46
|
-
1.
|
46
|
+
1.11.2
|
@@ -7,102 +7,119 @@ module Kansou
|
|
7
7
|
return nil unless app_id
|
8
8
|
|
9
9
|
@app_id = app_id
|
10
|
+
|
11
|
+
@users = []
|
12
|
+
@versions = []
|
13
|
+
@dates = []
|
14
|
+
@titles = []
|
15
|
+
@stars = []
|
16
|
+
@bodies = []
|
10
17
|
end
|
11
|
-
|
18
|
+
|
19
|
+
def fetch(page_amount = 1)
|
12
20
|
reviews = []
|
13
21
|
max_page = page_amount - 1
|
14
22
|
(0..max_page).each do |page|
|
15
23
|
xml = download(page)
|
16
24
|
reviews.concat(parse(xml))
|
17
25
|
end
|
18
|
-
|
26
|
+
reviews
|
19
27
|
end
|
20
28
|
|
21
|
-
def download(page=0)
|
22
|
-
base_url =
|
23
|
-
user_agent =
|
24
|
-
+
|
29
|
+
def download(page = 0)
|
30
|
+
base_url = 'https://itunes.apple.com'
|
31
|
+
user_agent = 'iTunes/9.2 (Windows; Microsoft Windows 7 '\
|
32
|
+
+ 'Home Premium Edition (Build 7600)) AppleWebKit/533.16'
|
25
33
|
|
26
|
-
url = base_url +
|
27
|
-
+ @app_id.to_s +
|
34
|
+
url = base_url + '/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id='\
|
35
|
+
+ @app_id.to_s + '&pageNumber=' + page.to_s + '&sortOrdering=4&type=Purple+Software'
|
28
36
|
xml = open(url, 'User-Agent' => user_agent, 'X-Apple-Store-Front' => '143462-1').read
|
29
|
-
|
37
|
+
xml
|
30
38
|
end
|
31
39
|
|
32
40
|
def parse(xml)
|
33
|
-
items = []
|
34
|
-
users = []
|
35
|
-
versions = []
|
36
|
-
dates = []
|
37
|
-
i = 0
|
38
41
|
document = Oga.parse_xml(xml)
|
39
42
|
|
40
|
-
|
41
|
-
document
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
users
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if info[2]
|
59
|
-
dates.push(info[2])
|
60
|
-
else
|
61
|
-
dates.push("")
|
62
|
-
end
|
63
|
-
end
|
43
|
+
parse_author_info(document)
|
44
|
+
parse_title(document)
|
45
|
+
parse_star(document)
|
46
|
+
parse_body(document)
|
47
|
+
|
48
|
+
items = []
|
49
|
+
count = @stars.size - 1
|
50
|
+
(0..count).each do |key|
|
51
|
+
item = {
|
52
|
+
star: @stars[key],
|
53
|
+
user: @users[key],
|
54
|
+
date: @dates[key],
|
55
|
+
title: @titles[key],
|
56
|
+
body: @bodies[key],
|
57
|
+
version: @versions[key],
|
58
|
+
app_id: @app_id
|
59
|
+
}
|
60
|
+
items.push(item)
|
64
61
|
end
|
62
|
+
items
|
63
|
+
end
|
65
64
|
|
66
|
-
|
65
|
+
def parse_title(document)
|
67
66
|
document.css('TextView[styleSet="basic13"][textJust="left"][maxLines="1"]').each do |elm|
|
68
67
|
elm.css('b').each do |e|
|
69
|
-
titles.push e.text
|
68
|
+
@titles.push e.text
|
70
69
|
end
|
71
70
|
end
|
71
|
+
end
|
72
72
|
|
73
|
-
|
73
|
+
def parse_star(document)
|
74
74
|
document.css('HBoxView[topInset="1"]').each do |elm|
|
75
|
-
stars.push elm.attribute(
|
75
|
+
@stars.push elm.attribute('alt').value.gsub(/ stars*/, '')
|
76
76
|
end
|
77
|
+
end
|
77
78
|
|
78
|
-
|
79
|
+
def parse_body(document)
|
79
80
|
document.css('TextView[styleSet="normal11"]').each do |elm|
|
80
|
-
bodies.push(elm.text.gsub("\n",
|
81
|
+
@bodies.push(elm.text.gsub("\n", '<br />'))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_author_info(document)
|
86
|
+
expression = 'TextView[topInset="0"][styleSet="basic13"]' +
|
87
|
+
'[squishiness="1"][leftInset="0"][truncation="right"]' +
|
88
|
+
'[textJust="left"][maxLines="1"]'
|
89
|
+
document.css(expression).each do |elm|
|
90
|
+
next unless elm.text =~ /by/
|
91
|
+
|
92
|
+
tmp_array = elm.text.delete(' ').split("\n")
|
93
|
+
info = []
|
94
|
+
tmp_array.each do |v|
|
95
|
+
info.push v if v != '' && v != '-' && v != 'by'
|
96
|
+
end
|
97
|
+
@users.push info[0]
|
98
|
+
push_version(info)
|
99
|
+
push_date(info)
|
81
100
|
end
|
101
|
+
end
|
82
102
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
:date => dates[key],
|
89
|
-
:title => titles[key],
|
90
|
-
:body => bodies[key],
|
91
|
-
:version => versions[key],
|
92
|
-
:app_id => @app_id
|
93
|
-
}
|
94
|
-
items.push(item)
|
103
|
+
def push_version(info)
|
104
|
+
if info[1]
|
105
|
+
@versions.push(get_version(info[1]))
|
106
|
+
else
|
107
|
+
@versions.push('')
|
95
108
|
end
|
96
|
-
return items
|
97
109
|
end
|
98
110
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
111
|
+
def push_date(info)
|
112
|
+
if info[2]
|
113
|
+
@dates.push(info[2])
|
114
|
+
else
|
115
|
+
@dates.push('')
|
103
116
|
end
|
104
|
-
return version
|
105
117
|
end
|
106
118
|
|
119
|
+
def get_version(text)
|
120
|
+
version = nil
|
121
|
+
version = Regexp.last_match(1) if /Version([\d\.]+)/ =~ text
|
122
|
+
version
|
123
|
+
end
|
107
124
|
end
|
108
125
|
end
|
@@ -8,79 +8,91 @@ module Kansou
|
|
8
8
|
return nil unless app_id
|
9
9
|
|
10
10
|
@app_id = app_id
|
11
|
+
@titles = []
|
12
|
+
@bodies = []
|
13
|
+
@dates = []
|
14
|
+
@stars = []
|
15
|
+
@authors = []
|
11
16
|
end
|
12
17
|
|
13
|
-
def fetch
|
14
|
-
|
15
|
-
|
16
|
-
result = download(@app_id, page)
|
17
|
-
if result
|
18
|
-
reviews.concat(parse(result))
|
19
|
-
end
|
20
|
-
end
|
21
|
-
return reviews
|
18
|
+
def fetch
|
19
|
+
result = download(@app_id)
|
20
|
+
parse(result)
|
22
21
|
end
|
23
22
|
|
24
23
|
private
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
|
25
|
+
def download(app_id)
|
26
|
+
# https://play.google.com/store/apps/details?id=jp.mixi&hl=ja
|
27
|
+
http = Net::HTTP.new('play.google.com', 443)
|
28
|
+
http.use_ssl = true
|
29
|
+
path = '/store/apps/details'
|
30
|
+
data = "id=#{app_id}"
|
31
|
+
http.post(path, data).body
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse(input_text)
|
35
|
+
document = Oga.parse_html(input_text)
|
36
|
+
main_expression = 'div[class="single-review"]'
|
37
|
+
document.css(main_expression).each do |elm|
|
38
|
+
parse_review_element(elm)
|
32
39
|
end
|
33
40
|
|
34
|
-
|
35
|
-
|
36
|
-
json = JSON.load(input_text)
|
37
|
-
body = json[0][2]
|
41
|
+
compose_review
|
42
|
+
end
|
38
43
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
def compose_review
|
45
|
+
reviews = []
|
46
|
+
count = @stars.size - 1
|
47
|
+
(0..count).each do |key|
|
48
|
+
item = {
|
49
|
+
star: @stars[key],
|
50
|
+
user: @authors[key],
|
51
|
+
date: @dates[key],
|
52
|
+
title: @titles[key],
|
53
|
+
body: @bodies[key],
|
54
|
+
app_id: @app_id
|
55
|
+
}
|
56
|
+
reviews.push(item)
|
57
|
+
end
|
58
|
+
reviews
|
59
|
+
end
|
51
60
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
def parse_review_element(elm)
|
62
|
+
title_expression = 'span[class="review-title"]'
|
63
|
+
elm.css(title_expression).each do |title_node|
|
64
|
+
@titles.push(title_node.text)
|
65
|
+
end
|
66
|
+
|
67
|
+
body_expression = 'div[class="review-body"]'
|
68
|
+
elm.css(body_expression).each do |body_node|
|
69
|
+
@bodies.push(body_node.text)
|
70
|
+
end
|
59
71
|
|
60
|
-
|
61
|
-
|
62
|
-
(
|
63
|
-
item = {
|
64
|
-
:star => stars[key],
|
65
|
-
:user => authors[key],
|
66
|
-
:date => dates[key],
|
67
|
-
:title => titles[key],
|
68
|
-
:body => bodies[key],
|
69
|
-
:app_id => @app_id
|
70
|
-
}
|
71
|
-
reviews.push(item)
|
72
|
-
end
|
73
|
-
return reviews
|
72
|
+
date_expression = 'span[class="review-date"]'
|
73
|
+
elm.css(date_expression).each do |date_node|
|
74
|
+
@dates.push(date_node.text)
|
74
75
|
end
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
77
|
+
star_expression = 'div[class="current-rating"]'
|
78
|
+
elm.css(star_expression).each do |star_node|
|
79
|
+
@stars.push(process_star_count(star_node))
|
79
80
|
end
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
author_expression = 'span[class="author-name"]'
|
83
|
+
elm.css(author_expression).each do |author_node|
|
84
|
+
@authors.push(author_node.text.strip)
|
84
85
|
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def remove_unused_lines(text)
|
89
|
+
lines = text.split("\n")
|
90
|
+
lines[2] + ']'
|
91
|
+
end
|
92
|
+
|
93
|
+
def process_star_count(node)
|
94
|
+
widths = node.attribute('style').value.match('width: ([0-9]+)')
|
95
|
+
widths[1].to_i / 20
|
96
|
+
end
|
85
97
|
end
|
86
98
|
end
|
data/lib/kansou/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kansou
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- punchdrunker
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|