bizratr 0.0.5 → 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.
- data/Gemfile.lock +5 -1
- data/README.rdoc +7 -3
- data/lib/bizratr/business.rb +25 -4
- data/lib/bizratr/connector.rb +80 -32
- data/lib/bizratr/version.rb +1 -1
- metadata +27 -16
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bizratr (0.0
|
4
|
+
bizratr (0.1.0)
|
5
5
|
factual-api
|
6
6
|
foursquare2
|
7
7
|
geocoder
|
8
8
|
google_places
|
9
9
|
google_places
|
10
|
+
koala
|
10
11
|
levenshtein
|
11
12
|
yelpster
|
12
13
|
|
@@ -32,6 +33,9 @@ GEM
|
|
32
33
|
multi_json (~> 1.0)
|
33
34
|
multi_xml
|
34
35
|
json (1.7.5)
|
36
|
+
koala (1.5.0)
|
37
|
+
faraday (~> 0.7)
|
38
|
+
multi_json (~> 1.3)
|
35
39
|
levenshtein (0.2.2)
|
36
40
|
multi_json (1.3.6)
|
37
41
|
multi_xml (0.5.1)
|
data/README.rdoc
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
= BizRatr
|
2
|
-
This gem pulls in business data from a variety of sources and synthesizes a singular view of the business. Right now Yelp, Factual, Google Places, and Foursquare are used as sources. Bizratr will collapse all of the matching sources into a singular view of each matching business.
|
2
|
+
This gem pulls in business data from a variety of sources and synthesizes a singular view of the business. Right now Facebook, Yelp, Factual, Google Places, and Foursquare are used as sources. Bizratr will collapse all of the matching sources into a singular view of each matching business.
|
3
3
|
|
4
4
|
>> require 'bizratr'
|
5
5
|
>> config = {
|
6
6
|
:foursquare => { :client_id => 'anid', :client_secret => 'asecret' },
|
7
7
|
:yelp => { :consumer_key => 'akey', :consumer_secret => 'asecret', :token => 'atoken', :token_secret => 'atokensecret' },
|
8
8
|
:google_places => { :key => "akey" },
|
9
|
-
:factual => { :key => 'akey', :secret => 'asecret' }
|
9
|
+
:factual => { :key => 'akey', :secret => 'asecret' },
|
10
|
+
:facebook => { :key => 'akey', :secret => 'asecret' }
|
10
11
|
}
|
11
|
-
>> finder = BizRatr::
|
12
|
+
>> finder = BizRatr::UberClient.new(config)
|
12
13
|
>> matches = finder.search_location([40.729401, -73.996061], 'third rail coffee')
|
13
14
|
>> puts matches.first.rating
|
14
15
|
=> 4.55
|
15
16
|
>> matches = finder.search_location("240 Sullivan St., New York, NY 10012", 'third rail coffee')
|
16
17
|
>> puts matches.first.rating
|
17
18
|
=> 4.55
|
19
|
+
>> puts matches.first.website_likes
|
20
|
+
=> {"share_count"=>75, "like_count"=>10, "comment_count"=>9, "click_count"=>6}
|
18
21
|
|
19
22
|
|
20
23
|
In this example, the average of the ratings from any of the sources (normalized to a 5 point scale) is used as the rating. Each result has address information, rating information, "like" information, and other relevant info.
|
@@ -25,6 +28,7 @@ You only need to specify the config options for the services you actually want t
|
|
25
28
|
* Google places: https://code.google.com/apis/console/b/0/
|
26
29
|
* Foursquare: https://foursquare.com/oauth/
|
27
30
|
* Factual: https://www.factual.com/api-keys/request
|
31
|
+
* Facebook: https://developers.facebook.com/apps
|
28
32
|
|
29
33
|
See http://findingscience.com/bizratr for more information.
|
30
34
|
|
data/lib/bizratr/business.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
1
3
|
module BizRatr
|
2
4
|
class Business
|
3
|
-
attr_accessor :name, :phone, :address, :state, :country, :zip, :twitter, :ids, :checkins, :users, :likes, :ratings, :review_counts, :coords, :city, :categories
|
5
|
+
attr_accessor :name, :phone, :address, :state, :country, :zip, :twitter, :ids, :checkins, :users, :likes, :ratings, :review_counts, :coords, :city, :categories, :website
|
4
6
|
|
5
|
-
def initialize(lat, lon, name)
|
7
|
+
def initialize(uberclient, lat, lon, name)
|
6
8
|
@ids = {}
|
7
9
|
@checkins = {}
|
8
10
|
@users = {}
|
@@ -12,10 +14,11 @@ module BizRatr
|
|
12
14
|
@categories = {}
|
13
15
|
@coords = [lat, lon]
|
14
16
|
@name = name
|
17
|
+
@uberclient = uberclient
|
15
18
|
end
|
16
19
|
|
17
20
|
def to_s
|
18
|
-
attrs = [:name, :phone, :address, :state, :country, :zip, :twitter, :ids, :checkins, :users, :likes, :ratings, :review_counts, :coords, :city, :categories]
|
21
|
+
attrs = [:name, :phone, :address, :state, :country, :zip, :twitter, :ids, :checkins, :users, :likes, :ratings, :review_counts, :coords, :city, :categories, :website]
|
19
22
|
args = attrs.map { |k| "#{k.to_s}=#{send(k)}" }.join(", ")
|
20
23
|
"<Business [#{args}]>"
|
21
24
|
end
|
@@ -28,6 +31,23 @@ module BizRatr
|
|
28
31
|
@users.values.inject { |a,b| a+b } || 0
|
29
32
|
end
|
30
33
|
|
34
|
+
# Get all of the website like information from Facebook. If there's no website, or an issue, return {} - otherwise
|
35
|
+
# you'll get something of the form {"share_count"=>75, "like_count"=>10, "comment_count"=>9, "click_count"=>6}
|
36
|
+
def website_likes
|
37
|
+
fb = @uberclient.get_connector(:facebook)
|
38
|
+
return {} if fb.nil? or @website.nil?
|
39
|
+
# normalize URL first
|
40
|
+
begin
|
41
|
+
uri = URI(@website)
|
42
|
+
uri.query = nil
|
43
|
+
uri.path = ''
|
44
|
+
results = fb.get_url_likes(uri.to_s)
|
45
|
+
(results.length > 0) ? results.first : {}
|
46
|
+
rescue
|
47
|
+
{}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
31
51
|
def total_reviews
|
32
52
|
@review_counts.values.inject { |a,b| a+b } || 0
|
33
53
|
end
|
@@ -49,6 +69,7 @@ module BizRatr
|
|
49
69
|
@zip ||= other.zip
|
50
70
|
@twitter ||= other.twitter
|
51
71
|
@city ||= other.city
|
72
|
+
@website ||= other.website
|
52
73
|
@checkins = @checkins.merge(other.checkins)
|
53
74
|
@users = @users.merge(other.users)
|
54
75
|
@likes = @likes.merge(other.likes)
|
@@ -82,7 +103,7 @@ module BizRatr
|
|
82
103
|
end
|
83
104
|
|
84
105
|
def add_likes(connector, likes)
|
85
|
-
@
|
106
|
+
@likes[connector] = likes
|
86
107
|
end
|
87
108
|
|
88
109
|
def add_rating(connector, rating)
|
data/lib/bizratr/connector.rb
CHANGED
@@ -4,34 +4,74 @@ require 'levenshtein'
|
|
4
4
|
require 'google_places'
|
5
5
|
require 'geocoder'
|
6
6
|
require 'factual'
|
7
|
+
require 'koala'
|
7
8
|
|
8
9
|
module BizRatr
|
9
10
|
class Connector
|
11
|
+
def initialize(uberclient, config)
|
12
|
+
@uberclient = uberclient
|
13
|
+
@config = config
|
14
|
+
@client = make_client(@config)
|
15
|
+
end
|
16
|
+
|
17
|
+
def make_client(config)
|
18
|
+
raise "Not implemented"
|
19
|
+
end
|
20
|
+
|
10
21
|
def search_location(location, query)
|
11
22
|
raise "Not implemented"
|
12
23
|
end
|
24
|
+
end
|
13
25
|
|
14
|
-
|
15
|
-
|
26
|
+
class FacebookConnector < Connector
|
27
|
+
def make_client(config)
|
28
|
+
oauth = Koala::Facebook::OAuth.new(config[:key], config[:secret])
|
29
|
+
Koala::Facebook::API.new(oauth.get_app_access_token)
|
30
|
+
end
|
31
|
+
|
32
|
+
def search_location(location, query)
|
33
|
+
results = @client.search(query, { :type => 'place', :center => location.join(','), :distance => 1000 })
|
34
|
+
results.map { |item|
|
35
|
+
make_business(@client.get_object(item['id']))
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def make_business(item)
|
40
|
+
b = Business.new(@uberclient, item['location']['latitude'], item['location']['longitude'], item['name'])
|
41
|
+
b.add_id(:facebook, item['id'])
|
42
|
+
b.city = item['location']['city']
|
43
|
+
b.country = item['location']['country']
|
44
|
+
b.phone = item['phone'] unless item['phone'] == "nope"
|
45
|
+
b.zip = item['location']['zip']
|
46
|
+
b.website = item['website'].split(' ').first
|
47
|
+
b.address = item['location']['street']
|
48
|
+
b.add_categories(:facebook, [item['category']])
|
49
|
+
b.add_checkins(:facebook, item['checkins'] + item['were_here_count'])
|
50
|
+
b.add_likes(:facebook, item['likes'])
|
51
|
+
b
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_url_likes(url)
|
55
|
+
@client.fql_query("SELECT share_count, like_count, comment_count, click_count FROM link_stat WHERE url='#{url}'")
|
16
56
|
end
|
17
57
|
end
|
18
58
|
|
19
59
|
class FactualConnector < Connector
|
20
|
-
def
|
21
|
-
|
60
|
+
def make_client(config)
|
61
|
+
Factual.new(config[:key], config[:secret])
|
22
62
|
end
|
23
63
|
|
24
64
|
def search_location(location, query)
|
25
|
-
location = geocode(location) if location.is_a? String
|
26
65
|
results = @client.table("places").filters("name" => query).geo("$circle" => { "$center" => location, "$meters" => 1000 })
|
27
66
|
results.map { |item| make_business(item) }
|
28
67
|
end
|
29
68
|
|
30
69
|
def make_business(item)
|
31
|
-
b = Business.new(item['latitude'], item['longitude'], item['name'])
|
70
|
+
b = Business.new(@uberclient, item['latitude'], item['longitude'], item['name'])
|
32
71
|
b.add_id(:factual, item['factual_id'])
|
33
72
|
b.add_categories(:factual, item['category'].split(",").map(&:strip))
|
34
73
|
b.phone = item['tel'].gsub(/[\ ()-]*/, '')
|
74
|
+
b.website = item['website']
|
35
75
|
b.city = item['locality']
|
36
76
|
b.country = item['country']
|
37
77
|
b.zip = item['postcode']
|
@@ -41,46 +81,43 @@ module BizRatr
|
|
41
81
|
end
|
42
82
|
|
43
83
|
class GooglePlacesConnector < Connector
|
44
|
-
def
|
45
|
-
|
84
|
+
def make_client(config)
|
85
|
+
GooglePlaces::Client.new(config[:key])
|
46
86
|
end
|
47
87
|
|
48
88
|
def search_location(location, query)
|
49
|
-
location = geocode(location) if location.is_a? String
|
50
89
|
results = @client.spots(location[0], location[1], :name => query)
|
51
90
|
results.map { |item| make_business(item) }
|
52
91
|
end
|
53
92
|
|
54
93
|
def make_business(item)
|
55
|
-
b = Business.new(item.lat, item.lng, item.name)
|
94
|
+
b = Business.new(@uberclient, item.lat, item.lng, item.name)
|
56
95
|
b.add_id(:google_places, item.id)
|
57
96
|
b.add_categories(:google_places, item.types)
|
58
97
|
b.phone = (item.formatted_phone_number || "").gsub(/[\ ()-]*/, '')
|
59
98
|
b.city = item.city || item.vicinity.split(',').last
|
60
99
|
b.country = item.country
|
100
|
+
b.website = item.website
|
61
101
|
b.zip = item.postal_code
|
62
102
|
b.address = item.vicinity.split(',').first
|
63
103
|
b.add_rating(:google_places, item.rating)
|
104
|
+
b.add_review_counts(:google_places, item.reviews.length)
|
64
105
|
b
|
65
106
|
end
|
66
107
|
end
|
67
108
|
|
68
109
|
class FourSquareConnector < Connector
|
69
|
-
def
|
70
|
-
|
110
|
+
def make_client(config)
|
111
|
+
Foursquare2::Client.new(config)
|
71
112
|
end
|
72
113
|
|
73
114
|
def search_location(location, query)
|
74
|
-
|
75
|
-
results = @client.search_venues(:ll => location.join(","), :query => query)
|
76
|
-
else
|
77
|
-
results = @client.search_venues(:near => location, :query => query)
|
78
|
-
end
|
115
|
+
results = @client.search_venues(:ll => location.join(","), :query => query)
|
79
116
|
results['groups'].first['items'].map { |item| make_business(item) }
|
80
117
|
end
|
81
118
|
|
82
119
|
def make_business(item)
|
83
|
-
b = Business.new(item['location']['lat'], item['location']['lng'], item['name'])
|
120
|
+
b = Business.new(@uberclient, item['location']['lat'], item['location']['lng'], item['name'])
|
84
121
|
b.add_id(:foursquare, item['id'])
|
85
122
|
categories = item.categories.map { |c| [ c.name ] + c.parents }.flatten
|
86
123
|
b.add_categories(:foursquare, categories)
|
@@ -91,15 +128,15 @@ module BizRatr
|
|
91
128
|
b.country = item['location']['cc']
|
92
129
|
b.address = item['location']['address']
|
93
130
|
b.add_checkins(:foursquare, item['stats']['checkinsCount'])
|
131
|
+
b.website = item['url']
|
94
132
|
b.add_users(:foursquare, item['stats']['usersCount'])
|
95
133
|
b
|
96
134
|
end
|
97
135
|
end
|
98
136
|
|
99
137
|
class YelpConnector < Connector
|
100
|
-
def
|
101
|
-
|
102
|
-
@client = Yelp::Client.new
|
138
|
+
def make_client(config)
|
139
|
+
Yelp::Client.new
|
103
140
|
end
|
104
141
|
|
105
142
|
def search_location(location, query)
|
@@ -113,7 +150,7 @@ module BizRatr
|
|
113
150
|
end
|
114
151
|
|
115
152
|
def make_business(item)
|
116
|
-
b = Business.new(item['location']['coordinate']['latitude'], item['location']['coordinate']['longitude'], item['name'])
|
153
|
+
b = Business.new(@uberclient, item['location']['coordinate']['latitude'], item['location']['coordinate']['longitude'], item['name'])
|
117
154
|
b.add_id(:yelp, item['id'])
|
118
155
|
b.add_categories(:yelp, item['categories'].map(&:first))
|
119
156
|
b.state = item['location']['state_code']
|
@@ -128,16 +165,18 @@ module BizRatr
|
|
128
165
|
end
|
129
166
|
end
|
130
167
|
|
131
|
-
class
|
168
|
+
class UberClient
|
132
169
|
def initialize(config)
|
133
|
-
@connectors =
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
170
|
+
@connectors = {}
|
171
|
+
config.each { |key, value|
|
172
|
+
@connectors[key] = case key
|
173
|
+
when :foursquare then FourSquareConnector.new(self, value)
|
174
|
+
when :yelp then YelpConnector.new(self, value)
|
175
|
+
when :google_places then GooglePlacesConnector.new(self, value)
|
176
|
+
when :factual then FactualConnector.new(self, value)
|
177
|
+
when :facebook then FacebookConnector.new(self, value)
|
178
|
+
else raise "No such connector found: #{key}"
|
179
|
+
end
|
141
180
|
}
|
142
181
|
end
|
143
182
|
|
@@ -145,11 +184,20 @@ module BizRatr
|
|
145
184
|
# location parameter should be either an address string or an array consisting of
|
146
185
|
# [ lat, lon ].
|
147
186
|
def search_location(location, query)
|
148
|
-
|
187
|
+
location = geocode(location) if location.is_a? String
|
188
|
+
merge @connectors.values.map { |c|
|
149
189
|
c.search_location(location, query)
|
150
190
|
}
|
151
191
|
end
|
152
192
|
|
193
|
+
def geocode(address)
|
194
|
+
Geocoder.coordinates(address)
|
195
|
+
end
|
196
|
+
|
197
|
+
def get_connector(key)
|
198
|
+
@connectors.fetch(key, nil)
|
199
|
+
end
|
200
|
+
|
153
201
|
# Search a location (just like search_location) but only return the best
|
154
202
|
# matching business (based on name).
|
155
203
|
def search_location_strictly(location, name)
|
data/lib/bizratr/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bizratr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-19 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: foursquare2
|
16
|
-
requirement: &
|
16
|
+
requirement: &70168127272320 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70168127272320
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: yelpster
|
27
|
-
requirement: &
|
27
|
+
requirement: &70168127271660 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70168127271660
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: google_places
|
38
|
-
requirement: &
|
38
|
+
requirement: &70168127271020 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70168127271020
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: levenshtein
|
49
|
-
requirement: &
|
49
|
+
requirement: &70168127270360 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70168127270360
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: google_places
|
60
|
-
requirement: &
|
60
|
+
requirement: &70168127269740 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70168127269740
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: geocoder
|
71
|
-
requirement: &
|
71
|
+
requirement: &70168127269100 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,21 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70168127269100
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: koala
|
82
|
+
requirement: &70168127268520 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70168127268520
|
80
91
|
- !ruby/object:Gem::Dependency
|
81
92
|
name: factual-api
|
82
|
-
requirement: &
|
93
|
+
requirement: &70168127246840 !ruby/object:Gem::Requirement
|
83
94
|
none: false
|
84
95
|
requirements:
|
85
96
|
- - ! '>='
|
@@ -87,7 +98,7 @@ dependencies:
|
|
87
98
|
version: '0'
|
88
99
|
type: :runtime
|
89
100
|
prerelease: false
|
90
|
-
version_requirements: *
|
101
|
+
version_requirements: *70168127246840
|
91
102
|
description: Get business ratings.
|
92
103
|
email: bamuller@gmail.com
|
93
104
|
executables: []
|