bnet_scraper 0.6.0 → 0.7.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.
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