market_bot 0.17.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Guardfile +70 -0
  4. data/README.markdown +45 -95
  5. data/Rakefile +0 -89
  6. data/bin/app_categories +17 -0
  7. data/bin/benchmark_parser_app +24 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +7 -0
  10. data/bin/update_test_data +30 -0
  11. data/lib/market_bot.rb +20 -15
  12. data/lib/market_bot/exceptions.rb +2 -1
  13. data/lib/market_bot/play/app.rb +188 -0
  14. data/lib/market_bot/play/app/constants.rb +33 -0
  15. data/lib/market_bot/play/chart.rb +118 -0
  16. data/lib/market_bot/play/chart/constants.rb +74 -0
  17. data/lib/market_bot/play/constants.rb +7 -0
  18. data/lib/market_bot/play/developer.rb +32 -0
  19. data/lib/market_bot/util.rb +17 -0
  20. data/lib/market_bot/version.rb +1 -1
  21. data/market_bot.gemspec +6 -3
  22. data/spec/market_bot/play/app_spec.rb +201 -0
  23. data/spec/market_bot/play/chart_spec.rb +126 -0
  24. data/spec/market_bot/play/data/app-com.bluefroggaming.popdat.txt +99 -0
  25. data/spec/market_bot/play/data/app-com.mg.android.txt +103 -0
  26. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-0.txt +97 -0
  27. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-1.txt +97 -0
  28. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-2.txt +97 -0
  29. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-3.txt +97 -0
  30. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-4.txt +97 -0
  31. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-5.txt +97 -0
  32. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-6.txt +97 -0
  33. data/spec/market_bot/play/data/chart-topselling_paid-GAME_ARCADE-7.txt +97 -0
  34. data/spec/market_bot/play/data/developer-zynga.txt +97 -0
  35. data/spec/market_bot/play/developer_spec.rb +52 -0
  36. data/spec/market_bot_spec.rb +14 -0
  37. data/spec/spec_helper.rb +5 -11
  38. metadata +57 -52
  39. data/NOTES.txt +0 -61
  40. data/lib/market_bot/android/app.rb +0 -273
  41. data/lib/market_bot/android/developer.rb +0 -32
  42. data/lib/market_bot/android/leaderboard.rb +0 -232
  43. data/lib/market_bot/android/leaderboard/constants.rb +0 -59
  44. data/lib/market_bot/android/search_query.rb +0 -35
  45. data/lib/market_bot/movie/leaderboard.rb +0 -167
  46. data/lib/market_bot/movie/leaderboard/constants.rb +0 -30
  47. data/lib/market_bot/movie/search_query.rb +0 -32
  48. data/spec/market_bot/android/app_spec.rb +0 -253
  49. data/spec/market_bot/android/data/app_1.txt +0 -99
  50. data/spec/market_bot/android/data/app_2.txt +0 -100
  51. data/spec/market_bot/android/data/app_3.txt +0 -103
  52. data/spec/market_bot/android/data/app_4.txt +0 -117
  53. data/spec/market_bot/android/data/developer-zynga.txt +0 -97
  54. data/spec/market_bot/android/data/leaderboard-apps_editors_choice.txt +0 -97
  55. data/spec/market_bot/android/data/leaderboard-apps_topselling_paid-page1.txt +0 -97
  56. data/spec/market_bot/android/data/leaderboard-apps_topselling_paid-page2.txt +0 -97
  57. data/spec/market_bot/android/data/leaderboard-apps_topselling_paid-page3.txt +0 -97
  58. data/spec/market_bot/android/data/leaderboard-apps_topselling_paid-page4.txt +0 -97
  59. data/spec/market_bot/android/developer_spec.rb +0 -57
  60. data/spec/market_bot/android/leaderboard_spec.rb +0 -140
  61. data/spec/market_bot/android/search_query_spec.rb +0 -6
  62. data/spec/market_bot/movie/data/leaderboard-movies_comedy_topselling_paid.txt +0 -327
  63. data/spec/market_bot/movie/leaderboard_spec.rb +0 -67
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b9b827496e5425d3887b85c676d993abe3d0998
4
- data.tar.gz: 1387fb5cf278a03a366120f96758623388a710db
3
+ metadata.gz: 9206239cc019edb10efdf93e3c56e0bda9817e4b
4
+ data.tar.gz: 50dd856eb3b5aa3a69b494ba641b70b10ce75bf0
5
5
  SHA512:
6
- metadata.gz: 7aae31488f75f6c4c56fbc7d7e0bdf14a949dcf380d6de7a006024dd1e8b73e8f24c8ec118622932dbda16b8bcbd0147bbff129fc7c1db87b4c855ca58900d57
7
- data.tar.gz: 17e6cb00e21febbca548e6a8d4750383890335d2d6d2e4204aebc456c2fe7ed0f509c9b71b471f2c31e45c5edb3158ddd1a1fd35aa912eb4ad76884db07f759e
6
+ metadata.gz: 23560b228f34cd479889578a7ee1b56d974a6c88a910e6522eb18680de1265be6554e9a5169e9374abb081c0a17f410669cce92f53f7d982ea8f445e961bd489
7
+ data.tar.gz: 851d0bd20f7b00d17d6524857c356067a0fea1c5dfd4b46589f9bbaa74da1c251b7dc9a74b6f31fab57566bfbcb300d3ac1979716d2ac94c26a198208fece940
data/.travis.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.2
3
+ - 2.3.1
data/Guardfile ADDED
@@ -0,0 +1,70 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ # Note: The cmd option is now required due to the increasing number of ways
19
+ # rspec may be run, below are examples of the most common uses.
20
+ # * bundler: 'bundle exec rspec'
21
+ # * bundler binstubs: 'bin/rspec'
22
+ # * spring: 'bin/rspec' (This will use spring if running and you have
23
+ # installed the spring binstubs per the docs)
24
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
25
+ # * 'just' rspec: 'rspec'
26
+
27
+ guard :rspec, cmd: "bundle exec rspec" do
28
+ require "guard/rspec/dsl"
29
+ dsl = Guard::RSpec::Dsl.new(self)
30
+
31
+ # Feel free to open issues for suggestions and improvements
32
+
33
+ # RSpec files
34
+ rspec = dsl.rspec
35
+ watch(rspec.spec_helper) { rspec.spec_dir }
36
+ watch(rspec.spec_support) { rspec.spec_dir }
37
+ watch(rspec.spec_files)
38
+
39
+ # Ruby files
40
+ ruby = dsl.ruby
41
+ dsl.watch_spec_files_for(ruby.lib_files)
42
+
43
+ # Rails files
44
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
45
+ dsl.watch_spec_files_for(rails.app_files)
46
+ dsl.watch_spec_files_for(rails.views)
47
+
48
+ watch(rails.controllers) do |m|
49
+ [
50
+ rspec.spec.("routing/#{m[1]}_routing"),
51
+ rspec.spec.("controllers/#{m[1]}_controller"),
52
+ rspec.spec.("acceptance/#{m[1]}")
53
+ ]
54
+ end
55
+
56
+ # Rails config changes
57
+ watch(rails.spec_helper) { rspec.spec_dir }
58
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
59
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
60
+
61
+ # Capybara features specs
62
+ watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
63
+ watch(rails.layouts) { |m| rspec.spec.("features/#{m[1]}") }
64
+
65
+ # Turnip features and steps
66
+ watch(%r{^spec/acceptance/(.+)\.feature$})
67
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
68
+ Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
69
+ end
70
+ end
data/README.markdown CHANGED
@@ -1,14 +1,13 @@
1
- # Market Bot - [![Build Status](https://travis-ci.org/chadrem/market_bot.svg?branch=master)](https://travis-ci.org/chadrem/market_bot) [![Coverage Status](https://coveralls.io/repos/chadrem/market_bot/badge.svg?branch=master&service=github)](https://coveralls.io/github/chadrem/market_bot?branch=master)
1
+ # Market Bot - [![Build Status](https://travis-ci.org/chadrem/market_bot.svg?branch=master)](https://travis-ci.org/chadrem/market_bot) [![Coverage Status](https://coveralls.io/repos/github/chadrem/market_bot/badge.svg?branch=master)](https://coveralls.io/github/chadrem/market_bot?branch=master)
2
2
 
3
- Market Bot is a high performance Ruby scraper for Google's (Google Play) Android Market with a simple to use API.
4
- Currently it can: scrape apps, app leaderboards, movies, and tv shows. It can also search for apps.
5
- It is built on top of Nokogiri and Typhoeus.
3
+ Market Bot is a web scraper (web robot, web spider) for the Google Play Android app store.
4
+ It can collect data on apps, charts, and developers.
6
5
 
7
- **This project is currently seeking developers to help maintain it.
8
- Please send pull requests or contact me if you are able to help out.
9
- The best ways to get started are to fix bugs, improve documentation,
10
- and merge useful changes from public forks. By working together we
11
- can make the best scraper for the Google Play Store!**
6
+ ##### Commercial Support
7
+
8
+ Want to buy data instead of collect it yourself?
9
+ Want to add a feature to Market Bot, but don't know how?
10
+ Please contact me ([chad@remesch.com](mailto:chad@remesch.com)) for commercial solutions.
12
11
 
13
12
  ## Dependencies
14
13
 
@@ -17,97 +16,49 @@ can make the best scraper for the Google Play Store!**
17
16
 
18
17
  ## Installation
19
18
 
20
- gem install market_bot
19
+ Add this line to your application's Gemfile to use the latest stable version:
20
+
21
+ gem 'market_bot'
22
+
23
+ And then execute:
21
24
 
22
- ## Getting Started Example
25
+ $ bundle
23
26
 
24
- require 'rubygems'
25
- require 'market_bot'
27
+ ## App API example
26
28
 
27
- # Download all the data for the Facebook app.
28
- app = MarketBot::Android::App.new('com.facebook.katana')
29
+ # Download/parse the app.
30
+ app = MarketBot::Play::App.new('com.facebook.katana')
29
31
  app.update
30
32
 
31
- # Here we will print out the title of the app.
33
+ # Print out the app title.
32
34
  puts app.title
33
35
 
34
- # Here we will print out the rating of the app.
35
- puts app.rating
36
-
37
- # And the price...
38
- puts app.price
39
-
40
- # market_bot has many other attributes for each app.
41
- # You can see what attributes are available in your version of
42
- # market_bot by printing a simple constant included in the gem.
43
- puts MarketBot::Android::App::MARKET_ATTRIBUTES.inspect
44
-
45
- ## Simple API Examples
46
-
47
- require 'rubygems'
48
- require 'market_bot'
49
-
50
- # Download/parse the leaderboard.
51
- lb = MarketBot::Android::Leaderboard.new(:topselling_free, :game)
52
- lb.update
53
-
54
- # Download/parse the details for the first and last entries of the leaderboard.
55
- first_app = MarketBot::Android::App.new(lb.results.first[:market_id])
56
- last_app = MarketBot::Android::App.new(lb.results.last[:market_id])
57
- first_app.update
58
- last_app.update
59
- puts "First place app (#{first_app.title}) price: #{first_app.price}"
60
- puts "Last place app (#{last_app.title}) price: #{last_app.price}"
61
-
62
- # Search for apps.
63
- sq = MarketBot::Android::SearchQuery.new('donkeys')
64
- sq.update
65
- puts "Results found: #{sq.results.count}"
66
-
67
- # Download/parse developer pages.
68
- developer = MarketBot::Android::Developer.new('Zynga')
69
- developer.update
70
- puts "Results found: #{developer.results.count}"
71
-
72
- # Print the rating for an app.
73
- puts MarketBot::Android::App.new('com.king.candycrushsaga').update.rating
74
-
75
- # Check if an app exists and has a title.
76
- def app_exists?(app_id)
77
- begin
78
- return !!MarketBot::Android::App.new(app_id).update.title
79
- rescue
80
- return false
81
- end
82
- end
83
- app_exists?('com.king.candycrushsaga') # Return's true.
84
- app_exists?('com.some.fake.app.that.does.not.exist') # Return's false.
85
-
86
- ## Advanced API Examples
87
-
88
- require 'rubygems'
89
- require 'market_bot'
90
-
91
- # Create a reusable hydra object with 5 http workers.
92
- hydra = Typhoeus::Hydra.new(:max_concurrency => 5)
93
-
94
- # Download/parse the leaderboard.
95
- lb = MarketBot::Android::Leaderboard.new(:topselling_free, :game, :hyda => hydra)
96
- lb.update
97
-
98
- # Download/parse the details for the first and last entries of the leaderboard using the batch API.
99
- first_app = MarketBot::Android::App.new(lb.results.first[:market_id], :hydra => hydra)
100
- last_app = MarketBot::Android::App.new(lb.results.last[:market_id], :hydra => hydra)
101
- first_app.enqueue_update
102
- last_app.enqueue_update do |a|
103
- # Callback example. This block will execute on a successful hydra.run.
104
- puts "Callback... title: #{a.title}"
105
- end
106
- hydra.run
107
-
108
- # You must manually check if an error occurred when using the batch API without callbacks.
109
- puts "First place app (#{first_app.title}) price: #{first_app.price}" unless first_app.error
110
- puts "Last place app (#{last_app.title}) price: #{last_app.price}" unless last_app.error
36
+ # Print all the other attributes you can find on an app object.
37
+ puts MarketBot::Play::App::ATTRIBUTES.inspect
38
+
39
+ ## Charts API example
40
+
41
+ Charts are defined by a collection and an option category.
42
+
43
+ # Download/parse the chart (collection=topselling_free, category=GAME).
44
+ chart = MarketBot::Play::Chart.new('topselling_free', 'GAME')
45
+ chart.update
46
+
47
+ # Print the first app.
48
+ puts chart.result.first.inspect
49
+
50
+ # Print all the chart collections & categories.
51
+ puts MarketBot::Play::Chart::COLLECTIONS.inspect
52
+ puts MarketBot::Play::Chart::CATEGORIES.inspect
53
+
54
+ ## Developer API example
55
+
56
+ # Download/parse developer.
57
+ dev = MarketBot::Play::Developer.new('Zynga')
58
+ dev.update
59
+
60
+ # Print the first app.
61
+ puts dev.result.first.inspect
111
62
 
112
63
  ## Excessive Use
113
64
 
@@ -126,6 +77,5 @@ Please contact me if you are looking for commercial data solutions.
126
77
 
127
78
  ## Copyright
128
79
 
129
- Copyright (c) 2011 - 2015 Chad Remesch. See LICENSE.txt for
80
+ Copyright (c) 2011 - 2016 Chad Remesch. See LICENSE.txt for
130
81
  further details.
131
-
data/Rakefile CHANGED
@@ -8,92 +8,3 @@ end
8
8
 
9
9
  task :default => :spec
10
10
 
11
- desc 'Start an IRB console with Workers loaded'
12
- task :console do
13
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
14
-
15
- require 'market_bot'
16
- require 'irb'
17
-
18
- ARGV.clear
19
-
20
- IRB.start
21
- end
22
-
23
- namespace :spec do
24
- namespace :data do
25
- require 'typhoeus'
26
-
27
- def download(url, save_path)
28
- resp = Typhoeus::Request.get(url)
29
- File.open(save_path, "w") do |file|
30
- resp.body.force_encoding('utf-8')
31
- file.puts(resp.body)
32
- end
33
- end
34
-
35
- desc 'download the latest test data used by the specs'
36
- task :update do
37
- download('https://play.google.com/store/apps/details?id=com.bluefroggaming.popdat',
38
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'app_1.txt'))
39
-
40
- download('https://play.google.com/store/apps/details?id=com.evernote',
41
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'app_2.txt'))
42
-
43
- download('https://play.google.com/store/apps/details?id=com.mg.android',
44
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'app_3.txt'))
45
-
46
- download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?num=24',
47
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'leaderboard-apps_topselling_paid-page1.txt'))
48
-
49
- download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=24&num=24',
50
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'leaderboard-apps_topselling_paid-page2.txt'))
51
-
52
- download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=48&num=24',
53
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'leaderboard-apps_topselling_paid-page3.txt'))
54
-
55
- download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=96&num=24',
56
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'leaderboard-apps_topselling_paid-page4.txt'))
57
-
58
- download('https://play.google.com/store/apps/collection/editors_choice',
59
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'leaderboard-apps_editors_choice.txt'))
60
-
61
- download('https://play.google.com/store/apps/developer?id=Zynga',
62
- File.join(File.dirname(__FILE__), 'spec', 'market_bot', 'android', 'data', 'developer-zynga.txt'))
63
- end
64
- end
65
- end
66
-
67
- namespace :benchmark do
68
- task :android do
69
- require 'market_bot'
70
- require 'benchmark'
71
-
72
- hydra = Typhoeus::Hydra.new(:max_concurrency => 20)
73
-
74
- leaderboard = nil
75
- leaderboard_ms = Benchmark.realtime {
76
- leaderboard = MarketBot::Android::Leaderboard.new(:apps_topselling_paid, nil, :hydra => hydra)
77
- leaderboard.update
78
- }
79
-
80
- puts '----------------------------------------------------'
81
- puts 'Benchmark Leaderboard: Top Selling Paid Apps'
82
- puts '----------------------------------------------------'
83
- puts "app count: #{leaderboard.results.length}"
84
- puts "time: #{leaderboard_ms.round(3)} seconds"
85
- puts
86
-
87
- apps = nil
88
- apps_ms = Benchmark.realtime {
89
- apps = leaderboard.results.map{ |r| MarketBot::Android::App.new(r[:market_id], :hydra => hydra).enqueue_update }
90
- hydra.run
91
- }
92
-
93
- puts '----------------------------------------------------'
94
- puts 'Benchmark Apps: top Selling Paid Apps'
95
- puts '----------------------------------------------------'
96
- puts "app count: #{apps.length}"
97
- puts "time: #{apps_ms.round(3)} seconds"
98
- end
99
- end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'nokogiri'
5
+ require 'typhoeus'
6
+
7
+ res = Typhoeus.get('https://play.google.com/store/apps', timeout: 5, connecttimeout: 5)
8
+ doc = Nokogiri::HTML(res.body)
9
+ elems = doc.css('a.child-submenu-link')
10
+ links = elems.map { |e| e.attributes['href'].value }
11
+
12
+ # Filter out non-app links such as 'Popular Characters'.
13
+ links = links.select { |l| l =~ /apps\/category/ }
14
+
15
+ categories = links.map { |l| l.gsub('/store/apps/category/', '') }
16
+
17
+ categories.each { |c| puts c }
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'market_bot'
5
+
6
+ require 'benchmark'
7
+
8
+ loops = 5
9
+ test_files = %w{app_1.txt app_2.txt app_3.txt}
10
+ test_files.each do |test_file|
11
+ puts '----------------------------------------------------'
12
+ puts "Benchmark App Parser: #{test_file}"
13
+ puts '----------------------------------------------------'
14
+ file_path = File.join(File.dirname(__FILE__), '..', 'spec', 'market_bot', 'play', 'data', test_file)
15
+ html = File.read(file_path)
16
+
17
+ total = 0.0
18
+ loops.times do
19
+ total += Benchmark.realtime { MarketBot::Play::App.parse(html) }
20
+ end
21
+ average = total.to_f / loops.to_f
22
+
23
+ puts "average: #{average} seconds"
24
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "market_bot"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'typhoeus'
5
+
6
+ def download(url, name)
7
+ path = play_path(name)
8
+ puts "Downloading: #{name}..."
9
+ resp = Typhoeus::Request.get(url)
10
+ File.open(path, 'w') do |file|
11
+ resp.body.force_encoding('utf-8')
12
+ file.puts(resp.body)
13
+ end
14
+ end
15
+
16
+ def play_path(name)
17
+ File.join(File.dirname(__FILE__), '..', 'spec', 'market_bot', 'play', 'data', name)
18
+ end
19
+
20
+ download('https://play.google.com/store/apps/details?id=com.bluefroggaming.popdat', 'app-com.bluefroggaming.popdat.txt')
21
+ download('https://play.google.com/store/apps/details?id=com.mg.android', 'app-com.mg.android.txt')
22
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=0&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-0.txt')
23
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=100&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-1.txt')
24
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=200&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-2.txt')
25
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=300&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-3.txt')
26
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=400&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-4.txt')
27
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=500&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-5.txt')
28
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=600&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-6.txt')
29
+ download('https://play.google.com/store/apps/category/GAME_ARCADE/collection/topselling_paid?start=700&gl=us&num=100&hl=en', 'chart-topselling_paid-GAME_ARCADE-7.txt')
30
+ download('https://play.google.com/store/apps/developer?id=Zynga', 'developer-zynga.txt')