osu-cc-scraper 1.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f3a4b341ef148c517c8e0bce60cd66b5626fb5bb
4
+ data.tar.gz: be876d5f07610468ae75ea6c96d864faeeb42cef
5
+ SHA512:
6
+ metadata.gz: b33d730a9e4dccbe85477dbbd02137cdbd23feea22b67d1355eb6003d3ab066fe7da2d46a9a1a6fa94f878dc696595ea33146bac8d9ef7b296f460758d6cd728
7
+ data.tar.gz: 8073fa241a16ffd2553e0e9a5049c394fef00ddf5c2b8aa7091856e00a04ca0ffb6d500a47deec7439c2208a6a8e932fb1bd3148ac8156584997595bdcbcb38d
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "osu-cc-scraper"
4
+ require "csv"
5
+
6
+ OsuCcScraper::Department.all.each do |department|
7
+ department.courses.each do |course|
8
+ course.sections.each do |section|
9
+ $stdout.puts(section.to_a.to_csv)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,37 @@
1
+ require "open-uri"
2
+ require "nokogiri"
3
+ require "osu-cc-scraper/section"
4
+
5
+ class OsuCcScraper::Course
6
+ attr_accessor :subject_code
7
+ attr_accessor :course_number
8
+
9
+ def initialize(args)
10
+ args.each do |k,v|
11
+ instance_variable_set("@#{k}", v) unless v.nil?
12
+ end
13
+ end
14
+
15
+ def sections
16
+ html = OsuCcScraper::Section::fetch(self.subject_code, self.course_number)
17
+ OsuCcScraper::Section::parse(html)
18
+ end
19
+
20
+ private
21
+
22
+ def self.fetch(subject_code)
23
+ open("#{OsuCcScraper::ENDPOINT}/CourseList.aspx?subjectcode=#{subject_code}&level=undergrad&campus=corvallis").read
24
+ end
25
+
26
+ def self.parse(html)
27
+ ng = Nokogiri::HTML(html)
28
+ ng.css("tr td strong a:last").map{ |course|
29
+ uri = course.attribute('href').to_s.gsub('CourseDetail.aspx?', '')
30
+ params = URI.decode_www_form(uri).to_h
31
+ OsuCcScraper::Course.new({
32
+ subject_code: params["subjectcode"],
33
+ course_number: params["coursenumber"]
34
+ })
35
+ }
36
+ end
37
+ end
@@ -0,0 +1,40 @@
1
+ require "open-uri"
2
+ require "nokogiri"
3
+ require "osu-cc-scraper/course"
4
+
5
+ class OsuCcScraper::Department
6
+ attr_accessor :subject_code
7
+
8
+ def initialize(args)
9
+ args.each do |k,v|
10
+ instance_variable_set("@#{k}", v) unless v.nil?
11
+ end
12
+ end
13
+
14
+ def self.all
15
+ html = OsuCcScraper::Department::fetch
16
+ OsuCcScraper::Department::parse(html)
17
+ end
18
+
19
+ def courses
20
+ html = OsuCcScraper::Course::fetch(self.subject_code)
21
+ OsuCcScraper::Course::parse(html)
22
+ end
23
+
24
+ private
25
+
26
+ def self.fetch
27
+ open("#{OsuCcScraper::ENDPOINT}/CourseDescription.aspx?level=undergrad").read
28
+ end
29
+
30
+ def self.parse(html)
31
+ ng = Nokogiri::HTML(html)
32
+ ng.xpath("//tr/td/font/a").map{ |department|
33
+ OsuCcScraper::Department.new({
34
+ subject_code: department.content[/\(.*?\)/][1..-2]
35
+ })
36
+ }.sort { |a,b|
37
+ a.subject_code.downcase <=> b.subject_code.downcase
38
+ }
39
+ end
40
+ end
@@ -0,0 +1,64 @@
1
+ require "open-uri"
2
+ require "nokogiri"
3
+
4
+ class OsuCcScraper::Section
5
+ attr_accessor :department
6
+ attr_accessor :number
7
+ attr_accessor :name
8
+ attr_accessor :term
9
+ attr_accessor :section
10
+ attr_accessor :instructor
11
+ attr_accessor :type
12
+ attr_accessor :status
13
+ attr_accessor :capacity
14
+ attr_accessor :availability
15
+
16
+ def initialize(args)
17
+ args.each do |k,v|
18
+ instance_variable_set("@#{k}", v) unless v.nil?
19
+ end
20
+ end
21
+
22
+ def to_a
23
+ [@department, @number, @name, @term, @section, @instructor, @type, @status, @capacity, @availability]
24
+ end
25
+
26
+ private
27
+
28
+ def self.fetch(subject_code, course_number)
29
+ open("#{OsuCcScraper::ENDPOINT}/CourseDetail.aspx?subjectcode=#{subject_code}&coursenumber=#{course_number}").read
30
+ end
31
+
32
+ def self.parse(html)
33
+ sections = []
34
+
35
+ ng = Nokogiri::HTML(html)
36
+ rows = ng.xpath('//table[@id="ctl00_ContentPlaceHolder1_SOCListUC1_gvOfferings"]/tr[position() > 1]')
37
+ rows.each_with_index do |row, key|
38
+ title = ng.at_xpath('//form/h3').content.split("\n")
39
+ query = "//table[@id='ctl00_ContentPlaceHolder1_SOCListUC1_gvOfferings']"
40
+
41
+ sections << OsuCcScraper::Section.new({
42
+ :department => title[2].delete("\r\n").strip[0..-2].split(" ")[0],
43
+ :number => title[2].split(" ")[1][0..-2],
44
+ :name => title[3].strip,
45
+ :term => at_xpath_or_null(ng, "#{query}/tr[position() = #{key+2}]/td[position() = 1]"),
46
+ :section => at_xpath_or_null(ng, "#{query}/tr[position() = #{key+2}]/td[position() = 3]"),
47
+ :instructor => at_xpath_or_null(ng, "#{query}/tr[position() = #{key+2}]/td[position() = 6]"),
48
+ :type => at_xpath_or_null(ng, "#{query}/tr[position() = #{key+2}]/td[position() = 11]"),
49
+ :status => at_xpath_or_null(ng, "#{query}/tr[position() = #{key+2}]/td[position() = 12]"),
50
+ :capacity => at_xpath_or_null(ng, "#{query}/tr[position() = #{key+2}]/td[position() = 13]"),
51
+ :availability => at_xpath_or_null(ng, "#{query}/tr[position() = #{key+2}]/td[position() = 14]")
52
+ })
53
+ end
54
+ sections
55
+ end
56
+
57
+ def self.at_xpath_or_null(document, selector)
58
+ if document.at_xpath(selector) != nil
59
+ return document.at_xpath(selector).content.delete("\r\n").strip
60
+ else
61
+ return nil
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ class OsuCcScraper
2
+ ENDPOINT = "http://catalog.oregonstate.edu"
3
+ end
4
+
5
+ require "osu-cc-scraper/department"
6
+ require "osu-cc-scraper/course"
7
+ require "osu-cc-scraper/section"
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: osu-cc-scraper
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jonah George
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.6.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.6.2
27
+ description: A script to gather course data from Oregon State's Course Catalog.
28
+ email: jonah.george@me.com
29
+ executables:
30
+ - osu-cc-scraper
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - bin/osu-cc-scraper
35
+ - lib/osu-cc-scraper.rb
36
+ - lib/osu-cc-scraper/course.rb
37
+ - lib/osu-cc-scraper/department.rb
38
+ - lib/osu-cc-scraper/section.rb
39
+ homepage: https://github.com/jonahgeorge/osu-cc-scraper
40
+ licenses:
41
+ - MIT
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.4.8
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: OSU Course Catalog Scraper
63
+ test_files: []