football_now 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7dada34844e1d8c67413b9b4c018b9e86bc9bd74
4
+ data.tar.gz: f2f629b4a491c40df0991bf3ac0b7bca2cb6d508
5
+ SHA512:
6
+ metadata.gz: 62aa6b58d2634d527e9a06b5904eca84c79d70e38b5251da66af9f9c43e7cc6369390b0883267141fb074fab0ba8e634b86925f0b9ac81c4ea82acc0ed681ce0
7
+ data.tar.gz: 6870df52f01351e5e393850d076f3ab033b2111f60b32258cab588604f5275326175564526b6d2c1b0c62b5309dff4bb804a101d2b0a707c7faf0cc20e614df3
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /NOTES.md
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in football_now.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 gnfisher
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # FootballNow
2
+
3
+ Football Now brings you all the information you need from top Football leagues in Europe.
4
+
5
+ ## Project goals
6
+
7
+ - User can get latest scores (including live scores if match is ongoing)
8
+ - User can get league standings
9
+ - User can get list of results for a specific team
10
+ - User can get list of upcoming matches for a specific team
11
+
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'football_now'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install football_now
28
+
29
+ ## Usage
30
+
31
+ TODO: Write usage instructions here
32
+
33
+ ## Development
34
+
35
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
36
+
37
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
38
+
39
+ ## Contributing
40
+
41
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/football_now.
42
+
43
+
44
+ ## License
45
+
46
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "football_now"
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/football_now ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'football_now.rb'
4
+
5
+ FootballNow::CLI.new.call
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,23 @@
1
+ # require 'require_all'
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+ require 'capybara'
5
+ require 'capybara/dsl'
6
+ require 'capybara/poltergeist'
7
+
8
+
9
+ Capybara.default_driver = :poltergeist
10
+ Capybara.run_server = false
11
+ Capybara.default_max_wait_time = 120
12
+ Capybara.register_driver :poltergeist do |app|
13
+ Capybara::Poltergeist::Driver.new(app, js_errors: false, phantomjs_options: ['--load-images=false', '--disk-cache=false'])
14
+ end
15
+
16
+ require 'football_now/version'
17
+ require 'cli'
18
+ require 'db'
19
+ require 'importer'
20
+ require 'league'
21
+ require 'match'
22
+ require 'scraper'
23
+ require 'team'
data/data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *
2
+ !.gitignore
data/exe/football_now ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'football_now.rb'
4
+
5
+ FootballNow::CLI.new.call
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'football_now/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "football_now"
8
+ spec.version = FootballNow::VERSION
9
+ spec.authors = ["gnfisher"]
10
+ spec.email = ["me@gnfisher.com"]
11
+
12
+ spec.summary = %q{Get standings, results and stats on the top four European leagues from your command line.}
13
+ spec.description = %q{Scraping a popular football site, this gem allows you to navigate the standings, results, and stats of the teams in Europe's top competitions.}
14
+ spec.homepage = "http://gnfisher.com"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib", "config", "data"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.10"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rspec"
33
+
34
+ spec.add_runtime_dependency "nokogiri"
35
+ spec.add_runtime_dependency "require_all"
36
+ spec.add_runtime_dependency "capybara"
37
+ spec.add_runtime_dependency "poltergeist"
38
+ end
data/lib/cli.rb ADDED
@@ -0,0 +1,170 @@
1
+ class FootballNow::CLI
2
+
3
+ def call
4
+ welcome_screen
5
+ list_leagues
6
+
7
+ end
8
+
9
+ def list_leagues
10
+ puts "\n\n"
11
+ puts "Available Leagues:"
12
+ puts "=================="
13
+ FootballNow::League.print_leagues
14
+ puts ""
15
+ puts "You can:"
16
+ puts " - type `<#> recent results` for scores"
17
+ puts " - type `<#> get standings` for the league table"
18
+ puts " - type `<#> list teams` to explore a team indepth"
19
+ puts " - type `exit` to quit now."
20
+ puts ""
21
+ puts "Usage: typing `1 list teams` will list all teams in the first league listed."
22
+ puts ""
23
+ puts "What would you like to do?"
24
+
25
+ input = get_user_input
26
+ league = FootballNow::League.get_league_by_index(input.split("").first.to_i - 1) if input =~ /^\d/
27
+
28
+ case input
29
+ when "exit"
30
+ goodbye_message
31
+ when /^\D/
32
+ puts "Sorry, I didn't understand..."
33
+ list_leagues
34
+ when /recent results/
35
+ list_recent_results(league)
36
+ list_leagues
37
+ when /get standings/
38
+ get_standings(league)
39
+ when /list teams/
40
+ list_teams(league)
41
+ else
42
+ puts "Sorry, I didn't understand..."
43
+ list_leagues
44
+ end
45
+ end
46
+
47
+ def list_recent_results(league)
48
+ puts ""
49
+ puts "#{league.name.upcase}"
50
+ puts "Round #{league.current_round}:"
51
+ puts ""
52
+
53
+ FootballNow::Match.get_recent_results(league).each do |result|
54
+ puts " #{result.home_score} #{result.home_team.name}"
55
+ puts " #{result.away_score} #{result.away_team.name}"
56
+ puts ""
57
+ end
58
+
59
+ puts "Hit enter to go back or exit to quit."
60
+ goodbye_message if get_user_input.downcase == "exit"
61
+ end
62
+
63
+ def get_standings(league)
64
+ table = league.get_standings
65
+
66
+ puts ""
67
+ puts "#{league.name.upcase} : Up to Round #{league.current_round}"
68
+ puts "=========================================="
69
+ print_table(table)
70
+ puts ""
71
+ puts "Hit enter to return to league list or exit to quit."
72
+
73
+ get_user_input.downcase == "exit" ? goodbye_message : list_leagues
74
+ end
75
+
76
+ def list_teams(league)
77
+ puts ""
78
+ puts "#{league.name.upcase} : Up to Round #{league.current_round}"
79
+ puts ""
80
+
81
+ format = '%-4s %-20s'
82
+ league.teams.sort_by{|team| team.name}.each_with_index do |team, index|
83
+ puts format % [index + 1, team.name]
84
+ end
85
+
86
+ puts ""
87
+ puts "You can:"
88
+ puts " - type `<#> results` for all results"
89
+ puts " - type `<#> stats` for all avaulable stats"
90
+ puts " - type `back` to return to the first menu"
91
+ puts " - type `exit` to quit now."
92
+ puts ""
93
+ puts "Usage: typing `1 results` will list all results for that team."
94
+ puts ""
95
+ puts "What would you like to do?"
96
+
97
+ input = get_user_input
98
+ team = league.teams.sort_by{|team| team.name}[input.to_i - 1] if input =~ /^\d/
99
+
100
+ case input
101
+ when /results/
102
+ list_all_results(team)
103
+ list_teams(league)
104
+ when /stats/
105
+ list_stats(team)
106
+ list_teams(league)
107
+ when /back/
108
+ list_leagues
109
+ when /exit/
110
+ goodbye_message
111
+ else
112
+ puts "Sorry, I didn't understand you."
113
+ list_teams
114
+ end
115
+ end
116
+
117
+ def list_all_results(team)
118
+ puts ""
119
+ puts "#{team.name.upcase}: League Results"
120
+ puts ""
121
+ team.matches.each do |match|
122
+ puts "Round #{match.round}:"
123
+ puts " #{match.home_score} #{match.home_team.name}"
124
+ puts " #{match.away_score} #{match.away_team.name}"
125
+ puts ""
126
+ end
127
+
128
+ puts "Hit enter to go back or exit to quit."
129
+ goodbye_message if get_user_input.downcase == "exit"
130
+ end
131
+
132
+ def list_stats(team)
133
+ puts ""
134
+ puts "#{team.name.upcase}: League Stats"
135
+ puts ""
136
+ format = '%-5s %-5s %-8s %-10s %-10s %-13s %s'
137
+ puts format % ['Wins', 'Draws', 'Losses', 'Points', 'Goals For', 'Goals Against', 'Matches Played']
138
+ puts format % [ team.wins, team.draws, team.losses, team.points, team.goals_for, team.goals_against, team.matches.size ]
139
+ puts "Hit enter to go back or exit to quit."
140
+ goodbye_message if get_user_input.downcase == "exit"
141
+ end
142
+
143
+ def print_table(table)
144
+ format = '%-4s %-20s %-3s %-3s %-3s %s'
145
+ puts format % ['#', 'Team', 'W', 'D', 'L', 'Pts']
146
+ table.each do |team|
147
+ puts format % [ team.standing, team.name, team.wins, team.draws, team.losses, team.points]
148
+ end
149
+ end
150
+
151
+ def welcome_screen
152
+ puts "Welcome to Football Now"
153
+ load_all_data
154
+ end
155
+
156
+ def load_all_data
157
+ puts "Loading data from www.soccer24.com..."
158
+ puts "This may take a minute or two..."
159
+ FootballNow::Importer.generate
160
+ end
161
+
162
+ def goodbye_message
163
+ puts "Until next time!"
164
+ exit 0
165
+ end
166
+
167
+ def get_user_input
168
+ gets.strip
169
+ end
170
+ end
data/lib/db.rb ADDED
@@ -0,0 +1,67 @@
1
+ class FootballNow::DB
2
+
3
+ extend Capybara::DSL
4
+
5
+ def self.get_html(url)
6
+ url_array = strip_url(url)
7
+ file_path = file_path_from(url_array)
8
+
9
+ if File.exists?(file_path) && not_expired?(file_path)
10
+ File.read(file_path)
11
+ else
12
+ return_html(url_array, url)
13
+ end
14
+ end
15
+
16
+ def self.get_leagues_html(url)
17
+ page_html = open(url).read
18
+ url_array = strip_url(url)
19
+ save_as_file(url_array, page_html)
20
+ page_html
21
+ end
22
+
23
+ def self.get_standings_html(url)
24
+ visit(url)
25
+ sleep(1)
26
+
27
+ url_array = strip_url(url)
28
+ save_as_file(url_array, page.html)
29
+ page.html
30
+ end
31
+
32
+ def self.get_results_html(url)
33
+ visit(url)
34
+ sleep(1)
35
+ click_link("Show more matches")
36
+ sleep(2)
37
+ click_link("Show more matches")
38
+ sleep(2)
39
+
40
+ url_array = strip_url(url)
41
+ save_as_file(url_array, page.html)
42
+ page.html
43
+ end
44
+
45
+ def self.file_path_from(url_array)
46
+ url_array[1] == nil ? "#{FootballNow::DB_PATH}/leagues.html" :
47
+ "#{FootballNow::DB_PATH}/#{url_array[2]}-#{url_array[3]}.html"
48
+ end
49
+
50
+ def self.not_expired?(file_path)
51
+ Time.now - File.mtime(file_path) < FootballNow::TIME_OUT
52
+ end
53
+
54
+ def self.strip_url(url)
55
+ url.gsub("http://", "").split("/")
56
+ end
57
+
58
+ def self.save_as_file(url_array, html)
59
+ leagues_file = open(file_path_from(url_array), "w")
60
+ leagues_file.write(html)
61
+ leagues_file.close
62
+ end
63
+
64
+ def self.return_html(url_array, url)
65
+ url_array[1] == nil ? get_leagues_html(url) : send("get_#{url_array[3]}_html", url)
66
+ end
67
+ end
@@ -0,0 +1,3 @@
1
+ # require "football_now/version"
2
+
3
+ require "environment"
@@ -0,0 +1,14 @@
1
+ module FootballNow
2
+ VERSION = "0.1.4"
3
+
4
+ # Football Now Config options
5
+ #
6
+ # DB_PATH
7
+ # Folder in the directory where scraped HTML pages are saved.
8
+ DB_PATH = "#{File.expand_path("../..", __dir__)}/data"
9
+
10
+ # TIME_OUT
11
+ # The number of seconds that a saved copy of the HTML file is valid for.
12
+ # Default = 24 hours
13
+ TIME_OUT = 86400
14
+ end
data/lib/importer.rb ADDED
@@ -0,0 +1,41 @@
1
+ class FootballNow::Importer
2
+
3
+ def self.generate
4
+ create_leagues
5
+ puts "#{FootballNow::League.all.count} Leagues loaded..."
6
+ create_teams
7
+ puts "#{FootballNow::Team.all.count} Teams loaded..."
8
+ create_matches
9
+ puts "#{FootballNow::Match.all.count} Matches loaded..."
10
+ end
11
+
12
+ def self.create_leagues
13
+ FootballNow::Scraper.scrape_leagues.each do |league|
14
+ FootballNow::League.create_from_hash(league)
15
+ end
16
+ end
17
+
18
+ def self.create_teams
19
+ FootballNow::League.all.each do |league|
20
+ teams_hash(league.league_url).each do |team_hash|
21
+ FootballNow::Team.create_from_hash(team_hash)
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.teams_hash(league_url)
27
+ FootballNow::Scraper.scrape_teams(league_url)
28
+ end
29
+
30
+ def self.create_matches
31
+ FootballNow::League.all.each do |league|
32
+ matches_hash(league.league_url).each do |match_hash|
33
+ FootballNow::Match.create_from_hash(match_hash)
34
+ end
35
+ end
36
+ end
37
+
38
+ def self.matches_hash(league_url)
39
+ FootballNow::Scraper.scrape_matches(league_url)
40
+ end
41
+ end
data/lib/league.rb ADDED
@@ -0,0 +1,62 @@
1
+ class FootballNow::League
2
+
3
+ attr_accessor :name, :league_url, :teams
4
+
5
+ @@all = []
6
+
7
+ def initialize(name, league_url)
8
+ @name = name
9
+ @league_url = league_url
10
+ @teams = []
11
+ end
12
+
13
+ def save
14
+ @@all << self
15
+ self
16
+ end
17
+
18
+ def add_team(team)
19
+ team.league ||= self
20
+ @teams << team unless @teams.include? team
21
+ end
22
+
23
+ def matches
24
+ @teams.map { |team| team.matches }.flatten.uniq
25
+ end
26
+
27
+ def get_standings
28
+ @teams.sort {|a, b| a.standing.to_i <=> b.standing.to_i }
29
+ end
30
+
31
+ def current_round
32
+ FootballNow::Match.most_recent_round_number(self)
33
+ end
34
+
35
+ def self.find_by_name(name)
36
+ self.all.detect {|league| league.name.downcase == name.downcase}
37
+ end
38
+
39
+ def self.new_from_hash(league_hash)
40
+ new(league_hash[:name], league_hash[:league_url])
41
+ end
42
+
43
+ def self.create_from_hash(league_hash)
44
+ new_from_hash(league_hash).tap(&:save)
45
+ end
46
+
47
+ def self.all
48
+ @@all
49
+ end
50
+
51
+ def self.print_leagues
52
+ self.all.each.with_index(1) {|league, index| puts "#{index}. #{league.name}"}
53
+ end
54
+
55
+ def self.get_league_by_index(index)
56
+ self.all[index]
57
+ end
58
+
59
+ def self.reset
60
+ @@all.clear
61
+ end
62
+ end
data/lib/match.rb ADDED
@@ -0,0 +1,47 @@
1
+ class FootballNow::Match
2
+
3
+ attr_accessor :round, :date, :home_score, :away_score
4
+ attr_reader :home_team, :away_team
5
+
6
+ @@all = []
7
+
8
+ def initialize(opt = {})
9
+ opt.each {|method, arg| send("#{method}=", arg) if respond_to?("#{method}=") }
10
+ end
11
+
12
+ def home_team=(team)
13
+ @home_team = team
14
+ team.add_match(self, 'home_team')
15
+ end
16
+
17
+ def away_team=(team)
18
+ @away_team = team
19
+ team.add_match(self, 'away_team')
20
+ end
21
+
22
+ def league
23
+ @home_team.league
24
+ end
25
+
26
+ def self.create_from_hash(match_hash)
27
+ new(match_hash).tap(&:save)
28
+ end
29
+
30
+ def save
31
+ @@all << self
32
+ self
33
+ end
34
+
35
+ def self.all
36
+ @@all
37
+ end
38
+
39
+ def self.get_recent_results(league)
40
+ round_number = most_recent_round_number(league)
41
+ league.matches.select {|match| match.round == round_number}
42
+ end
43
+
44
+ def self.most_recent_round_number(league)
45
+ league.matches.max {|a,b| a.round <=> b.round}.round
46
+ end
47
+ end
data/lib/scraper.rb ADDED
@@ -0,0 +1,86 @@
1
+ class FootballNow::Scraper
2
+
3
+ extend Capybara::DSL
4
+
5
+ BASE_URL = "http://www.soccer24.com"
6
+ LEAGUES = [
7
+ "Premier League", "Primera Division",
8
+ "Bundesliga", "Serie A"
9
+ ]
10
+
11
+ def self.scrape_leagues
12
+ doc = FootballNow::DB.get_html(BASE_URL)
13
+ league_list = Nokogiri::HTML(doc).css('.left-menu').first.css('ul li')
14
+
15
+ league_list.map do |row|
16
+ href = row.css('a').attribute('href').value
17
+ league = row.css('a').text
18
+ team_hash = {name: league, league_url: "#{BASE_URL}#{href}"}
19
+
20
+ LEAGUES.include?(league) ? team_hash : nil
21
+ end.compact
22
+ end
23
+
24
+ def self.scrape_teams(league_url)
25
+ doc = FootballNow::DB.get_html(get_standings_page_url(league_url))
26
+ standings_page = Nokogiri::HTML(doc)
27
+ standings = standings_page.css('table#table-type-1 tbody tr')
28
+ league = standings_page.css('.tournament-name').text
29
+
30
+ standings.map do |row|
31
+ goals_for_against = row.css('.goals').first.text.split(':')
32
+ team_hash = {
33
+ name: row.css('.participant_name .team_name_span').text,
34
+ league: FootballNow::League.find_by_name(league),
35
+ wins: row.css('.wins').text,
36
+ draws: row.css('.draws').text,
37
+ losses: row.css('.losses').text,
38
+ standing: row.css('.rank').text.chomp('.'),
39
+ goals_for: goals_for_against[0],
40
+ goals_against: goals_for_against[1],
41
+ points: row.css('.goals')[1].text
42
+ }
43
+ end
44
+ end
45
+
46
+ def self.scrape_matches(league_url)
47
+ doc = FootballNow::DB.get_html(get_matches_page_url(league_url))
48
+ matches_page = Nokogiri::HTML(doc)
49
+ rows = matches_page.css('tbody tr')
50
+
51
+ rows.map do |row|
52
+ if row.css('td').first.text[/Round/]
53
+ @@round = row.css('td').first.text.gsub(/Round /, "").to_i
54
+ nil
55
+ elsif row.css('td.time').text.empty?
56
+ nil
57
+ else
58
+ score = row.css('td.score').text.split(':')
59
+ home_team = row.css('td.team-home').text.gsub(/[[:space:]]/, ' ').strip
60
+ away_team = row.css('td.team-away').text.gsub(/[[:space:]]/, ' ').strip
61
+ match_hash = {
62
+ round: @@round,
63
+ date: row.css('td.time').text.strip,
64
+ home_team: FootballNow::Team.find_by_name(home_team),
65
+ away_team: FootballNow::Team.find_by_name(away_team),
66
+ home_score: score[0].gsub(/[[:space:]]/, ' ').strip,
67
+ away_score: score[1].gsub(/[[:space:]]/, ' ').strip
68
+ }
69
+ end
70
+ end.compact
71
+ end
72
+
73
+ private
74
+
75
+ def self.get_standings_page_url(league_url)
76
+ league_page = Nokogiri::HTML(open(league_url))
77
+ href = league_page.css('.page-tabs .ifmenu li a:contains("Standings")').attribute('href').value
78
+ "#{BASE_URL}#{href}"
79
+ end
80
+
81
+ def self.get_matches_page_url(league_url)
82
+ matches_page = Nokogiri::HTML(open(league_url))
83
+ href = matches_page.css('.page-tabs .ifmenu li a:contains("Results")').attribute('href').value
84
+ "#{BASE_URL}#{href}"
85
+ end
86
+ end
data/lib/team.rb ADDED
@@ -0,0 +1,45 @@
1
+ class FootballNow::Team
2
+
3
+ attr_accessor :name, :league, :wins, :losses, :draws, :goals_for,
4
+ :goals_against, :points, :standing
5
+ attr_reader :matches
6
+
7
+ @@all = []
8
+
9
+ def initialize(name, opt={})
10
+ @name = name
11
+ @matches = []
12
+ opt.each {|method, arg| send("#{method}=", arg) if self.respond_to?("#{method}=")}
13
+ end
14
+
15
+ def save
16
+ @@all << self
17
+ self
18
+ end
19
+
20
+ def league=(league)
21
+ @league = league
22
+ league.add_team(self)
23
+ end
24
+
25
+ def add_match(match, key)
26
+ match.send("#{key}=", self) unless match.send(key)
27
+ @matches << match
28
+ end
29
+
30
+ def self.find_by_name(team_name)
31
+ @@all.detect {|team| team.name.downcase == team_name.downcase}
32
+ end
33
+
34
+ def self.create_from_hash(team_data)
35
+ team = new(team_data[:name], team_data).tap(&:save)
36
+ end
37
+
38
+ def self.all
39
+ @@all
40
+ end
41
+
42
+ def self.reset
43
+ @@all.clear
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: football_now
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - gnfisher
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: require_all
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: capybara
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: poltergeist
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Scraping a popular football site, this gem allows you to navigate the
112
+ standings, results, and stats of the teams in Europe's top competitions.
113
+ email:
114
+ - me@gnfisher.com
115
+ executables:
116
+ - football_now
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - ".gitignore"
121
+ - ".rspec"
122
+ - ".travis.yml"
123
+ - Gemfile
124
+ - LICENSE.txt
125
+ - README.md
126
+ - Rakefile
127
+ - bin/console
128
+ - bin/football_now
129
+ - bin/setup
130
+ - config/environment.rb
131
+ - data/.gitignore
132
+ - exe/football_now
133
+ - football_now.gemspec
134
+ - lib/cli.rb
135
+ - lib/db.rb
136
+ - lib/football_now.rb
137
+ - lib/football_now/version.rb
138
+ - lib/importer.rb
139
+ - lib/league.rb
140
+ - lib/match.rb
141
+ - lib/scraper.rb
142
+ - lib/team.rb
143
+ homepage: http://gnfisher.com
144
+ licenses:
145
+ - MIT
146
+ metadata:
147
+ allowed_push_host: https://rubygems.org
148
+ post_install_message:
149
+ rdoc_options: []
150
+ require_paths:
151
+ - lib
152
+ - config
153
+ - data
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ requirements: []
165
+ rubyforge_project:
166
+ rubygems_version: 2.4.8
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: Get standings, results and stats on the top four European leagues from your
170
+ command line.
171
+ test_files: []