crowd_finder 0.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: 70826c47d3675b7abbc6e1c0cf6ad55cba6c2d94
4
+ data.tar.gz: b6a01b53df7d5c1bebe4b85142da1f5c14d9b229
5
+ SHA512:
6
+ metadata.gz: bddb08a1602e106b7976aa20026ea098612af030c37fdd1cb29525a3a9435894a8efb976b1e7db5940219e8cabe5aff2cd8b3b636f40f881c888a370d3f28157
7
+ data.tar.gz: 4be035ccbd91d26a145d2128c488c54258b488c2140e71fcf42ad7395df2015911afe45dcb8fe006654c364a2a215385244247ca0c3de797ef583e2633855c7e
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "crowd_finder"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Daniel Ziv"]
9
+ spec.email = ["Daniel@shake.cards"]
10
+ spec.description = %q{Get all the data you need from crowdfunding campaigns}
11
+ spec.summary = %q{Crowd funding sites scraper}
12
+ spec.homepage = "https://github.com/DanielRasta/crowd_finder"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency 'json'
21
+ spec.add_development_dependency 'time'
22
+ spec.add_development_dependency 'open-uri'
23
+ spec.add_development_dependency 'open_uri_redirections'
24
+ spec.add_development_dependency 'nokogiri'
25
+ spec.add_development_dependency 'uri'
26
+
27
+ end
@@ -0,0 +1,26 @@
1
+ ###
2
+ # Influenced by this great tutorial
3
+ # http://metabates.com/2011/02/07/building-interfaces-and-abstract-classes-in-ruby/
4
+ ###
5
+
6
+ module AbstractInterface
7
+
8
+ class InterfaceNotImplementedError < NoMethodError
9
+ end
10
+
11
+ def self.included(klass)
12
+ klass.send(:include, AbstractInterface::Methods)
13
+ klass.send(:extend, AbstractInterface::Methods)
14
+ end
15
+
16
+ module Methods
17
+
18
+ def api_not_implemented(klass)
19
+ caller.first.match(/in \`(.+)\'/)
20
+ method_name = $1
21
+ raise AbstractInterface::InterfaceNotImplementedError.new("#{klass.class.name} needs to implement '#{method_name}' for interface #{self.name}!")
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,80 @@
1
+ require "abstract_interface"
2
+ require "sites_module"
3
+ require 'json'
4
+ require 'time'
5
+
6
+ class BaseFinder
7
+ include AbstractInterface
8
+
9
+ # Members
10
+
11
+ @url = ""
12
+ @body = ""
13
+
14
+ # Base
15
+
16
+ def set(new_value)
17
+ @url = new_value
18
+ @body = Sites::get_html(new_value)
19
+ end
20
+
21
+ def reload
22
+ @body = Sites::get_html(@url)
23
+ end
24
+
25
+ def to_json
26
+ my_hash = {:name => project_name,
27
+ :precentage => precentage,
28
+ :deadline => deadline,
29
+ :days_to_go => days_to_go,
30
+ :backers_count => num_of_backers,
31
+ :twitter_link => twitter_link,
32
+ :pledged => pledged,
33
+ :goal => goal}
34
+ return JSON.generate(my_hash)
35
+ rescue => e
36
+ ""
37
+ end
38
+
39
+ # Calculated
40
+
41
+ def precentage
42
+ p = pledged.gsub!(/[^0-9A-Za-z]/, '').to_f
43
+ g = goal.gsub!(/[^0-9A-Za-z]/, '').to_f
44
+ ((p/g)*100).round
45
+ rescue => e
46
+ ""
47
+ end
48
+
49
+ def days_to_go
50
+ ((deadline - Time.new)/(60*60*24)).floor
51
+ rescue => e
52
+ ""
53
+ end
54
+
55
+ # Implementation
56
+
57
+ def project_name
58
+ BaseFinder.api_not_implemented(self)
59
+ end
60
+
61
+ def num_of_backers
62
+ BaseFinder.api_not_implemented(self)
63
+ end
64
+
65
+ def twitter_link
66
+ BaseFinder.api_not_implemented(self)
67
+ end
68
+
69
+ def pledged
70
+ BaseFinder.api_not_implemented(self)
71
+ end
72
+
73
+ def test_print
74
+ BaseFinder.api_not_implemented(self)
75
+ end
76
+
77
+ def goal
78
+ BaseFinder.api_not_implemented(self)
79
+ end
80
+ end
@@ -0,0 +1,17 @@
1
+ # CrowdFinder.new('http://www.headstart.co.il/project.aspx?id=18568')
2
+
3
+
4
+ require "finders_factory"
5
+ require "sites_module"
6
+
7
+
8
+ module CrowdFinder
9
+ def self.new(url)
10
+ unless Sites::valid?(url)
11
+ raise "#{url} is invalid URL"
12
+ else
13
+ site_name = Sites::get_site_name(url)
14
+ findr = FindersFactory.build(site_name.to_sym,url)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require "kickstarter_finder"
2
+ require "headstart_finder"
3
+
4
+ class FindersFactory
5
+
6
+ def self.build(p_shape,p_url)
7
+ case p_shape
8
+ when :kickstarter
9
+ ret_class = KickstarterFinder.new
10
+ when :headstart
11
+ ret_class = HeadstartFinder.new
12
+ end
13
+
14
+ ret_class.set(p_url)
15
+ return ret_class
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ require 'base_finder'
2
+
3
+ class HeadstartFinder < BaseFinder
4
+
5
+ def test_print
6
+ "I'm #{self.class.name} and my url is #{@url}"
7
+ rescue => e
8
+ ""
9
+ end
10
+
11
+ def project_name
12
+ @body.css('.leftpanel')[0].css('h1').text.gsub("\n", ' ').squeeze(' ')
13
+ rescue => e
14
+ ""
15
+ end
16
+
17
+ def days_to_go
18
+ @body.css('.projectstatus').css('.bb').css('.l').css('div')[0].text.gsub("\n", ' ').gsub("\r", ' ').squeeze(' ')
19
+ rescue => e
20
+ ""
21
+ end
22
+
23
+ def deadline
24
+ "N/A"
25
+ end
26
+
27
+ def num_of_backers
28
+ @body.css('.projectstatus').css('.bb').css('.r').css('.t1').text.gsub("\n", ' ').gsub("\r", ' ').squeeze(' ')
29
+ rescue => e
30
+ ""
31
+ end
32
+
33
+ def twitter_link
34
+ ""
35
+ end
36
+
37
+ def pledged
38
+ @body.css('.projectstatus').css('.cu').text.gsub('\n', '').gsub("\n", ' ').gsub("\r", ' ').squeeze(' ')
39
+ rescue => e
40
+ ""
41
+ end
42
+
43
+ def goal
44
+ @body.css('.projectstatus').css('.pl').text.gsub('\n', '').gsub("\n", ' ').gsub("\r", ' ').squeeze(' ')
45
+ rescue => e
46
+ ""
47
+ end
48
+
49
+ end
@@ -0,0 +1,48 @@
1
+ require 'base_finder'
2
+
3
+ class KickstarterFinder < BaseFinder
4
+
5
+ def test_print
6
+ "I'm #{self.class.name} and my url is #{@url}"
7
+ rescue => e
8
+ ""
9
+ end
10
+
11
+ def project_name
12
+ @body.css('title')[0].text
13
+ rescue => e
14
+ ""
15
+ end
16
+
17
+ def num_of_backers
18
+ @body.css('div#backers_count').text.to_i
19
+ rescue => e
20
+ ""
21
+ end
22
+
23
+ def twitter_link
24
+ @body.css('.js-twitter-share')[0]['href']
25
+ rescue => e
26
+ ""
27
+ end
28
+
29
+ def pledged
30
+ @body.css('.stat-item')[1].css('data').text
31
+ rescue => e
32
+ ""
33
+ end
34
+
35
+ def goal
36
+ @body.css('.stat-item')[1].css('.money').text
37
+ rescue => e
38
+ ""
39
+ end
40
+
41
+ # Override
42
+
43
+ def deadline
44
+ Time.parse(@body.css('.ksr_page_timer')[0]["data-end_time"])
45
+ rescue => e
46
+ ""
47
+ end
48
+ end
@@ -0,0 +1,34 @@
1
+ ###
2
+ # Good guide
3
+ # http://ruby.bastardsbook.com/chapters/html-parsing/
4
+ ###
5
+
6
+ require 'open-uri'
7
+ require 'open_uri_redirections'
8
+ require 'nokogiri'
9
+ require 'uri'
10
+
11
+
12
+ module Sites
13
+ def self.get_html(p_url)
14
+ if valid?(p_url)
15
+ source = open(p_url, :allow_redirections => :safe){|f|f.read}
16
+ page = Nokogiri::HTML(source)
17
+ end
18
+ end
19
+
20
+ def self.valid?(url)
21
+ uri = URI.parse(url)
22
+ uri.kind_of?(URI::HTTP)
23
+ rescue URI::InvalidURIError
24
+ false
25
+ end
26
+
27
+ def self.get_site_name(url)
28
+ full_url = URI.parse(url).host.downcase
29
+ full_url.split(".")[1].downcase
30
+ rescue URI::InvalidURIError
31
+ ""
32
+ end
33
+
34
+ end
data/test/test.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "crowd_finder"
2
+ puts CrowdFinder.new('http://www.headstart.co.il/project.aspx?id=18568').to_json
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crowd_finder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Ziv
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: time
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: open-uri
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: open_uri_redirections
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
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: nokogiri
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
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: uri
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Get all the data you need from crowdfunding campaigns
98
+ email:
99
+ - Daniel@shake.cards
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - crowd_finder..gemspec
105
+ - lib/abstract_interface.rb
106
+ - lib/base_finder.rb
107
+ - lib/crowd_finder.rb
108
+ - lib/finders_factory.rb
109
+ - lib/headstart_finder.rb
110
+ - lib/kickstarter_finder.rb
111
+ - lib/sites_module.rb
112
+ - test/test.rb
113
+ homepage: https://github.com/DanielRasta/crowd_finder
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.0.14
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Crowd funding sites scraper
137
+ test_files:
138
+ - test/test.rb