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 +65 -54
- data/bnet_scraper.gemspec +2 -1
- data/lib/bnet_scraper/starcraft2.rb +6 -10
- data/lib/bnet_scraper/starcraft2/achievement.rb +1 -12
- data/lib/bnet_scraper/starcraft2/achievement_scraper.rb +47 -33
- data/lib/bnet_scraper/starcraft2/base_scraper.rb +2 -0
- data/lib/bnet_scraper/starcraft2/league.rb +5 -3
- data/lib/bnet_scraper/starcraft2/league_scraper.rb +15 -12
- data/lib/bnet_scraper/starcraft2/profile.rb +11 -2
- data/lib/bnet_scraper/starcraft2/profile_scraper.rb +26 -27
- data/spec/starcraft2/achievement_scraper_spec.rb +13 -1
- data/spec/starcraft2/league_scraper_spec.rb +7 -0
- data/spec/starcraft2/profile_scraper_spec.rb +12 -9
- data/spec/starcraft2_spec.rb +1 -1
- data/spec/support/fixtures/vcr_cassettes/demon_profile.yml +1289 -1585
- data/spec/support/fixtures/vcr_cassettes/euro_achievements.yml +237 -0
- metadata +6 -3
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
|
-
|
45
|
-
profile
|
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/
|
64
|
-
BnetScraper::Starcraft2::ProfileScraper.new(bnet_id: '
|
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.
|
68
|
-
|
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
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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(
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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(
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
data/bnet_scraper.gemspec
CHANGED
@@ -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
|
+
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
|
42
|
-
#
|
43
|
-
# @
|
44
|
-
|
45
|
-
|
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.
|
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
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
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
|
-
|
110
|
-
|
111
|
-
|
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
|
@@ -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
|
-
|
41
|
+
scrape
|
42
42
|
self.instance_variable_get(attribute)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
47
|
-
|
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
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
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
|