schedule-scraper 0.4.0 → 0.5.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
@@ -1,12 +1,14 @@
1
1
  # ScheduleScraper
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/johnallen3d/schedule-scrape.png?branch=master)](http://travis-ci.org/johnallen3d/schedule-scrape)
4
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/johnallen3d/schedule-scrape)
4
5
 
5
6
  A web calendar scraper for sites that do not provid portable (csv, i-cal etc) version.
6
7
 
7
8
  Supported schedule sites:
8
9
 
9
10
  * [PointStreak](http://pointstreak.com)
11
+ * [EZFacility](http://www.ezfacility.com/)
10
12
 
11
13
  Supported output formats:
12
14
 
@@ -31,8 +33,6 @@ Or install it yourself as:
31
33
 
32
34
  ## Usage
33
35
 
34
- ### Pointstreak Example
35
-
36
36
  Locate the printable version of the scheulde:
37
37
 
38
38
  1. Visit the leagues home page
@@ -43,7 +43,15 @@ Locate the printable version of the scheulde:
43
43
  Request a schedule:
44
44
 
45
45
  url = "http://www.pointstreak.com/players/print/players-team-schedule.html?teamid=385368&seasonid=9162"
46
- schedule = ScheduleScraper.fetch(:pointstreak, url)
46
+ schedule = ScheduleScraper.fetch(:pointstreak, url)
47
+
48
+ or
49
+
50
+ url = "http://pinevilleice.ezleagues.ezfacility.com/teams/1026121/The-Schwartz.aspx"
51
+ schedule = ScheduleScraper.fetch(:ezleagues, url)
52
+
53
+ then
54
+
47
55
 
48
56
  Export the schedule:
49
57
 
@@ -59,11 +67,11 @@ or
59
67
 
60
68
  ## TODO
61
69
 
62
- 1. Add other schedule types: ezleagues
70
+ 1. Add other schedule types
63
71
 
64
72
  ## Why?
65
73
 
66
- To scratch an itch. I play on a couple of ice hockey teams and the rinks these sites to manage leagues and schedules. These sites do not offer any options for exporing and I got tired of updating my schedule manually every couple of months.
74
+ To scratch an itch. I play on a couple of ice hockey teams and the rinks use these sites to manage leagues and schedules. These sites do not offer any options for exporing and I got tired of updating my schedule manually every couple of months.
67
75
 
68
76
  ## Contributing
69
77
 
@@ -8,6 +8,8 @@ require "schedule-scraper/event"
8
8
  require "schedule-scraper/schedule"
9
9
  require "schedule-scraper/pointstreak/event"
10
10
  require "schedule-scraper/pointstreak/schedule"
11
+ require "schedule-scraper/ezleagues/event"
12
+ require "schedule-scraper/ezleagues/schedule"
11
13
 
12
14
  module ScheduleScraper
13
15
  def self.fetch(type, url)
@@ -20,12 +22,14 @@ module ScheduleScraper
20
22
  def self.type_class(type)
21
23
  case type
22
24
  when :pointstreak then Pointstreak::Schedule
25
+ when :ezleagues then EZLeagues::Schedule
23
26
  end
24
27
  end
25
28
 
26
29
  def self.supported_schedules
27
30
  [
28
- :pointstreak
31
+ :pointstreak,
32
+ :ezleagues
29
33
  ]
30
34
  end
31
35
 
@@ -4,12 +4,62 @@ module ScheduleScraper
4
4
  def export_fields
5
5
  self.rules.keys
6
6
  end
7
+
8
+ def cleaner; lambda { |value| value.text.strip }; end
7
9
  end
8
10
 
9
11
  def self.included(base)
10
12
  base.extend ClassMethods
11
13
  end
12
14
 
15
+ def title
16
+ "#{home_team} vs. #{away_team}"
17
+ end
18
+
19
+ def all_day?
20
+ false
21
+ end
22
+
23
+ def description
24
+ title
25
+ end
26
+
27
+ def start_date
28
+ Date.parse(date).strftime(date_format)
29
+ end
30
+
31
+ def end_date
32
+ start_date
33
+ end
34
+
35
+ def start_time
36
+ begin
37
+ Time.parse(time)
38
+ time
39
+ rescue
40
+ # looks like an invalid time
41
+ "12:00 PM"
42
+ end
43
+ end
44
+
45
+ # def end_time
46
+ # will default to one hour?
47
+ # end
48
+
49
+ def start_date_time
50
+
51
+ DateTime.strptime "#{start_date} #{start_time}", '%m/%d/%y %H:%M %P'
52
+ end
53
+
54
+ def end_date_time
55
+ # default to 1 hr
56
+ start_date_time.to_time + 3600
57
+ end
58
+
59
+ def private?
60
+ true
61
+ end
62
+
13
63
  def to_csv
14
64
  self.class.export_fields.collect do |field|
15
65
  self.send(field)
@@ -0,0 +1,17 @@
1
+ module ScheduleScraper
2
+ module EZLeagues
3
+ class Event < Nibbler
4
+ include ScheduleScraper::Event
5
+
6
+ element 'td:nth(2)' => :home_team, :with => cleaner
7
+ element 'td:nth(4)' => :away_team, :with => cleaner
8
+ element 'td:first a' => :date, :with => cleaner
9
+ element 'td:nth(5)' => :time, :with => cleaner
10
+ element 'td:nth(6)' => :rink, :with => cleaner
11
+
12
+ def date_format
13
+ "%m/%d/%y"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module ScheduleScraper
2
+ module EZLeagues
3
+ class Schedule < Nibbler
4
+ include ScheduleScraper::Schedule
5
+
6
+ element 'table#ctl00_C_Schedule1_GridView1' => :list do
7
+ elements 'tr:not(.HeaderStyle)' => :event_list, :with => Event
8
+ end
9
+
10
+ def events
11
+ list.event_list #.reject { |event| event.away_team.nil? }
12
+ end
13
+
14
+ private
15
+
16
+ def event_class
17
+ ScheduleScraper::EZLeagues::Event
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -3,53 +3,14 @@ module ScheduleScraper
3
3
  class Event < Nibbler
4
4
  include ScheduleScraper::Event
5
5
 
6
- cleaner = lambda { |value| value.text.strip }
7
-
8
6
  element 'td:first' => :home_team, :with => cleaner
9
7
  element 'td:nth(2)' => :away_team, :with => cleaner
10
8
  element 'td:nth(3)' => :date, :with => cleaner
11
9
  element 'td:nth(4)' => :time, :with => cleaner
12
10
  element 'td:nth(5)' => :rink, :with => cleaner
13
11
 
14
- def title
15
- "#{home_team} vs. #{away_team}"
16
- end
17
-
18
- def start_date
19
- Date.parse(date).strftime("%m/%d/%y")
20
- end
21
-
22
- def end_date
23
- start_date
24
- end
25
-
26
- def start_time
27
- time
28
- end
29
-
30
- # def end_time
31
- # will default to one hour?
32
- # end
33
-
34
- def start_date_time
35
- DateTime.strptime "#{start_date} #{start_time}", '%m/%d/%y %H:%M %P'
36
- end
37
-
38
- def end_date_time
39
- # default to 1 hr
40
- start_date_time.to_time + 3600
41
- end
42
-
43
- def all_day?
44
- false
45
- end
46
-
47
- def description
48
- title
49
- end
50
-
51
- def private?
52
- true
12
+ def date_format
13
+ "%m/%d/%y"
53
14
  end
54
15
  end
55
16
  end
@@ -7,10 +7,6 @@ module ScheduleScraper
7
7
  elements 'tr:not(.fields)' => :event_list, :with => Event
8
8
  end
9
9
 
10
- def self.fetch(url)
11
- parse open(url)
12
- end
13
-
14
10
  def events
15
11
  list.event_list.reject { |event| event.away_team.nil? }
16
12
  end
@@ -4,6 +4,9 @@ require 'ri_cal'
4
4
  module ScheduleScraper
5
5
  module Schedule
6
6
  module ClassMethods
7
+ def fetch(url)
8
+ parse open(url)
9
+ end
7
10
  end
8
11
 
9
12
  def self.included(base)
@@ -1,3 +1,3 @@
1
1
  module ScheduleScraper
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -1,9 +1,98 @@
1
- # require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
2
2
 
3
- # describe ScheduleScraper::Event do
4
- # subject() { ScheduleScraper::Event }
3
+ describe ScheduleScraper::Event do
4
+ subject() { EventTest.new }
5
5
 
6
- # it "uses elements to define fields for csv" do
7
- # subject.send(:export_fields).must_equal subject.rules.keys
8
- # end
9
- # end
6
+ let(:expected_values) {
7
+ {
8
+ :home_team => "home team",
9
+ :away_team => "away team",
10
+ :date => "01/01/2013",
11
+ :time => "09:00 PM"
12
+ }
13
+ }
14
+
15
+ describe "output helper methods" do
16
+ it "defines a title" do
17
+ expected = "#{expected_values[:home_team]} vs. #{expected_values[:away_team]}"
18
+ subject.title.must_equal expected
19
+ end
20
+
21
+ it "defines a start date" do
22
+ expected = Date.parse(expected_values[:date]).strftime("%m/%d/%y")
23
+ subject.start_date.must_equal expected
24
+ end
25
+
26
+ it "defines an end date" do
27
+ subject.end_date.must_equal subject.start_date
28
+ end
29
+
30
+ it "defines a start time" do
31
+ subject.start_time.must_equal expected_values[:time]
32
+ end
33
+
34
+ it "defines a description" do
35
+ subject.description.must_equal subject.title
36
+ end
37
+
38
+ it "defines all day event" do
39
+ subject.all_day?.must_equal false
40
+ end
41
+
42
+ it "defines all private" do
43
+ subject.private?.must_equal true
44
+ end
45
+ end
46
+
47
+ describe "#to_gcal" do
48
+ it "provides an array ready to export to csv" do
49
+ expected = [
50
+ subject.title,
51
+ subject.start_date,
52
+ subject.start_time,
53
+ subject.end_date,
54
+ "",
55
+ false,
56
+ subject.description,
57
+ "",
58
+ true
59
+ ]
60
+
61
+ subject.to_gcal.must_equal expected
62
+ end
63
+ end
64
+
65
+ describe "#to_ical" do
66
+ it "provides an array ready to export to csv" do
67
+ local_subject = subject
68
+
69
+ RiCal.Calendar do |cal|
70
+ local_subject.to_ical(cal)
71
+ end.must_be_instance_of RiCal::Component::Calendar
72
+ end
73
+
74
+ it "handles invalid times" do
75
+ local_subject = subject
76
+ subject.time = "this is not a date"
77
+
78
+ RiCal.Calendar do |cal|
79
+ local_subject.to_ical(cal)
80
+ end.must_be_instance_of RiCal::Component::Calendar
81
+ end
82
+ end
83
+
84
+ describe "#to_h" do
85
+ it "provides a hash for export" do
86
+ expected = {
87
+ :title => subject.title,
88
+ :start_date => subject.start_date,
89
+ :start_time => subject.start_time,
90
+ :end_date => subject.end_date,
91
+ :all_day => subject.all_day?,
92
+ :description => subject.description
93
+ }
94
+
95
+ subject.to_h.must_equal expected
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../spec_helper'))
2
+
3
+ describe ScheduleScraper::EZLeagues::Event do
4
+ let(:options) { EZ_OPTIONS }
5
+ let(:fields) { [:home_team, :away_team, :date, :time, :rink] }
6
+ let(:expected_values) do
7
+ {
8
+ :home_team => "007",
9
+ :away_team => "The Schwartz",
10
+ :date => "Tue-Sep 11",
11
+ :time => "8:55 PM",
12
+ :rink => "Pineville Ice House"
13
+ }
14
+ end
15
+
16
+ before do
17
+ VCR.use_cassette('schwartz_summer_2012') do
18
+ @schedule = ScheduleScraper::EZLeagues::Schedule.fetch(options)
19
+ end
20
+ end
21
+
22
+ subject() { @schedule.events.last }
23
+
24
+ [:home_team, :away_team, :date, :time, :rink].each do |field|
25
+ it "can find the #{field.to_s.gsub('_', ' ')}" do
26
+ subject.send(field).wont_be_nil
27
+ end
28
+ end
29
+
30
+ it "uses elements to define fields for csv" do
31
+ klass = ScheduleScraper::EZLeagues::Event
32
+ klass.send(:export_fields).must_equal expected_values.keys
33
+ end
34
+
35
+ it "returns a list of fields when you ask for csv" do
36
+ subject.to_csv.must_equal expected_values.values
37
+ end
38
+ end
39
+
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../spec_helper'))
2
+
3
+ describe ScheduleScraper::EZLeagues::Schedule do
4
+ subject() { ScheduleScraper::EZLeagues::Schedule }
5
+ let(:options) { EZ_OPTIONS }
6
+
7
+ describe "schedule instance" do
8
+ subject() do
9
+ VCR.use_cassette('schwartz_summer_2012') do
10
+ ScheduleScraper::EZLeagues::Schedule.fetch(options)
11
+ end
12
+ end
13
+
14
+ it "returns an instance of itself" do
15
+ subject.must_be_instance_of ScheduleScraper::EZLeagues::Schedule
16
+ end
17
+
18
+ it "finds an event list" do
19
+ subject.list.wont_be_nil
20
+ end
21
+
22
+ it "has a list of events" do
23
+ subject.events.must_be_instance_of Array
24
+ subject.events.length.must_equal 13
25
+ end
26
+ end
27
+ end
28
+
29
+