bnet_scraper 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -41,8 +41,9 @@ just for you. Call `BnetScraper::Starcraft2#full_profile_scrape` with the usual
41
41
  ProfileScraper would take, and it will eager-load the achievements, matches, and leagues.
42
42
 
43
43
  ``` ruby
44
- scraper = BnetScraper::Starcraft2.full_profile_scrape(url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/')
45
- profile = scraper.scrape
44
+ profile = BnetScraper::Starcraft2.full_profile_scrape(url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/')
45
+ profile.class.name # => 'BnetScraper::Starcraft2::Profile'
46
+ profile.leagues.first.name # => 'Changeling Bravo'
46
47
  ```
47
48
 
48
49
  Alternatively, these scrapers can be accessed in isolation.
@@ -60,12 +61,12 @@ All of the scrapers take an options hash, and can be created by either passing a
60
61
  passing the account information in the options hash. Thus, either of these two approaches work:
61
62
 
62
63
  ``` ruby
63
- BnetScraper::Starcraft2::ProfileScraper.new(url: 'http://us.battle.net/sc2/en/profile/12345/1/TestAccount/')
64
- BnetScraper::Starcraft2::ProfileScraper.new(bnet_id: '12345', account: 'TestAccount', region: 'na')
64
+ scraper1 = BnetScraper::Starcraft2::ProfileScraper.new(url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/')
65
+ scraper2 = BnetScraper::Starcraft2::ProfileScraper.new(bnet_id: '2377239', account: 'Demon', region: 'na')
65
66
  ```
66
67
 
67
- All scrapers have a `#scrape` method that triggers the scraping and storage. By default they will return the result,
68
- but an additional `#output` method exists to retrieve the results subsequent times without re-scraping.
68
+ All scrapers have a `#scrape` method that triggers the scraping and storage. The `#scrape` method will return an
69
+ object containing the scraped data result.
69
70
 
70
71
  ### BnetScraper::Starcraft2::ProfileScraper
71
72
 
@@ -78,6 +79,17 @@ profile = scraper.scrape
78
79
  profile.class.name # => BnetScraper::Starcraft2::Profile
79
80
  ```
80
81
 
82
+ Additionally, the resulting `BnetScraper::Starcraft2::Profile` object has methods to scrape additional
83
+ information without the need of creating another scraper. For example, if you need to pull league information up
84
+ on a player, you may call `BnetScraper::Starcraft2::Profile#leagues` and it will scrape and store the information
85
+ for memoized access.
86
+
87
+ ``` ruby
88
+ scraper = BnetScraper::Starcraft2::ProfileScraper.new(url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/')
89
+ profile = scraper.scrape
90
+ profile.leagues.map(&:division) #=> ['Bronze']
91
+ ```
92
+
81
93
  ### BnetScraper::Starcraft2::LeagueScraper
82
94
 
83
95
  This pulls information on a specific league for a specific account. It is best used either in conjunction with a
@@ -86,15 +98,15 @@ profile scrape that profiles a URL, or if you happen to know the specific league
86
98
  ``` ruby
87
99
  scraper = BnetScraper::Starcraft2::LeagueScraper.new(league_id: '12345', account: 'Demon', bnet_id: '2377239')
88
100
  scraper.scrape
89
- # => {
90
- season: '6',
91
- name: 'Aleksander Pepper',
92
- division: 'Diamond',
93
- size: '4v4',
94
- random: false,
95
- bnet_id: '2377239',
96
- account: 'Demon'
97
- }
101
+
102
+ # => #<BnetScraper::Starcraft2::League:0x007f89eab7a680
103
+ @account="Demon",
104
+ @bnet_id="2377239",
105
+ @division="Bronze",
106
+ @name="Changeling Bravo",
107
+ @random=false,
108
+ @season="2013 Season 4",
109
+ @size="3v3">
98
110
  ```
99
111
 
100
112
  ### BnetScraper::Starcraft2::AchievementScraper
@@ -103,33 +115,30 @@ This pulls achievement information for an account. Note that currently only ret
103
115
  not the in-depth, by-category achievement information.
104
116
 
105
117
  ``` ruby
106
- scraper = BnetScraper::Starcraft2::AchievementScraper.new(url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/')
107
- scraper.scrape
108
- # => {
109
- recent: [
110
- { title: 'Blink of an Eye', description: 'Complete round 24 in "Starcraft Master" without losing any stalkers', earned: '3/5/2012' },
111
- { title: 'Whack-a-Roach', description: 'Complete round 9 in "Starcraft Master" in under 45 seconds', earned: '3/5/2012' },
112
- { title: 'Safe Zone', description: 'Complete round 8 in "Starcraft Master" without losing any stalkers', earned: '3/5/2012' },
113
- { title: 'Starcraft Master', description: 'Complete all 30 rounds in "Starcraft Master"', earned: '3/5/2012' },
114
- { title: 'Starcraft Expert', description: 'Complete any 25 rounds in "Starcraft Master"', earned: '3/5/2012' },
115
- { title: 'Starcraft Apprentice', description: 'Complete any 20 rounds in "Starcraft Master"', earned: '3/5/2012' }
116
- ],
117
- showcase: [
118
- { title: 'Hot Shot', description: 'Finish a Qualification Round with an undefeated record.' },
119
- { title: 'Starcraft Master', description: 'Complete all rounds in "Starcraft Master"' },
120
- { title: 'Team Protoss 500', description: 'Win 500 team league matches as Protoss' },
121
- { title: 'Night of the Living III', description: 'Survive 15 Infested Horde Attacks in the "Night 2 Die" mode of the "Left 2 Die" scenario.' },
122
- { title: 'Team Top 100 Diamond', description: 'Finish a Season in Team Diamond Division' }
123
-
124
- ],
125
- progress: {
126
- liberty_campaign: '1580',
127
- exploration: '480',
128
- custom_game: '330',
129
- cooperative: '660',
130
- quick_match: '170'
131
- }
132
- }
118
+ scraper = BnetScraper::Starcraft2::AchievementScraper.new(
119
+ url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/'
120
+ )
121
+ achievement_information = scraper.scrape
122
+ achievement_information[:recent].size # => 6
123
+ achievement_information[:recent].first
124
+ # => #<BnetScraper::Starcraft2::Achievement:0x007fef52b0b488
125
+ @description="Win 50 Team Unranked or Ranked games as Zerg.",
126
+ @earned=#<Date: 2013-04-04 ((2456387j,0s,0n),+0s,2299161j)>,
127
+ @title="50 Wins: Team Zerg">
128
+
129
+ achievement_information[:progress]
130
+ # => {:liberty_campaign=>1580,
131
+ :swarm_campaign=>1120,
132
+ :matchmaking=>1410,
133
+ :custom_game=>120,
134
+ :arcade=>220,
135
+ :exploration=>530}
136
+
137
+ achievement_information[:showcase].size # => 5
138
+ achievement_information[:showcase].first
139
+ # => #<BnetScraper::Starcraft2::Achievement:0x007fef52abcb08
140
+ @description="Finish a Qualification Round with an undefeated record.",
141
+ @title="Hot Shot">
133
142
  ```
134
143
 
135
144
  ### BnetScraper::Starcraft2::MatchHistoryScraper
@@ -138,18 +147,20 @@ This pulls the 25 most recent matches played for an account. Note that this is o
138
147
  will likely not be as fast as in-game.
139
148
 
140
149
  ``` ruby
141
- scraper = BnetScraper::Starcraft2::MatchHistoryScraper.new(url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/')
142
- scraper.scrape
143
- # => {
144
- wins: '15',
145
- losses: '10',
146
- matches: [
147
- { map_name: 'Bx Monobattle - Sand Canyon (Fix)', outcome: :win, type: 'Custom', date: '3/12/2012' },
148
- { map_name: 'Deadlock Ridge', outcome: :loss, type: '4v4', date: '3/12/2012' },
149
- { map_name: 'District 10', outcome: :win, type: '4v4', date: '3/12/2012' },
150
- # ...
151
- ]
152
- }
150
+ scraper = BnetScraper::Starcraft2::MatchHistoryScraper.new(
151
+ url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/'
152
+ )
153
+ matches = scraper.scrape
154
+ matches.size # => 25
155
+ wins = matches.count { |m| m.outcome == :win } # => 15
156
+ losses = matches.count { |m| m.outcome == :loss } # => 10
157
+
158
+ matches.first
159
+ # => #<BnetScraper::Starcraft2::Match:0x007fef55113428
160
+ @date="5/24/2013",
161
+ @map_name="Queen's Nest",
162
+ @outcome=:win,
163
+ @type="3v3">
153
164
  ```
154
165
 
155
166
  ## BnetScraper::Starcraft2::Status
@@ -3,12 +3,13 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "bnet_scraper"
6
- s.version = "0.6.0"
6
+ s.version = "0.7.0"
7
7
  s.authors = ["Andrew Nordman"]
8
8
  s.email = ["cadwallion@gmail.com"]
9
9
  s.homepage = "https://github.com/agoragames/bnet_scraper/"
10
10
  s.summary = %q{Battle.net Profile Scraper}
11
11
  s.description = %q{BnetScraper is a Nokogiri-based scraper of Battle.net profile information. Currently this only includes Starcraft2.}
12
+ s.license = 'MIT'
12
13
 
13
14
  s.files = `git ls-files`.split("\n")
14
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -28,8 +28,6 @@ module BnetScraper
28
28
  'tw.battle.net' => 'fea'
29
29
  }
30
30
 
31
-
32
-
33
31
  # This is a convenience method that chains calls to ProfileScraper,
34
32
  # followed by a scrape of each league returned in the `leagues` array
35
33
  # in the profile_data. The end result is a fully scraped profile with
@@ -38,16 +36,14 @@ module BnetScraper
38
36
  # See `BnetScraper::Starcraft2::ProfileScraper` for more information on
39
37
  # the parameters being sent to `#full_profile_scrape`.
40
38
  #
41
- # @param bnet_id - Battle.net Account ID
42
- # @param account - Battle.net Account Name
43
- # @param region - Battle.net Account Region
44
- # @return profile_data - Hash containing complete profile and league data
45
- # scraped from the website
46
- def self.full_profile_scrape bnet_id, account, region = 'na'
47
- profile_scraper = ProfileScraper.new bnet_id: bnet_id, account: account, region: region
39
+ # @param options - Hash of profile options (url, bnet_id/account/region, etc). See
40
+ # `BnetScraper::Starcraft::BaseScraper` for more information on hash options.
41
+ # @return [BnetScraper::Profile] profile_data - Profile object containing complete profile and league data
42
+ def self.full_profile_scrape options = {}
43
+ profile_scraper = ProfileScraper.new options
48
44
  profile = profile_scraper.scrape
49
45
  profile.leagues.each do |league|
50
- league.scrape_league
46
+ league.scrape
51
47
  end
52
48
  profile.achievements
53
49
  profile.match_history
@@ -1,24 +1,13 @@
1
- require 'date'
2
1
  module BnetScraper
3
2
  module Starcraft2
4
3
  class Achievement
5
- attr_accessor :title, :description
6
- attr_reader :earned
4
+ attr_accessor :title, :description, :earned
7
5
 
8
6
  def initialize options = {}
9
7
  options.each_key do |key|
10
8
  self.send "#{key}=", options[key]
11
9
  end
12
10
  end
13
-
14
- def earned= date
15
- @earned = convert_date date
16
- end
17
-
18
- def convert_date date
19
- month, day, year = date.scan(/(\d+)\/(\d+)\/(\d+)/).first.map(&:to_i)
20
- Date.new year, month, day
21
- end
22
11
  end
23
12
  end
24
13
  end
@@ -1,38 +1,37 @@
1
1
  require 'bnet_scraper/starcraft2/achievement'
2
+ require 'date'
2
3
 
3
4
  module BnetScraper
4
5
  module Starcraft2
5
6
  # This pulls achievement information for an account. Note that currently only returns the overall achievements,
6
7
  # not the in-depth, by-category achievement information.
7
8
  #
8
- # scraper = BnetScraper::Starcraft2::AchievementScraper.new(url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/')
9
- # scraper.scrape
10
- # # => {
11
- # recent: [
12
- # { title: 'Blink of an Eye', description: 'Complete round 24 in "Starcraft Master" without losing any stalkers', earned: '3/5/2012' },
13
- # { title: 'Whack-a-Roach', description: 'Complete round 9 in "Starcraft Master" in under 45 seconds', earned: '3/5/2012' },
14
- # { title: 'Safe Zone', description: 'Complete round 8 in "Starcraft Master" without losing any stalkers', earned: '3/5/2012' },
15
- # { title: 'Starcraft Master', description: 'Complete all 30 rounds in "Starcraft Master"', earned: '3/5/2012' },
16
- # { title: 'Starcraft Expert', description: 'Complete any 25 rounds in "Starcraft Master"', earned: '3/5/2012' },
17
- # { title: 'Starcraft Apprentice', description: 'Complete any 20 rounds in "Starcraft Master"', earned: '3/5/2012' }
18
- # ],
19
- # showcase: [
20
- # { title: 'Hot Shot', description: 'Finish a Qualification Round with an undefeated record.' },
21
- # { title: 'Starcraft Master', description: 'Complete all rounds in "Starcraft Master"' },
22
- # { title: 'Team Protoss 500', description: 'Win 500 team league matches as Protoss' },
23
- # { title: 'Night of the Living III', description: 'Survive 15 Infested Horde Attacks in the "Night 2 Die" mode of the "Left 2 Die" scenario.' },
24
- # { title: 'Team Top 100 Diamond', description: 'Finish a Season in Team Diamond Division' }
25
- #
26
- # ],
27
- # progress: {
28
- # liberty_campaign: '1580',
29
- # swarm_campaign: '480',
30
- # matchmaking: '1100',
31
- # custom_game: '330',
32
- # arcade: '660',
33
- # exploration: '170'
34
- # }
35
- # }
9
+ # ``` ruby
10
+ # scraper = BnetScraper::Starcraft2::AchievementScraper.new(
11
+ # url: 'http://us.battle.net/sc2/en/profile/2377239/1/Demon/'
12
+ # )
13
+ # achievement_information = scraper.scrape
14
+ # achievement_information[:recent].size # => 6
15
+ # achievement_information[:recent].first
16
+ # # => #<BnetScraper::Starcraft2::Achievement:0x007fef52b0b488
17
+ # @description="Win 50 Team Unranked or Ranked games as Zerg.",
18
+ # @earned=#<Date: 2013-04-04 ((2456387j,0s,0n),+0s,2299161j)>,
19
+ # @title="50 Wins: Team Zerg">
20
+ #
21
+ # achievement_information[:progress]
22
+ # # => {:liberty_campaign=>1580,
23
+ # :swarm_campaign=>1120,
24
+ # :matchmaking=>1410,
25
+ # :custom_game=>120,
26
+ # :arcade=>220,
27
+ # :exploration=>530}
28
+ #
29
+ # achievement_information[:showcase].size # => 5
30
+ # achievement_information[:showcase].first
31
+ # # => #<BnetScraper::Starcraft2::Achievement:0x007fef52abcb08
32
+ # @description="Finish a Qualification Round with an undefeated record.",
33
+ # @title="Hot Shot">
34
+ # ```
36
35
  class AchievementScraper < BaseScraper
37
36
  attr_reader :recent, :progress, :showcase, :response
38
37
 
@@ -78,11 +77,23 @@ module BnetScraper
78
77
  Achievement.new({
79
78
  title: div.children[1].inner_text,
80
79
  description: div.children[2].inner_text.strip,
81
- earned: response.css(".recent-tile")[num].css('span')[1].inner_text
80
+ earned: convert_date(response.css(".recent-tile")[num].css('span')[1].inner_text)
82
81
  })
83
82
  end
84
83
  end
85
84
 
85
+ def convert_date date
86
+ dates = date.scan(/(\d+)\/(\d+)\/(\d+)/).first.map(&:to_i)
87
+
88
+ if region == 'na'
89
+ month, day, year = dates
90
+ else
91
+ day, month, year = dates
92
+ end
93
+
94
+ Date.new year, month, day
95
+ end
96
+
86
97
 
87
98
 
88
99
  # Scrapes the progress of each achievement category from the account's achievements
@@ -106,10 +117,12 @@ module BnetScraper
106
117
  # @return [Array<Achievement>] Array containing all the showcased achievements
107
118
  def scrape_showcase
108
119
  @showcase = response.css("#showcase-module .progress-tile").map do |achievement|
109
- Achievement.new({
110
- title: achievement.css('.tooltip-title').inner_text.strip,
111
- description: achievement.children[3].children[2].inner_text.strip
112
- })
120
+ if !achievement.values.first.split.include? 'empty'
121
+ Achievement.new({
122
+ title: achievement.css('.tooltip-title').inner_text.strip,
123
+ description: achievement.children[3].children[2].inner_text.strip
124
+ })
125
+ end
113
126
  end
114
127
  @showcase
115
128
  end
@@ -121,6 +134,7 @@ module BnetScraper
121
134
  showcase: @showcase
122
135
  }
123
136
  end
137
+
124
138
  end
125
139
  end
126
140
  end
@@ -1,3 +1,5 @@
1
+ require 'net/http'
2
+
1
3
  module BnetScraper
2
4
  module Starcraft2
3
5
  # BaseScraper handles the account information extraction. Each scraper can either be passed a profile URL or
@@ -38,13 +38,15 @@ module BnetScraper
38
38
  if self.instance_variable_get(attribute)
39
39
  return self.instance_variable_get(attribute)
40
40
  else
41
- scrape_league
41
+ scrape
42
42
  self.instance_variable_get(attribute)
43
43
  end
44
44
  end
45
45
 
46
- def scrape_league
47
- scraped_data = LeagueScraper.new(url: href).scrape
46
+ def scrape
47
+ scraper = LeagueScraper.new(url: href)
48
+ scraper.scrape
49
+ scraped_data = scraper.output
48
50
  scraped_data.each_key do |key|
49
51
  self.send "#{key}=", scraped_data[key]
50
52
  end
@@ -5,17 +5,19 @@ module BnetScraper
5
5
  # This pulls information on a specific league for a specific account. It is best used either in conjunction with a
6
6
  # profile scrape that profiles a URL, or if you happen to know the specific league\_id and can pass it as an option.
7
7
  #
8
- # scraper = BnetScraper::Starcraft2::LeagueScraper.new(league_id: '12345', account: 'Demon', bnet_id: '2377239')
9
- # scraper.scrape
10
- # # => {
11
- # season: '6',
12
- # name: 'Aleksander Pepper',
13
- # division: 'Diamond',
14
- # size: '4v4',
15
- # random: false,
16
- # bnet_id: '2377239',
17
- # account: 'Demon'
18
- # }
8
+ # ``` ruby
9
+ # scraper = BnetScraper::Starcraft2::LeagueScraper.new(league_id: '12345', account: 'Demon', bnet_id: '2377239')
10
+ # scraper.scrape
11
+ #
12
+ # # => #<BnetScraper::Starcraft2::League:0x007f89eab7a680
13
+ # @account="Demon",
14
+ # @bnet_id="2377239",
15
+ # @division="Bronze",
16
+ # @name="Changeling Bravo",
17
+ # @random=false,
18
+ # @season="2013 Season 4",
19
+ # @size="3v3">
20
+ # ```
19
21
  class LeagueScraper < BaseScraper
20
22
  attr_reader :league_id, :season, :size, :random, :name, :division
21
23
 
@@ -28,6 +30,7 @@ module BnetScraper
28
30
  @league_id = options[:url].match(/http:\/\/.+\/sc2\/.+\/profile\/.+\/\d{1}\/.+\/ladder\/(.+)(#current-rank)?/).to_a[1]
29
31
  else
30
32
  @league_id = options[:league_id]
33
+ @url = "#{profile_url}ladder/#{@league_id}"
31
34
  end
32
35
  end
33
36
 
@@ -42,7 +45,7 @@ module BnetScraper
42
45
  @season, @size, @random, @division, @name = header_values
43
46
 
44
47
  @random = !@random.nil?
45
- output
48
+ League.new(output)
46
49
  else
47
50
  raise BnetScraper::InvalidProfileError
48
51
  end
@@ -1,4 +1,3 @@
1
-
2
1
  module BnetScraper
3
2
  module Starcraft2
4
3
  class Profile
@@ -6,7 +5,7 @@ module BnetScraper
6
5
  :highest_solo_league, :current_team_league, :highest_team_league,
7
6
  :career_games, :games_this_season, :terran_swarm_level, :protoss_swarm_level,
8
7
  :zerg_swarm_level, :leagues, :swarm_levels, :terran_campaign_completion,
9
- :zerg_campaign_completion
8
+ :zerg_campaign_completion, :clan_tag, :clan_name, :account
10
9
 
11
10
  def initialize options = {}
12
11
  options.each_key do |key|
@@ -58,6 +57,16 @@ module BnetScraper
58
57
  false
59
58
  end
60
59
  end
60
+
61
+ def scrape
62
+ scraper = ProfileScraper.new(url: @url)
63
+ scraper.scrape
64
+
65
+ scraped_data = scraper.output
66
+ scraped_data.each_key do |key|
67
+ self.send "#{key}=", scraped_data[key]
68
+ end
69
+ end
61
70
  end
62
71
  end
63
72
  end