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 +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
|