store_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 815c553130c66a2e04469be1aafbdc901421be26
4
+ data.tar.gz: a3f5193ae4d8f2898718f11fb08807d397b9f357
5
+ SHA512:
6
+ metadata.gz: 422dc029152f3ab93ead0f7a48e442d0177dfbcbd937a5134214180fcae1afdf6a0949be7aacb6a3760e0fb3e31dc2943f4e2685a0f31d71edc1a6762f7c9c53
7
+ data.tar.gz: 2a7e598dea854bcb08632411f24126a5b10d8c31963d4b1cfd161ef84e0d626935151e9cc317f0b055007c59ab8fc63ccdff0413ed1a21129cfa525f8c2dc3e5
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ *.swp
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.3
6
+ - 2.1.4
7
+ - 2.1.5
8
+ bundler_args: --jobs=2
9
+ script: bundle exec rspec
10
+ branches:
11
+ only:
12
+ - master
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in store_api.gemspec
4
+ gemspec
5
+ group :test do
6
+ gem 'coveralls', :require => false
7
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 tatsunori_nishikori
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # StoreApi
2
+ [![Coverage Status](https://coveralls.io/repos/tatsu07/store_api/badge.svg)](https://coveralls.io/r/tatsu07/store_api) [![Build Status](https://travis-ci.org/tatsu07/store_api.svg?branch=master)](https://travis-ci.org/tatsu07/store_api)
3
+
4
+ This is the API to get the data from GooglePlay and AppStore and KindleStore and WindowsStore
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'store_api'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install store_api
21
+
22
+ ## Usage
23
+
24
+ ```ruby
25
+ require 'store_api'
26
+ ```
27
+
28
+ #### GooglePlay
29
+ - app details
30
+
31
+ ```ruby
32
+ apps = StoreApi::GooglePlay::Apps::Details.new('com.king.candycrushsodasaga')
33
+ # Can be specified language
34
+ apps = StoreApi::GooglePlay::Apps::Details.new('com.king.candycrushsodasaga','en')
35
+
36
+ puts apps.title
37
+ >>> Candy Crush Soda Saga
38
+ ```
39
+ - ranking chart
40
+
41
+ ```ruby
42
+ # Top Grossing Android Apps
43
+ ranking = StoreApi::GooglePlay::Apps::Ranking.new('topgrossing')
44
+ # Top Grossing Games
45
+ ranking = StoreApi::GooglePlay::Apps::Ranking.new('topgrossing','GAME')
46
+ # Trending Apps
47
+ trending_apps = StoreApi::GooglePlay::Apps::Ranking.new('movers_shakers')
48
+ ```
49
+
50
+ - search apps
51
+
52
+ ```ruby
53
+ search_apps = StoreApi::GooglePlay::Apps::Search.new('candy crush')
54
+ ```
55
+
56
+ - developer apps
57
+
58
+ ```ruby
59
+ developer_apps = StoreApi::GooglePlay::Apps::Developer.new('King')
60
+ ```
61
+
62
+ ## Contributing
63
+
64
+ 1. Fork it ( https://github.com/tatsu07/store_api/fork )
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/lib/store_api.rb ADDED
@@ -0,0 +1,11 @@
1
+ # encoding : utf-8
2
+ require "net/https"
3
+ require "uri"
4
+ require "nokogiri"
5
+ require "store_api/version"
6
+ require "store_api/request"
7
+ require "store_api/google_play"
8
+
9
+ module StoreApi
10
+ # Your code goes here...
11
+ end
@@ -0,0 +1,12 @@
1
+ # encoding : utf-8
2
+ require "store_api/google_play/card"
3
+ require "store_api/google_play/apps/details"
4
+ require "store_api/google_play/apps/ranking"
5
+ require "store_api/google_play/apps/search"
6
+ require "store_api/google_play/apps/developer"
7
+ module StoreApi
8
+ module GooglePlay
9
+ HOST = 'play.google.com'
10
+ HTTPS = true
11
+ end
12
+ end
@@ -0,0 +1,88 @@
1
+ # encoding : utf-8
2
+
3
+ module StoreApi
4
+ module GooglePlay
5
+ module Apps
6
+ ##
7
+ # google play detail class
8
+ class Details
9
+ include StoreApi::Request
10
+ @@path = '/store/apps/details'
11
+ attr_accessor :id,:title,:cover_image,:developer,:developer_url,:category,:category_id,
12
+ :category_url,:badge_title,:price,:google_plus,:video_url,:screenshot,:description,
13
+ :rating_value,:rating_count,:rating_score,:rating_map,:whatsnew,:date_published,
14
+ :file_size,:downloads,:software_version,:operating_system,:content_rating,
15
+ :developer_links,:developer_address
16
+ ##
17
+ # initialize
18
+ # @param [String] id
19
+ # @param [String] lang
20
+ # @param [Hash] proxy
21
+ # @param [Hash] header
22
+ def initialize(id,lang=nil,proxy=nil,header=nil)
23
+ params = {'id' => id }
24
+ if !lang.nil?
25
+ params['hl'] = lang
26
+ end
27
+ begin
28
+ html = get(StoreApi::GooglePlay::HOST,@@path,params,StoreApi::GooglePlay::HTTPS,proxy,header)
29
+ doc = Nokogiri::HTML(html,nil,'utf-8')
30
+ @id = id
31
+
32
+ content_xpath = "id('body-content')"
33
+ doc.xpath("#{content_xpath}/div[@class='main-content']//div[@class='details-info']").each do |node|
34
+ # puts node.methods
35
+ @title = node.css('.document-title').text.strip
36
+ @cover_image = node.css('.cover-image').attribute('src').value
37
+ @developer = node.css('.primary').text.strip
38
+ @developer_url = node.css('.primary').attribute('href').value
39
+ @category = node.css('.category').text.strip
40
+ @category_url = node.css('.category').attribute('href').value
41
+ @category_id = node.css('.category').attribute('href').value.split("/")[4]
42
+ @badge_title = node.css('.badge-title').text.strip
43
+ @price = node.xpath("//*[@class='price buy id-track-click']//*[@itemprop='price']/@content").text
44
+ end
45
+
46
+ thumbnails_xpath = "#{content_xpath}//div[@class='thumbnails']"
47
+ @screenshot = doc.xpath("#{thumbnails_xpath}/img").map {|node| node.attribute('src').value }
48
+ @video_url = doc.xpath("#{thumbnails_xpath}/span[@class='details-trailer']/span[@class='preview-overlay-container']/@data-video-url").text
49
+ @description = doc.xpath("#{content_xpath}//div[@itemprop='description']").to_html
50
+ @rating_score = doc.xpath("#{content_xpath}//div[@class='rating-box']//div[@class='score']").text
51
+ rating_xpath = "#{content_xpath}////div[@class='rating-box']"
52
+ @rating_value = doc.xpath("#{rating_xpath}//*[@itemprop='ratingValue']/@content").text
53
+ @rating_count = doc.xpath("#{rating_xpath}//*[@itemprop='ratingCount']/@content").text
54
+
55
+ @rating_map = {}
56
+ doc.xpath("#{rating_xpath}//div[@class='rating-histogram']/div").each do |node|
57
+ star_num = node.css(".bar-label").text.strip
58
+ @rating_map[star_num.to_i] = node.css(".bar-number").text.gsub(',','')
59
+ end
60
+
61
+ @whatsnew = doc.xpath("#{content_xpath}//div[@class='details-section whatsnew']//div[@class='recent-change']").text
62
+ metadata_xpath = "#{content_xpath}//div[@class='details-section metadata']//div[@class='meta-info']"
63
+ @date_published = doc.xpath("#{metadata_xpath}//div[@itemprop='datePublished']").text
64
+ @file_size = doc.xpath("#{metadata_xpath}//div[@itemprop='fileSize']").text
65
+ @file_size = !@file_size.nil? ? @file_size.strip : nil
66
+ @downloads = doc.xpath("#{metadata_xpath}//div[@itemprop='numDownloads']").text
67
+ @downloads = !@downloads.nil? ? @downloads.strip : nil
68
+ @software_version = doc.xpath("#{metadata_xpath}//div[@itemprop='softwareVersion']").text
69
+ @software_version = !@software_version.nil? ? @software_version.strip : nil
70
+ @operating_system = doc.xpath("#{metadata_xpath}//div[@itemprop='operatingSystems']").text
71
+ @operating_system = !@operating_system.nil? ? @operating_system.strip : nil
72
+ @content_rating = doc.xpath("#{metadata_xpath}//div[@itemprop='contentRating']").text
73
+ @content_rating = !@content_rating.nil? ? @content_rating.strip : nil
74
+ @developer_address = doc.xpath("#{metadata_xpath}//div[@class='content physical-address']").text
75
+ @developer_address = !@developer_address.nil? ? @developer_address.strip : nil
76
+ @developer_links = []
77
+ doc.xpath("#{metadata_xpath}//div[@class='content contains-text-link']/a[@class='dev-link']").each do |node|
78
+ @developer_links.push({'text' => node.text,'link' => node.attribute('href').value})
79
+ end
80
+ rescue => e
81
+ puts e
82
+ end
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,39 @@
1
+ # encoding : utf-8
2
+
3
+ module StoreApi
4
+ module GooglePlay
5
+ module Apps
6
+ ##
7
+ # google play developer class
8
+ class Developer
9
+ include StoreApi::Request
10
+ include StoreApi::GooglePlay::Card
11
+ attr_accessor :apps_list
12
+
13
+ def initialize(developer_name,lang=nil,proxy=nil,header=nil)
14
+ params = {'id' => developer_name }
15
+ if !lang.nil?
16
+ params['hl'] = lang
17
+ end
18
+ @@path = URI.escape("/store/apps/developer")
19
+ @apps_list = []
20
+ num = 60
21
+ (0..1).each do |start|
22
+ begin
23
+ params['start'] = start*60
24
+ params['num'] = num
25
+ html = post(StoreApi::GooglePlay::HOST,@@path,params,StoreApi::GooglePlay::HTTPS,proxy,header)
26
+ doc = Nokogiri::HTML(html,nil,'utf-8')
27
+ @apps_list.concat(parse(doc))
28
+ rescue => e
29
+ puts e.backtrace
30
+ puts e.message
31
+ break
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,75 @@
1
+ # encoding : utf-8
2
+
3
+ module StoreApi
4
+ module GooglePlay
5
+ module Apps
6
+ ##
7
+ # == google play ranking class
8
+ # @note specification
9
+ # - top path : '/store/apps/collection/ranking_type'
10
+ # - category path : '/store/apps/category/category_id/collection/ranking_type'
11
+ # - post data start: min 0 max 480 num:60
12
+ class Ranking
13
+ include StoreApi::Request
14
+ attr_accessor :topchart
15
+ ##
16
+ # initialize
17
+ # @param [String] ranking_type
18
+ # @param [String] category_id
19
+ # @param [String] lang
20
+ # @param [Hash] proxy
21
+ # @param [Hash] header
22
+ # @see StoreApi::GooglePlay::RANKING_TYPE_LIST
23
+ # @see StoreApi::GooglePlay::CATEGORY_ID_LIST
24
+ def initialize(ranking_type=nil,category_id=nil,lang=nil,proxy=nil,header=nil)
25
+ params = {}
26
+ if !lang.nil?
27
+ params['hl'] = lang
28
+ end
29
+ if category_id.nil?
30
+ @@path = "/store/apps/collection/#{ranking_type}"
31
+ else
32
+ @@path = "/store/apps/category/#{category_id}/collection/#{ranking_type}"
33
+ end
34
+ @topchart = []
35
+ num = 60
36
+ (0..8).each do |start|
37
+ begin
38
+ params['start'] = start*60
39
+ params['num'] = num
40
+ html = post(StoreApi::GooglePlay::HOST,@@path,params,StoreApi::GooglePlay::HTTPS,proxy,header)
41
+ doc = Nokogiri::HTML(html,nil,'utf-8')
42
+ parse(doc)
43
+ rescue => e
44
+ puts e.backtrace
45
+ puts e.message
46
+ break
47
+ end
48
+ end
49
+ end
50
+
51
+ def parse(doc)
52
+ doc.css('.card-list > .card').each do |node|
53
+ rank = node.css('.title').text.split('.')[0].strip
54
+ if (/^[+-]?[0-9]+$/ =~ rank)
55
+ rank = rank.to_i
56
+ else
57
+ rank = nil
58
+ end
59
+ @topchart.push(
60
+ {:id => node.css('.preview-overlay-container')[0]['data-docid'],
61
+ :title => node.css('.title')[0]['title'].strip,
62
+ :cover_image => node.css('.cover-image').attribute('src').value,
63
+ :details_url => node.css('.title').attribute('href').value,
64
+ :developer => node.css('.subtitle').attribute('title').value.strip,
65
+ :price => node.css('.display-price')[0].text,
66
+ :rank => rank}
67
+ )
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,43 @@
1
+ # encoding : utf-8
2
+
3
+ module StoreApi
4
+ module GooglePlay
5
+ module Apps
6
+ ##
7
+ # google play search class
8
+ class Search
9
+ include StoreApi::Request
10
+ include StoreApi::GooglePlay::Card
11
+ attr_accessor :search_list
12
+
13
+ def initialize(search_word,lang=nil,limit=nil,proxy=nil,header=nil)
14
+ params = {'q' => search_word,'c' => 'apps' }
15
+ if !lang.nil?
16
+ params['hl'] = lang
17
+ end
18
+ @@path = URI.escape("/store/search")
19
+ @search_list = []
20
+ num = 60
21
+ # TODO search limit
22
+ (0..2).each do |start|
23
+ begin
24
+ params['start'] = start*60
25
+ params['num'] = num
26
+ html = post(StoreApi::GooglePlay::HOST,@@path,params,StoreApi::GooglePlay::HTTPS,proxy,header)
27
+ doc = Nokogiri::HTML(html,nil,'utf-8')
28
+ @search_list.concat(parse(doc))
29
+ rescue => e
30
+ puts e.backtrace
31
+ puts e.message
32
+ break
33
+ end
34
+ end
35
+ end
36
+
37
+ def main
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ # encoding : utf-8
2
+
3
+ module StoreApi
4
+ module GooglePlay
5
+ module Card
6
+
7
+ ##
8
+ # card parts parse
9
+ # @param [Nokogiri::XML::Docment] doc
10
+ # @return [Array] card_list
11
+ def parse(doc)
12
+ card_list = []
13
+ doc.css('.card-list > .card').each do |node|
14
+ rank = node.css('.title').text.split('.')[0].strip
15
+ if (/^[+-]?[0-9]+$/ =~ rank)
16
+ rank = rank.to_i
17
+ else
18
+ rank = nil
19
+ end
20
+ card_list.push(
21
+ {:id => node.css('.preview-overlay-container')[0]['data-docid'],
22
+ :title => node.css('.title')[0]['title'].strip,
23
+ :cover_image => node.css('.cover-image').attribute('src').value,
24
+ :details_url => node.css('.title').attribute('href').value,
25
+ :developer => node.css('.subtitle').attribute('title').value.strip,
26
+ :price => node.css('.display-price')[0].text,
27
+ :rank => rank}
28
+ )
29
+ end
30
+ card_list
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,52 @@
1
+ # encoding : utf-8
2
+ module StoreApi
3
+ module GooglePlay
4
+ CATEGORY_ID_LIST = [
5
+ 'GAME',
6
+ 'GAME_ACTION',
7
+ 'GAME_ADVENTURE',
8
+ 'GAME_ARCADE',
9
+ 'GAME_CASINO',
10
+ 'GAME_CASUAL',
11
+ 'GAME_CARD',
12
+ 'GAME_SIMULATION',
13
+ 'GAME_STRATEGY',
14
+ 'GAME_SPORTS',
15
+ 'GAME_PUZZLE',
16
+ 'GAME_FAMILY',
17
+ 'GAME_BOARD',
18
+ 'GAME_RACING',
19
+ 'GAME_ROLE_PLAYING',
20
+ 'GAME_EDUCATIONAL',
21
+ 'GAME_WORD',
22
+ 'GAME_TRIVIA',
23
+ 'GAME_MUSIC',
24
+ 'APP_WIDGETS',
25
+ 'ENTERTAINMENT',
26
+ 'PERSONALIZATION',
27
+ 'COMICS',
28
+ 'SHOPPING',
29
+ 'SPORTS',
30
+ 'SOCIAL',
31
+ 'TOOLS',
32
+ 'NEWS_AND_MAGAZINES',
33
+ 'BUSINESS',
34
+ 'FINANCE',
35
+ 'MEDIA_AND_VIDEO',
36
+ 'LIFESTYLE',
37
+ 'LIBRARIES_AND_DEMO',
38
+ 'APP_WALLPAPER',
39
+ 'TRANSPORTATION',
40
+ 'PRODUCTIVITY',
41
+ 'HEALTH_AND_FITNESS',
42
+ 'PHOTOGRAPHY',
43
+ 'MEDICAL',
44
+ 'WEATHER',
45
+ 'EDUCATION',
46
+ 'TRAVEL_AND_LOCAL',
47
+ 'BOOKS_AND_REFERENCE',
48
+ 'COMMUNICATION',
49
+ 'MUSIC_AND_AUDIO'
50
+ ]
51
+ end
52
+ end
@@ -0,0 +1,16 @@
1
+ # encoding : utf-8
2
+ module StoreApi
3
+ module GooglePlay
4
+ RANKING_TYPE_LIST = [
5
+ 'topgrossing',
6
+ 'topselling_free',
7
+ 'topselling_paid',
8
+ 'topselling_new_free',
9
+ 'topselling_new_paid',
10
+ 'movers_shakers',
11
+ 'editors_choice',
12
+ 'tablet_featured',
13
+ 'featured'
14
+ ]
15
+ end
16
+ end
@@ -0,0 +1,112 @@
1
+ # encoding : utf-8
2
+ module StoreApi
3
+
4
+ module Request
5
+
6
+ TIME_OUT = 20
7
+ @@redirect_count = 0
8
+
9
+ ##
10
+ # http get
11
+ # @param [String] host
12
+ # @param [String] path
13
+ # @param [Hash] proxy [:host=>'host',:port=>port]
14
+ # @param [Hash] header http header
15
+ # @param [Hash] params
16
+ # @return [String] response.body
17
+ def get(host,path,params=nil,https=false,proxy=nil,header=nil)
18
+ request(host,path,'get',params,https,proxy,header).body
19
+ end
20
+
21
+ ##
22
+ # http post
23
+ # @param [String] host
24
+ # @param [String] path
25
+ # @param [Hash] params
26
+ # @param [Hash] proxy [:host=>'host',:port=>port]
27
+ # @param [Hash] header http header
28
+ # @return [String] response.body
29
+ def post(host,path,params=nil,https=false,proxy=nil,header=nil)
30
+ request(host,path,'post',params,https,proxy,header).body
31
+ end
32
+
33
+ ##
34
+ # http request
35
+ # @param [String] host
36
+ # @param [String] path
37
+ # @param [String] method get/post
38
+ # @param [Boolean] https
39
+ # @param [Hash] proxy [:host=>'host',:port=>port]
40
+ # @param [Hash] header http header
41
+ # @param [Hash] params
42
+ # @return [Object] response
43
+ def request(host,path,method='get',params=nil,https=false,proxy=nil,header=nil)
44
+ if !params.nil?
45
+ query = params.map{|k,v| "#{k}=#{v}"}.join('&')
46
+ query_escaped = URI.escape(query)
47
+ end
48
+ if !proxy.nil? && !proxy.empty?
49
+ if https
50
+ http = Net::HTTP::Proxy(proxy[:host],proxy[:port]).new(host,443)
51
+ else
52
+ http = Net::HTTP::Proxy(proxy[:host],proxy[:port]).new(host)
53
+ end
54
+ else
55
+ if https
56
+ http = Net::HTTP.new(host,443)
57
+ http.use_ssl = true
58
+ else
59
+ http = Net::HTTP.new(host)
60
+ end
61
+ end
62
+ http.read_timeout = TIME_OUT
63
+ if !header.nil? && !header.empty?
64
+ if method == 'get'
65
+ if !query_escaped.nil?
66
+ path = path + '?' + query_escaped
67
+ end
68
+ response = http.get(path,header)
69
+ elsif method == 'post'
70
+ if !query_escaped.nil?
71
+ response = http.post(path,query_escaped,header)
72
+ else
73
+ response = http.post(path,nil,header)
74
+ end
75
+ end
76
+ else
77
+ if method == 'get'
78
+ if !query_escaped.nil?
79
+ path = path + '?' + query_escaped
80
+ end
81
+ response = http.get(path)
82
+ elsif method == 'post'
83
+ if !query_escaped.nil?
84
+ response = http.post(path,query_escaped)
85
+ else
86
+ response = http.post(path)
87
+ end
88
+ end
89
+ end
90
+ if response.code.to_i > 500
91
+ @@redirect_count = 0
92
+ raise "Server Error ! responce code = #{response.code} response = #{response.body}"
93
+ elsif response.code.to_i >= 400 && response.code.to_i < 500
94
+ @@redirect_count = 0
95
+ raise "Not Found ! responce codee = #{response.code} response = #{response.body}"
96
+ elsif response.code.to_i >= 300 && response.code.to_i < 400
97
+ redirect_url = URI.parse(response.header['location'])
98
+ if redirect_url.scheme == "https"
99
+ https = true
100
+ end
101
+ @@redirect_count = @@redirect_count + 1
102
+ if @@redirect_count > 5
103
+ raise "Exception Redirect Loop"
104
+ end
105
+ response = request(redirect_url.host,redirect_url.path,method,params,https,proxy,header)
106
+ else
107
+ @redirect_count = 0
108
+ response
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,3 @@
1
+ module StoreApi
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ # encoding : utf-8
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'coveralls'
4
+ require 'store_api'
5
+
6
+ Coveralls.wear!
@@ -0,0 +1,35 @@
1
+ # encoding : utf-8
2
+ require 'spec_helper'
3
+
4
+ describe StoreApi::GooglePlay::Apps::Details do
5
+
6
+ it 'details test' do
7
+ apps = StoreApi::GooglePlay::Apps::Details.new('com.king.candycrushsodasaga','en')
8
+ # apps = StoreApi::GooglePlay::Apps::Details.new('com.toiletgaman','en')
9
+ expect(apps.title).not_to be nil
10
+ expect(apps.cover_image).not_to be nil
11
+ expect(apps.price).not_to be nil
12
+ expect(apps.developer).not_to be nil
13
+ expect(apps.developer_url).not_to be nil
14
+ expect(apps.category).not_to be nil
15
+ expect(apps.category_url).not_to be nil
16
+ expect(apps.category_id).not_to be nil
17
+ expect(apps.badge_title).not_to be nil
18
+ expect(apps.screenshot.size).to be > 0
19
+ expect(apps.video_url).not_to be nil
20
+ expect(apps.description).not_to be nil
21
+ expect(apps.rating_score).not_to be nil
22
+ expect(apps.rating_value).not_to be nil
23
+ expect(apps.rating_count).not_to be nil
24
+ expect(apps.rating_map.size).to be > 0
25
+ expect(apps.whatsnew).not_to be nil
26
+ expect(apps.date_published).not_to be nil
27
+ expect(apps.file_size).not_to be nil
28
+ expect(apps.downloads).not_to be nil
29
+ expect(apps.software_version).not_to be nil
30
+ expect(apps.operating_system).not_to be nil
31
+ expect(apps.content_rating).not_to be nil
32
+ expect(apps.developer_address).not_to be nil
33
+ expect(apps.developer_links.size).to be > 0
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ # encoding : utf-8
2
+ require 'spec_helper'
3
+
4
+ describe StoreApi::GooglePlay::Apps::Developer do
5
+
6
+ it 'developer app list test' do
7
+ developer_name = 'LINE Corporation'
8
+ developer = StoreApi::GooglePlay::Apps::Developer.new(developer_name)
9
+ expect(developer.apps_list).not_to be nil
10
+ expect(developer.apps_list.size).to be > 5
11
+ expect(developer.apps_list[0][:developer]).to eq developer_name
12
+ developer = StoreApi::GooglePlay::Apps::Developer.new(developer_name,'en')
13
+ expect(developer.apps_list).not_to be nil
14
+ end
15
+
16
+ end
17
+
@@ -0,0 +1,23 @@
1
+ # encoding : utf-8
2
+ require 'spec_helper'
3
+
4
+ describe StoreApi::GooglePlay::Apps::Ranking do
5
+
6
+ it 'ranking test' do
7
+ ranking = StoreApi::GooglePlay::Apps::Ranking.new('topgrossing','GAME')
8
+ expect(ranking.topchart).not_to be nil
9
+ expect(ranking.topchart.size).to be >= 540
10
+ # ranking = StoreApi::GooglePlay::Apps::Ranking.new('topselling_free')
11
+ # expect(ranking.topchart).not_to be nil
12
+ # expect(ranking.topchart.size).to be >= 540
13
+ ranking = StoreApi::GooglePlay::Apps::Ranking.new('editors_choice')
14
+ expect(ranking.topchart).not_to be nil
15
+ ranking = StoreApi::GooglePlay::Apps::Ranking.new('movers_shakers')
16
+ expect(ranking.topchart).not_to be nil
17
+ ranking = StoreApi::GooglePlay::Apps::Ranking.new('tablet_featured')
18
+ expect(ranking.topchart).not_to be nil
19
+ ranking = StoreApi::GooglePlay::Apps::Ranking.new('featured')
20
+ expect(ranking.topchart).not_to be nil
21
+ end
22
+
23
+ end
@@ -0,0 +1,13 @@
1
+ # encoding : utf-8
2
+ require 'spec_helper'
3
+
4
+ describe StoreApi::GooglePlay::Apps::Search do
5
+
6
+ it 'app search test' do
7
+ search_word = 'モンスト'
8
+ search = StoreApi::GooglePlay::Apps::Search.new(search_word)
9
+ expect(search.search_list).not_to be nil
10
+ expect(search.search_list.size).to be > 10
11
+ end
12
+
13
+ end
@@ -0,0 +1,20 @@
1
+ # encoding : utf-8
2
+ require 'spec_helper'
3
+
4
+ describe StoreApi do
5
+ it 'has a version number' do
6
+ expect(StoreApi::VERSION).not_to be nil
7
+ end
8
+
9
+ it 'http request test' do
10
+ extend StoreApi::Request
11
+ host = 'play.google.com'
12
+ path = '/store'
13
+ html = get(host,path)
14
+ expect(html).not_to be nil
15
+ path = '/store/apps/collection/topselling_free'
16
+ params = {'start' => 60,'num' => 60}
17
+ html = post(host,path,params,true)
18
+ expect(html).not_to be nil
19
+ end
20
+ end
data/store_api.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'store_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "store_api"
8
+ spec.version = StoreApi::VERSION
9
+ spec.authors = ["tatsunori_nishikori"]
10
+ spec.email = ["tora.1986.tatsu@gmail.com"]
11
+ spec.summary = %q{Smartphone app store data acquisition API.}
12
+ spec.description = %q{This is the API to get the data from GooglePlay and AppStore and KindleStore and WindowsStore.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "yard"
25
+ spec.add_development_dependency 'simplecov', '~> 0.9.2'
26
+ spec.add_development_dependency "nokogiri", "~> 1.6.6.2"
27
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: store_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - tatsunori_nishikori
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.9.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.9.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: nokogiri
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.6.6.2
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.6.6.2
97
+ description: This is the API to get the data from GooglePlay and AppStore and KindleStore
98
+ and WindowsStore.
99
+ email:
100
+ - tora.1986.tatsu@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".coveralls.yml"
106
+ - ".gitignore"
107
+ - ".travis.yml"
108
+ - Gemfile
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - lib/store_api.rb
113
+ - lib/store_api/google_play.rb
114
+ - lib/store_api/google_play/apps/details.rb
115
+ - lib/store_api/google_play/apps/developer.rb
116
+ - lib/store_api/google_play/apps/ranking.rb
117
+ - lib/store_api/google_play/apps/search.rb
118
+ - lib/store_api/google_play/card.rb
119
+ - lib/store_api/google_play/category_id.rb
120
+ - lib/store_api/google_play/ranking_type.rb
121
+ - lib/store_api/request.rb
122
+ - lib/store_api/version.rb
123
+ - spec/spec_helper.rb
124
+ - spec/store_api/google_play/apps/details_spec.rb
125
+ - spec/store_api/google_play/apps/developer_spec.rb
126
+ - spec/store_api/google_play/apps/ranking_spec.rb
127
+ - spec/store_api/google_play/apps/search_spec.rb
128
+ - spec/store_api_spec.rb
129
+ - store_api.gemspec
130
+ homepage: ''
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 2.2.2
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: Smartphone app store data acquisition API.
154
+ test_files:
155
+ - spec/spec_helper.rb
156
+ - spec/store_api/google_play/apps/details_spec.rb
157
+ - spec/store_api/google_play/apps/developer_spec.rb
158
+ - spec/store_api/google_play/apps/ranking_spec.rb
159
+ - spec/store_api/google_play/apps/search_spec.rb
160
+ - spec/store_api_spec.rb
161
+ has_rdoc: