sfcsfs 0.1.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.
@@ -0,0 +1,5 @@
1
+ .*.swp
2
+ .*.swo
3
+ *~
4
+ Gemfile.lock
5
+ pkg/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sfcsfs.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 ymrl
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,52 @@
1
+ # SFCSFS
2
+
3
+ SFCSFS is a SFC-SFS Scraping Library. SFC-SFS is an internal website for Keio Univ. Shounan Fujisawa Campus.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'sfcsfs'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install sfcsfs
18
+
19
+ ## Usage
20
+
21
+ config = Pit.get("sfcsfs", :require => {
22
+ :account => "your CNS account",
23
+ :password => "your CNS password"
24
+ })
25
+
26
+ # Login to SFC-SFS
27
+ agent = SFCSFS.login(config[:account],config[:password])
28
+
29
+ # Get all classes of this semester and shows
30
+ # It takes several minutes...
31
+ list = agent.all_classes_of_this_semester
32
+
33
+ # Show name of these
34
+ list.each do |e|
35
+ puts e.title
36
+ end
37
+
38
+ # Get your current weekly schedule
39
+ list = agent.my_schedule
40
+
41
+ # Show name of these
42
+ list.each do |e|
43
+ puts e.title
44
+ end
45
+
46
+ ## Contributing
47
+
48
+ 1. Fork it
49
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
50
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
51
+ 4. Push to the branch (`git push origin my-new-feature`)
52
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ #coding:utf-8
2
+ require 'rake'
3
+ $:.unshift File.join(File.dirname(__FILE__),'lib')
4
+
5
+ require 'rspec/core'
6
+ require 'rspec/core/rake_task'
7
+ require "bundler/gem_tasks"
8
+
9
+ task :default => :spec
10
+ Dir['tasks/**/*.rake'].each { |t| load t}
@@ -0,0 +1,16 @@
1
+ #coding:utf-8
2
+ $:.unshift(File.dirname(__FILE__)) unless
3
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
+
5
+ directory = File.expand_path(File.dirname(__FILE__))
6
+
7
+ require directory+'/sfcsfs/lecture.rb'
8
+ require directory+'/sfcsfs/homework.rb'
9
+ require directory+'/sfcsfs/util.rb'
10
+ require directory+'/sfcsfs/agent.rb'
11
+ require directory+'/sfcsfs/agent/navigations.rb'
12
+
13
+
14
+ module SFCSFS
15
+ VERSION = '0.1.0'
16
+ end
@@ -0,0 +1,88 @@
1
+ #coding:utf-8
2
+ require 'nokogiri'
3
+ require 'uri'
4
+ require 'net/https'
5
+ require 'addressable/uri'
6
+
7
+ module SFCSFS
8
+ REDIRECT_LIMIT = 5
9
+
10
+ class Agent
11
+
12
+ def inspect
13
+ "#{self.class} #{@id}"
14
+ end
15
+
16
+ def request uri,method=:get,data={}
17
+ ret = nil
18
+ count = 0
19
+ while count < REDIRECT_LIMIT and !ret or Net::HTTPRedirection === ret
20
+ uri = (URI::Generic === uri ? uri : URI.parse(uri))
21
+ req = nil
22
+ uri += '/' if uri.path == ''
23
+ path = uri.path
24
+ path += "?#{uri.query}" if uri.query && uri.query.length > 0
25
+ if method.to_sym == :post
26
+ req = Net::HTTP::Post.new(path)
27
+ else
28
+ req = Net::HTTP::Get.new(path)
29
+ end
30
+ req.set_form_data(data) if data.length > 0
31
+ http = Net::HTTP.new(uri.host,uri.port)
32
+ http.use_ssl = true if uri.scheme == 'https'
33
+ http.start{|http| ret = http.request(req)}
34
+ @uri = uri
35
+ uri = ret['location'] if ret['location']
36
+ count += 0
37
+ end
38
+ if count >= REDIRECT_LIMIT
39
+ raise TooManyRedirectionsException
40
+ end
41
+ return ret
42
+ end
43
+
44
+ def request_parse uri,method=:get,data={}
45
+ uri = (URI::Generic === uri ? uri : URI.parse(uri))
46
+ r = request(uri,method,data)
47
+ @doc = Nokogiri.HTML(SFCSFS.convert_encoding(r.body),nil,'UTF-8')
48
+ if meta = @doc.search('meta[http-equiv=refresh]').first
49
+ match = meta.attr('content').match(/url=(.*)$/)
50
+ if match
51
+ request_parse(@uri+match[1])
52
+ end
53
+ end
54
+ return @doc
55
+ end
56
+
57
+ def initialize
58
+ @uri = nil
59
+ @doc = nil
60
+ @id = nil
61
+ @base_uri = nil
62
+ @type = nil
63
+ return self
64
+ end
65
+
66
+ def Agent.login(account,passwd,options={})
67
+ a = Agent.new
68
+ doc = a.request_parse('https://gc.sfc.keio.ac.jp/sfc-sfs/')
69
+ action = doc.search('form').attr('action')
70
+ a.request_parse(action,:post,:u_login => account, :u_pass => passwd)
71
+ query_values = Addressable::URI.parse(a.uri).query_values
72
+ a.id = query_values['id']
73
+ a.type = query_values['type']
74
+
75
+ if options[:vu9]
76
+ a.base_uri = URI.parse('https://vu9.sfc.keio.ac.jp/')
77
+ else
78
+ a.base_uri = a.uri + '/'
79
+ end
80
+
81
+ return a
82
+ end
83
+ attr_accessor :login,:query_values,:base_uri,
84
+ :doc,:id,:uri,:type
85
+ end
86
+ class TooManyRedirectionsException < Exception
87
+ end
88
+ end
@@ -0,0 +1,97 @@
1
+ #coding:UTF-8
2
+ class SFCSFS::Agent
3
+ def plan_of_this_semester
4
+ get_plans_page_of_this_semester
5
+ plan_list_from_plans_page
6
+ end
7
+
8
+ def plan_of_next_semester
9
+ get_plans_page_of_next_semester
10
+ plan_list_from_plans_page
11
+ end
12
+
13
+ def all_classes_of_this_semester
14
+ get_plans_page_of_this_semester
15
+ all_classes_from_plans_page
16
+ end
17
+
18
+ def all_classes_of_next_semester
19
+ get_plans_page_of_next_semester
20
+ all_classes_from_plans_page
21
+ end
22
+
23
+ def get_plans_page_of_this_semester
24
+ outer_uri = @base_uri +
25
+ "/sfc-sfs/portal_s/s02.cgi?id=#{@id}&type=#{@type}&mode=1&lang=ja"
26
+ request_parse(outer_uri)
27
+ inner_uri = outer_uri + @doc.search('iframe').attr('src').to_s
28
+ request_parse(inner_uri)
29
+ end
30
+
31
+ def get_plans_page_of_next_semester
32
+ outer_uri = @base_uri +
33
+ "/sfc-sfs/portal_s/s02.cgi?id=#{@id}&type=#{@type}&mode=2&lang=ja"
34
+ request_parse(outer_uri)
35
+ inner_uri = outer_uri + @doc.search('iframe').attr('src').to_s
36
+ request_parse(inner_uri)
37
+ end
38
+
39
+ def all_classes_from_plans_page
40
+ list = []
41
+ uri = @uri
42
+ @doc.search('a[href]').to_a.delete_if{|e| !e.attr('href').match(/class_list\.cgi/)}.each do |e|
43
+ request_parse uri+e.attr('href')
44
+ @doc.search('a[href]').to_a.delete_if{|e| !e.attr('href').match(/plan_list\.cgi/)}.each do |e|
45
+ str = e.parent.text
46
+ title = nil
47
+ instructor = nil
48
+ #if match = str.match(/:\d+\(.+?\) …\s?(.+?)\s?\((.+?)\)…/)
49
+ if match = str.match(/:\d+\(.+?\) … (.+?)\s?\(([^\(\)]+?)\)…/u)
50
+ title = match[1]
51
+ instructor = match[2]
52
+ end
53
+ q = Addressable::URI.parse(e.attr('href')).query_values
54
+ ks = q['ks']
55
+ yc = q['yc']
56
+ reg = q['reg']
57
+ term = q['term']
58
+ list.push SFCSFS::Lecture.new(self,title,instructor,:ks=>ks,:yc=>yc,:reg=>reg,:term=>term)
59
+ end
60
+ end
61
+ return list
62
+ end
63
+
64
+ def plan_list_from_plans_page
65
+ @doc.search('a').to_a.delete_if{|e| !e.attributes['href'].match(/syll_view.cgi/)}.map do |e|
66
+ href = e.attributes['href']
67
+ q = Addressable::URI.parse(href).query_values
68
+ ks = q['ks']
69
+ yc = q['yc']
70
+ title = e.children.first.to_s
71
+ SFCSFS::Lecture.new(self,title,nil,:ks=>ks,:yc=>yc)
72
+ end
73
+ end
74
+
75
+ def my_schedule
76
+ outer_uri = @base_uri +
77
+ "/sfc-sfs/portal_s/s01.cgi?id=#{@id}&type=#{@type}&mode=1&lang=ja"
78
+ request_parse outer_uri
79
+ inner_uri = @uri + @doc.search('iframe').attr('src').to_s
80
+ request_parse inner_uri
81
+
82
+ @doc.search('table a[href]').to_a.delete_if{|e|
83
+ !e.attr('href').match(/sfs_class/)
84
+ }.map do |e|
85
+ href = e.attr("href")
86
+ q = Addressable::URI.parse(href).query_values
87
+ option ={}
88
+ option[:ks] = q['ks']
89
+ option[:yc] = q['yc']
90
+ option[:mode] = href.match(/faculty/) ? 'faculty' : 'student'
91
+ title = e.children.first.to_s
92
+ title.gsub!(/\[([^\]]*)\]$/u){option[:place]=$1;""}
93
+ instructor = e.next.next.to_s.gsub(/[()\s ]/u,'')
94
+ SFCSFS::Lecture.new(self,title,instructor,option)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,12 @@
1
+ #coding:utf-8
2
+
3
+ module SFCSFS
4
+ class Homework
5
+ def initialize(title,url)
6
+ @title = title.to_s
7
+ @url = url.to_s
8
+ end
9
+ attr_accessor :title,:url
10
+ end
11
+ end
12
+
@@ -0,0 +1,125 @@
1
+ #coding:utf-8
2
+ module SFCSFS
3
+ class Lecture
4
+ def initialize(agent,title,instructor,config={})
5
+ @agent = agent
6
+ @title = title
7
+ @instructor = instructor
8
+ @instructors = config[:instructors] || []
9
+ @mode = config[:mode]
10
+ @yc = config[:yc]
11
+ @ks = config[:ks]
12
+ @reg = config[:reg]
13
+ @term = config[:term]
14
+ @homeworks = config[:homeworks] || []
15
+ @periods = config[:periods] || []
16
+ @applicants = config[:applicants]
17
+ @limit = config[:limit]
18
+ @place = config[:place]
19
+ end
20
+ def inspect
21
+ "#{self.class} \"#{@title}\" \"#{@instructor}\" #{@yc} #{@ks}"
22
+ end
23
+ def class_top_path
24
+ unless @yc && @ks && @agent.id
25
+ raise NotEnoughParamsException
26
+ end
27
+ mode = 'student'
28
+ file = 's_class_top.cgi'
29
+ if(self.mode == 'faculty')
30
+ mode = 'faculty'
31
+ file = 'f_class_top.cgi'
32
+ end
33
+ return "/sfc-sfs/sfs_class/#{mode}/#{file}?lang=ja&ks=#{@ks}&yc=#{@yc}&id=#{@agent.id}"
34
+ end
35
+ def stay_input_path
36
+ unless @yc && @ks && @agent.id
37
+ raise NotEnoughParamsException
38
+ end
39
+ "/sfc-sfs/sfs_class/stay/stay_input.cgi?yc=#{@yc}&ks=#{@ks}&enc_id=#{@agent.id}"
40
+ end
41
+ def student_selection_path
42
+ unless @yc && @agent.id
43
+ raise NotEnoughParamsException
44
+ end
45
+ "/sfc-sfs/sfs_class/student/view_student_select.cgi?enc_id=#{@agent.id}&yc=#{@yc}&lang=ja"
46
+ end
47
+
48
+ def get_detail
49
+ uri = @agent.base_uri + class_top_path
50
+ doc = @agent.request_parse(uri)
51
+ @title = doc.search('h3.one').first.children.first.to_s.gsub(/[\s ]/,'')
52
+ @instructors += doc.search('h3.one > a[href]').to_a.delete_if{|e| !e.attr('href').match(/profile\.cgi/)}.map{|e|e.children.first.to_s}
53
+ @instructors.uniq!
54
+ term = doc.search('h3.one .ja').text.match(/時限:(\d{4})年([春秋])学期(.*)$/)
55
+ if term
56
+ @term = "#{term[1]}#{term[2] == '春' ? 's' : 'f'}"
57
+ @periods += term[3].gsub(/\s/,'').split(/,/)
58
+ @periods.uniq!
59
+ end
60
+ page = doc.to_s
61
+ #a.doc.search('a').to_a.delete_if{|e|!e.attributes['href'].match(%r{/report/report\.cgi\?})}.each do |e|
62
+ # # TODO : Homeworks Func
63
+ #end
64
+ if m = page.match(/履修希望者数:(\d+)/)
65
+ @applicants = m[1].to_i
66
+ end
67
+ if m = page.match(/受入学生数(予定):約 (\d+) 人/)
68
+ @limit = m[1].to_i
69
+ end
70
+ return self
71
+ end
72
+
73
+ def student_selection_list
74
+ uri = @agent.base_uri + student_selection_path
75
+ doc = @agent.request_parse(uri)
76
+ return doc.search('tr[bgcolor="#efefef"] td').map{|e| e.children.first.to_s}.delete_if{|e| !e.match(/^\d{8}/)}
77
+ end
78
+
79
+ def get_stay_input_page
80
+ uri = @agent.base_uri + stay_input_path
81
+ @agent.request_parse(uri)
82
+ end
83
+ def submit_stay_form data
84
+ param = {}
85
+ uri = @agent.base_uri + '/sfc-sfs/sfs_class/stay/stay_input.cgi'
86
+ unless @yc && @ks && @aget.id
87
+ raise NotEnoughParamsException
88
+ end
89
+ param[:stay_phone] = data[:stay_phone]
90
+ param[:stay_p_phone] = data[:stay_p_phone]
91
+ param[:stay_time] = data[:stay_time]
92
+ param[:selectRoom] = data[:selectRoom]
93
+ param[:selectFloor] = data[:selectFloor]
94
+ param[:stay_room_other] = data[:stay_room_other]
95
+ param[:stay_reason] = data[:stay_reason]
96
+ param[:mode] = 'submit'
97
+ param[:yc] = @yc
98
+ param[:ks] = @ks
99
+ param[:enc_id] = @agent.id
100
+ request uri,:post,data
101
+ end
102
+ def add_to_plan
103
+ unless @reg && @yc && @ks && @agent.id && @term
104
+ raise NotEnoughParamsException
105
+ end
106
+ uri = @agent.base_uri + "/sfc-sfs/sfs_class/student/plan_list.cgi?reg=#{@reg}&yc=#{@yc}&mode=add&ks=#{@ks}&id=#{@agent.id}&term=#{@term}&lang=ja"
107
+ @agent.request(uri)
108
+ end
109
+
110
+ def delete_from_plan
111
+ unless @yc && @ks && @agent.id && @term
112
+ raise NotEnoughParamsException
113
+ end
114
+ uri = @agent.base_uri + "/sfc-sfs/sfs_class/student/plan_list.cgi?reg=#{@reg}&yc=#{@yc}&mode=del&ks=#{@ks}&id=#{@agent.id}&term=#{@term}&lang=ja"
115
+ @agent.request(uri)
116
+ end
117
+
118
+ attr_accessor :title,:instructor,:mode,:yc,:ks,:homeworks,
119
+ :add_list_url,:periods,:applicants,:limit,
120
+ :reg,:term, :place
121
+ end
122
+
123
+ class NotEnoughParamsException < Exception
124
+ end
125
+ end
@@ -0,0 +1,15 @@
1
+ module SFCSFS
2
+ def SFCSFS.login(account,passwd)
3
+ return Agent.login(account,passwd)
4
+ end
5
+
6
+ def SFCSFS.convert_encoding str
7
+ if RUBY_VERSION >= "1.9"
8
+ return str.force_encoding(Encoding::EUC_JP).encode(Encoding::UTF_8,:invalid=>:replace,:undef=>:replace)
9
+ else
10
+ require 'kconv'
11
+ return Kconv.kconv(str,Kconv::UTF8,Kconv::EUC)
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r ./#{File.dirname(__FILE__) + '/../lib/sfcsfs'}"
9
+ libs << " -r ./#{File.dirname(__FILE__) + '/console_helper'}"
10
+ puts "Loading SFCSFS"
11
+ puts "SFCSFS::Agent.login(CONFIG[:account],CONFIG[:password])"
12
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,4 @@
1
+ require 'pit'
2
+ CONFIG = Pit.get("sfcsfs", :require => {
3
+ :account => "your CNS account",
4
+ :password => "your CNS password" })
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/sfcsfs', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["ymrl"]
6
+ gem.email = ["ymrl@ymrl.net"]
7
+ gem.description = %q{SFC-SFS Scraping Library}
8
+ gem.summary = %q{SFC-SFS Scraping Library}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "sfcsfs"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = SFCSFS::VERSION
17
+ gem.add_dependency('nokogiri','~> 1.5.5')
18
+ gem.add_dependency('addressable','~> 2.2.8')
19
+ gem.add_development_dependency('rspec', '~> 2.10.0')
20
+ gem.add_development_dependency('rake')
21
+ gem.add_development_dependency('pit')
22
+ end
@@ -0,0 +1,84 @@
1
+ #coding:utf-8
2
+
3
+ require File.dirname(__FILE__) + '/spec_helper.rb'
4
+ require File.dirname(__FILE__) + '/../lib/sfcsfs.rb'
5
+
6
+ describe 'Agent' do
7
+ before do
8
+ config = Pit.get("sfcsfs", :require => {
9
+ :account => "your CNS account",
10
+ :password => "your CNS password"
11
+ })
12
+ @agent = SFCSFS.login(config[:account],config[:password])
13
+ end
14
+ it 'URLがs01.cgiにいる' do
15
+ @agent.uri.to_s.match(%r!^https://vu.\.sfc\.keio\.ac\.jp/sfc-sfs/portal_s/s01\.cgi.*!).should be_true
16
+ end
17
+
18
+ it 'idがセットされている' do
19
+ @agent.id.should be_true
20
+ end
21
+
22
+ #it '次学期プランページへのアクセス' do
23
+ # @agent.get_plans_page_of_next_semester
24
+ #end
25
+
26
+ #context '次学期プランの履修' do
27
+ # it '科目一覧の取得' do
28
+ # list = @agent.get_class_list_of_next_semester
29
+ # list.each do |e|
30
+ # e.should be_instance_of(SFCSFS::Lecture)
31
+ # e.add_list_url.should be_true
32
+ # end
33
+ # end
34
+ #end
35
+ #it '今学期プランページへのアクセス' do
36
+ # @agent.get_plans_page_of_this_semester
37
+ #end
38
+
39
+ #context '今学期プランの履修' do
40
+ # it '科目一覧の取得' do
41
+ # list = @agent.get_class_list_of_this_semester
42
+ # list.each do |e|
43
+ # e.should be_instance_of(SFCSFS::Lecture)
44
+ # e.add_list_url.should be_true
45
+ # end
46
+ # end
47
+ #end
48
+
49
+
50
+ context 'my時間割にアクセスする' do
51
+ before do
52
+ @lectures = @agent.my_schedule
53
+ end
54
+ it 'Lectureが生成されている' do
55
+ @lectures.each do |e|
56
+ e.should be_instance_of(SFCSFS::Lecture)
57
+ e.instructor.should have_at_least(1).items
58
+ e.yc.should be_true
59
+ e.ks.should be_true
60
+ e.mode.should be_true
61
+ e.homeworks.should be_instance_of(Array)
62
+ end
63
+ end
64
+ #it 'Lectureから残留届けページヘ行ける' do
65
+ # @lectures.each {|e| e.get_stay_input_page(@agent)}
66
+ #end
67
+ it 'Lecture#instructorが括弧とか\sとか含まない' do
68
+ @lectures.each { |e| (e.instructor.match(/[()()\s]/)).should be_false }
69
+ end
70
+ #it 'Lectureそれぞれに詳細情報を取得できる' do
71
+ # @lectures.each do |e| e.get_detail()
72
+ # e.homeworks.each do |h|
73
+ # h.should be_instance_of(SFCSFS::Homework)
74
+ # h.title.should have_at_least(1).items
75
+ # h.title.match(/^「/).should be_false
76
+ # h.title.match(/」$/).should be_false
77
+ # h.url.match(%r{.*\.sfc\.keio\.ac\.jp/sfc-sfs/sfs_class/report/report.cgi\?}).should be_true
78
+ # end
79
+ # end
80
+ #end
81
+ end
82
+ end
83
+
84
+
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,8 @@
1
+ #coding:utf-8
2
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__)))
4
+
5
+ Dir[File.join(File.dirname(__FILE__), "..", "lib", "models", "**/*.rb")].each do |f|
6
+ require f
7
+ end
8
+ require 'pit'
@@ -0,0 +1,49 @@
1
+ require './' + File.dirname(__FILE__) + '/../lib/sfcsfs.rb'
2
+ require 'pit'
3
+ desc "Add All Lectures of Next Semester"
4
+
5
+ task :addnext do
6
+ config = Pit.get("sfcsfs", :require => {
7
+ :account => "your CNS account",
8
+ :password => "your CNS password"
9
+ })
10
+ agent = SFCSFS.login(config[:account],config[:password])
11
+ list = agent.all_classes_of_next_semester
12
+ list.each do |lecture|
13
+ puts "#{lecture.title} (#{lecture.instructor})"
14
+ retry_count = 0
15
+ begin
16
+ lecture.add_to_plan
17
+ rescue
18
+ sleep 60
19
+ retry_count += 1
20
+ if retry_count < 10
21
+ retry
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ desc "Add All Lectures of this Semester"
28
+ task :addall do
29
+ config = Pit.get("sfcsfs", :require => {
30
+ :account => "your CNS account",
31
+ :password => "your CNS password"
32
+ })
33
+ agent = SFCSFS.login(config[:account],config[:password])
34
+ list = agent.all_classes_of_this_semester
35
+ list.each do |lecture|
36
+ puts "#{lecture.title} (#{lecture.instructor})"
37
+ retry_count = 0
38
+ begin
39
+ lecture.add_to_plan
40
+ rescue
41
+ sleep 60
42
+ retry_count += 1
43
+ if retry_count < 10
44
+ retry
45
+ end
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,20 @@
1
+ begin
2
+ require 'rspec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ require 'rspec'
6
+ end
7
+ begin
8
+ require 'rspec/core/rake_task'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ RSpec::Core::RakeTask.new do |t|
18
+ t.rspec_opts = ['--options', "spec/spec.opts"]
19
+ t.pattern = 'spec/**/*_spec.rb'
20
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sfcsfs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - ymrl
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &87235160 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.5.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *87235160
25
+ - !ruby/object:Gem::Dependency
26
+ name: addressable
27
+ requirement: &87234920 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.2.8
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *87234920
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &87234690 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.10.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *87234690
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &87234500 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *87234500
58
+ - !ruby/object:Gem::Dependency
59
+ name: pit
60
+ requirement: &87234270 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *87234270
69
+ description: SFC-SFS Scraping Library
70
+ email:
71
+ - ymrl@ymrl.net
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - Rakefile
81
+ - lib/sfcsfs.rb
82
+ - lib/sfcsfs/agent.rb
83
+ - lib/sfcsfs/agent/navigations.rb
84
+ - lib/sfcsfs/homework.rb
85
+ - lib/sfcsfs/lecture.rb
86
+ - lib/sfcsfs/util.rb
87
+ - script/console
88
+ - script/console_helper.rb
89
+ - script/destroy
90
+ - script/generate
91
+ - sfcsfs.gemspec
92
+ - spec/sfcsfs_agent_spec.rb
93
+ - spec/spec.opts
94
+ - spec/spec_helper.rb
95
+ - tasks/add.rake
96
+ - tasks/rspec.rake
97
+ homepage: ''
98
+ licenses: []
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.11
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: SFC-SFS Scraping Library
121
+ test_files:
122
+ - spec/sfcsfs_agent_spec.rb
123
+ - spec/spec.opts
124
+ - spec/spec_helper.rb