sk_google_custom_search_api 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7242a2df55757ecf17e6e68e6176b2ed7d248727
4
+ data.tar.gz: f69674749f4670b55fa094862e36ea9d1bd05475
5
+ SHA512:
6
+ metadata.gz: 8e05b306d9ddceb3cbb50fef1f829818b8a4b4e7ff4e441cdb5ae73aaa0b2c50cb62c21b13129fb31078bb6630b3ad201fcc348000df1a7bf4e8eded02dc2f46
7
+ data.tar.gz: 66de2254b6b00cb4cef34cf76aa872a80130c1e31dd9023cd260ecb3dd0a5cf2839d0420aa54202ce8b0e6a8c6a31ba6f42b3cbcb823d0cc5c3875b84edafb9a
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,2 @@
1
+ = Changelog
2
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in importers.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ google_custom_search_api (2.0.0)
5
+ addressable
6
+ httparty
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ addressable (2.3.8)
12
+ crack (0.4.3)
13
+ safe_yaml (~> 1.0.0)
14
+ diff-lcs (1.2.5)
15
+ hashdiff (0.2.3)
16
+ httparty (0.13.7)
17
+ json (~> 1.8)
18
+ multi_xml (>= 0.5.2)
19
+ json (1.8.3)
20
+ multi_xml (0.5.5)
21
+ rspec (3.4.0)
22
+ rspec-core (~> 3.4.0)
23
+ rspec-expectations (~> 3.4.0)
24
+ rspec-mocks (~> 3.4.0)
25
+ rspec-core (3.4.1)
26
+ rspec-support (~> 3.4.0)
27
+ rspec-expectations (3.4.0)
28
+ diff-lcs (>= 1.2.0, < 2.0)
29
+ rspec-support (~> 3.4.0)
30
+ rspec-mocks (3.4.0)
31
+ diff-lcs (>= 1.2.0, < 2.0)
32
+ rspec-support (~> 3.4.0)
33
+ rspec-support (3.4.1)
34
+ safe_yaml (1.0.4)
35
+ vcr (3.0.1)
36
+ webmock (1.22.5)
37
+ addressable (< 2.4.0)
38
+ crack (>= 0.3.2)
39
+ hashdiff
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ google_custom_search_api!
46
+ json
47
+ rspec
48
+ vcr
49
+ webmock
50
+
51
+ BUNDLED WITH
52
+ 1.10.6
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Ben Wiseley
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # Google Custom Search
2
+
3
+ This project is a Ruby lib for Google's Custom Search ENgine API (http://www.google.com/cse). There seem to be quite a few cse libs out there that don't work so I rolled this up quickly.
4
+
5
+ Questions/comments, etc: wiseleyb@gmail.com
6
+
7
+ ## Install
8
+
9
+ Add to your Gemfile:
10
+
11
+ gem "sk_google_custom_search_api"
12
+
13
+ then
14
+
15
+ bundle install
16
+
17
+ Google's API management is confusing at best. At the time of this writing you codes like so:
18
+
19
+ ### GOOGLE_API_KEY
20
+
21
+ * Go to [Google Projects](https://console.developers.google.com/project)
22
+ * Create a project, open it
23
+ * Under `Explore other services` choose `Enable APIs and get credentials like keys`
24
+ * Search for `custom search` and click on it
25
+ * In the left column click on `Credentials`
26
+ * Under `API keys` grab your key. This is your `GOOGLE_API_KEY`
27
+
28
+ ### GOOGLE_SEARCH_CX
29
+
30
+ * Go to [Google CSE](https://cse.google.com/cse)
31
+ * Create a search engine and click on it
32
+ * Under `Setup > Tabs > Basic` find `Details` and click `Search engine ID`
33
+ * This is your GOOGLE_SEARCH_CX
34
+ * Make sure to add a site under `Sites to search`
35
+
36
+ ## Use
37
+
38
+ ### Search
39
+
40
+ To perform a search:
41
+
42
+ ```
43
+ results = GoogleCustomSearchApi.search("poker", {api_key: API_KEY, cx_key: CX_KEY})
44
+ ```
45
+ Results now contains a raw version and a class'ed version of the data show in ```Sample results``` below.
46
+
47
+ This means you can do:
48
+
49
+ ```
50
+ results["items"].each do |item|
51
+ puts item["title"], item["link"]
52
+ end
53
+ ```
54
+
55
+ or
56
+
57
+ ```
58
+ results.items.each do |item|
59
+ puts item.title, item.link
60
+ end
61
+ ```
62
+
63
+ ### Paging
64
+
65
+ Google only returns 10 results at a time and a maximum of 100 results. The easiest way to page through results if to use `:page`. Paging is 1 based (1-10). The default page is 1
66
+
67
+ ```
68
+ results = GoogleCustomerSearchApi.search("poker", page: 2)
69
+ results.pages == 10
70
+ results.current_page == 2
71
+ results.next_page == 3
72
+ results.previous_page == 1
73
+
74
+ results = GoogleCustomerSearchApi.search("poker", page: 1)
75
+ results.pages == 10
76
+ results.current_page == 1
77
+ results.next_page == 2
78
+ results.previous_page == nil
79
+
80
+ results = GoogleCustomerSearchApi.search("poker", page: 10)
81
+ results.pages == 10
82
+ results.current_page == 10
83
+ results.next_page == nil
84
+ results.previous_page == 9
85
+ ```
86
+
87
+ You can also use `:start` - which can be any number between 1 and 99. The `:page` helpers won't be accurate with `:start`
88
+
89
+ Example: get results 13-23
90
+
91
+ ```
92
+ results = GoogleCustomerSearchApi.search('poker', start: 13)
93
+ ```
94
+
95
+ See [Custom Search](http://code.google.com/apis/customsearch/v1/using_rest.html) documentation for an explanation of all fields available.
96
+
97
+ ### Search and return all results
98
+
99
+ This method isn't so useful because it's pretty slow (do to fetching up to 10 pages from Google). Helpful for testing sometimes.
100
+
101
+ ```
102
+ results = search_and_return_all_results('poker')
103
+ results.first.items.size # == 10
104
+
105
+ search_and_resturn_all_results('poker') do |results|
106
+ results.items.size # == 10 10 times
107
+ end
108
+
109
+ search_and_return_all_results(
110
+ '"California cult winery known for its Rhône"') do |results|
111
+ results.items.size # == 3 1 time
112
+ end
113
+ ```
114
+
115
+ ### Errors
116
+
117
+ Custom Search only returns a maximum of 100 results so - if you try something like
118
+
119
+ ```
120
+ results = GoogleCustomSearchApi.search('poker', start: 101)
121
+ ```
122
+ You get error and empty items.
123
+
124
+ ```
125
+ {
126
+ "error"=> {
127
+ "errors"=> [
128
+ {
129
+ "domain"=>"global",
130
+ "reason"=>"invalid",
131
+ "message"=>"Invalid Value"
132
+ }
133
+ ],
134
+ "code"=>400,
135
+ "message"=>"Invalid Value"
136
+ },
137
+ "items"=>[]
138
+ }
139
+ ```
140
+
141
+ So check for:
142
+
143
+ ```
144
+ if results.try(:error) || results.items.empty?
145
+ ```
146
+ ### Rails example
147
+
148
+ In **Gemfile**
149
+
150
+ ```
151
+ gem "google_custom_search_api"
152
+ ```
153
+
154
+ In **config/initializers/google_search.rb**
155
+
156
+ ```
157
+ GOOGLE_API_KEY = '...'
158
+ GOOGLE_SEARCH_CX = '...'
159
+ ```
160
+
161
+ In **config/routes.rb**
162
+
163
+ ```
164
+ get '/search' => 'search#index'
165
+ ```
166
+
167
+ In **app/controllers/search_controller.rb** you'd have something like this:
168
+
169
+ ```
170
+ class SearchController < ApplicationController
171
+ def index
172
+ if params[:q]
173
+ page = params[:page] || 1
174
+ @results = GoogleCustomSearchApi.search(params[:q],
175
+ page: page)
176
+ end
177
+ end
178
+ end
179
+ ```
180
+
181
+ And a simple view might look like this **app/search/index.html.erb** (this is using bootstrap styling)
182
+
183
+ ```
184
+ <section class='search-section'>
185
+ <div class='text-center titles-with-yellow'>
186
+ <h1>Search/h1>
187
+ </div>
188
+ <div class='container'>
189
+ <div class='text-center search-bar'>
190
+ <%= form_tag search_path, method: :get do %>
191
+ <div class="inner-addon right-addon">
192
+ <i class="glyphicon glyphicon-search"></i>
193
+ <%= text_field_tag :q, params[:q], class: 'form-control' %>
194
+ </div>
195
+ <% end %>
196
+ </div>
197
+ </div>
198
+
199
+ <% if @results && !@results.items.empty? %>
200
+ <div class='container'>
201
+ <% @results.items.each do |item| %>
202
+ <div class='row'>
203
+ <h4><%= link_to item.htmlTitle.html_safe, item.link %></h4>
204
+ <div>
205
+ <% if item['pagemap'] &&
206
+ item['pagemap']['cse_thumbnail'] &&
207
+ img = item.pagemap.cse_thumbnail.first %>
208
+ <div class='col-sm-2'>
209
+ <%= image_tag(img.src, width: '200px') %>
210
+ </div>
211
+ <div class='col-sm-10'>
212
+ <%= item.htmlSnippet.html_safe %>
213
+ </div>
214
+ <% else %>
215
+ <%= item.htmlSnippet.html_safe %>
216
+ <% end %>
217
+ </div>
218
+ </div>
219
+ <% end %>
220
+ </div>
221
+ <div class='container search-prev-next'>
222
+ <div class='row text-center'>
223
+ <% if @results.previous_page %>
224
+ <%= link_to '<< Previous',
225
+ search_path(q: params[:q], page: @results.previous_page),
226
+ class: 'btn' %>
227
+ <% end %>
228
+ <% @results.pages.times do |i| %>
229
+ <%= link_to i + 1,
230
+ search_path(q: params[:q], page: i+1),
231
+ class: 'btn btn-page' %>
232
+ <% end %>
233
+ <% if @results.next_page %>
234
+ <%= link_to 'Next >>',
235
+ search_path(q: params[:q],
236
+ page: @results.next_page),
237
+ class: 'btn' %>
238
+ <% end %>
239
+ </div>
240
+ </div>
241
+ <% else %>
242
+ <h4>No results</h4>
243
+ <% end %>
244
+ </section>
245
+ ```
246
+
247
+ ### Encoding issues
248
+
249
+ TODO - this section needs work
250
+
251
+ CSE will return non utf-8 results which can be problematic. I might add in a config value that you can explicitly set encoding. Until then a work around is doing stuff like:
252
+
253
+ ```
254
+ results.items.first.title.force_encoding(Encoding::UTF_8)
255
+ ```
256
+
257
+ More on this here: http://code.google.com/apis/customsearch/docs/ref_encoding.html
258
+
259
+ ## Contributing - Running tests
260
+
261
+ Pull requests welcome.
262
+
263
+ To run tests
264
+ ```
265
+ git clone git@github.com:wiseleyb/google_custom_search_api.git
266
+ cd google_custom_search_api
267
+ bundle install
268
+ bundle exec rspec spec
269
+ ```
270
+
271
+ ## Credits
272
+ * Based largely on the gem https://github.com/alexreisner/google_custom_search
273
+ * Awesome ResponseData class from https://github.com/mikedemers/rbing
274
+ * Work done while working on a project for the company http://reInteractive.net in sunny Sydney. A great ruby shop should you need help with something.
275
+
276
+ Copyright (c) 2012 Ben Wiseley, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/*_test.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
12
+
13
+ require 'rake/rdoctask'
14
+ Rake::RDocTask.new do |rdoc|
15
+ rdoc.rdoc_dir = 'rdoc'
16
+ rdoc.title = "Google Custom Search API #{GoogleCustomSearch::VERSION}"
17
+ rdoc.rdoc_files.include('*.rdoc')
18
+ rdoc.rdoc_files.include('lib/**/*.rb')
19
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "addressable/uri"
2
+ require 'google_custom_search_api'
@@ -0,0 +1,178 @@
1
+ ##
2
+ # Add search functionality (via Google Custom Search). Protocol reference at:
3
+ # http://www.google.com/coop/docs/cse/resultsxml.html
4
+ #
5
+
6
+ require 'httparty'
7
+ require 'addressable/uri'
8
+
9
+ module GoogleCustomSearchApi
10
+ extend self
11
+
12
+ ##
13
+ # Search the site.
14
+ #
15
+ # opts
16
+ # see list here for valid options
17
+ # http://code.google.com/apis/customsearch/v1/using_rest.html#query-params
18
+ def search(query, opts = {})
19
+ opts[:start] ||= 1
20
+
21
+ if (page = opts.delete(:page))
22
+ page = page.to_i
23
+ opts[:start] = (page - 1).abs * 10 + 1
24
+ else
25
+ page = (opts[:start].to_i / 10) + 1
26
+ end
27
+ page = 10 if page > 10
28
+
29
+ # Get and parse results.
30
+ url = url(query, opts)
31
+ return nil unless results = fetch(url)
32
+
33
+ results['items'] ||= []
34
+
35
+ # paging
36
+ if results.keys.include?('queries')
37
+ data = results['queries']['request'].first
38
+ results['pages'] = data['totalResults'].to_i / 10
39
+ results['pages'] = 10 if results['pages'] > 10
40
+ results['current_page'] = page.to_i
41
+
42
+ results['next_page'] = nil
43
+ results['previous_page'] = nil
44
+
45
+ if results['queries'].include?('nextPage') && page < 10
46
+ results['next_page'] = results['current_page'] + 1
47
+ end
48
+
49
+ if page > 1
50
+ results['previous_page'] = page - 1
51
+ end
52
+ end
53
+
54
+ ResponseData.new(results)
55
+ end
56
+
57
+ ##
58
+ # Search the site for all available results (max 100)
59
+ #
60
+ # This isn't so useful because it's quite slow
61
+ #
62
+ # Returns an array of up to 10 search(query) results
63
+ #
64
+ # examples:
65
+ #
66
+ # results = search_and_return_all_results('poker')
67
+ # results.first.items.size # == 10
68
+ #
69
+ # search_and_resturn_all_results('poker') do |results|
70
+ # results.items.size # == 10 10 times
71
+ # end
72
+ #
73
+ # search_and_return_all_results(
74
+ # '"California cult winery known for its Rhône"') do |results|
75
+ # results.items.size # == 3 1 time
76
+ # end
77
+ #
78
+ # opts
79
+ # see list here for valid options
80
+ # http://code.google.com/apis/customsearch/v1/using_rest.html#query-params
81
+ def search_and_return_all_results(query, opts = {})
82
+ res = []
83
+ opts[:start] ||= 1
84
+ begin
85
+ results = GoogleCustomSearchApi.search(query, opts)
86
+ return res unless results.keys.include?('queries')
87
+ yield results if block_given?
88
+ res << results
89
+ if results.queries.keys.include?("nextPage")
90
+ opts[:start] = results.queries.nextPage.first.startIndex
91
+ else
92
+ opts[:start] = nil
93
+ end
94
+ end while opts[:start].nil? == false
95
+ return res
96
+ end
97
+
98
+ # Convenience wrapper for the response Hash.
99
+ # Converts keys to Strings. Crawls through all
100
+ # member data and converts any other Hashes it
101
+ # finds. Provides access to values through
102
+ # method calls, which will convert underscored
103
+ # to camel case.
104
+ #
105
+ # Usage:
106
+ #
107
+ # rd = ResponseData.new("AlphaBeta" => 1,
108
+ # "Results" => {
109
+ # "Gamma" => 2,
110
+ # "delta" => [3, 4]})
111
+ # puts rd.alpha_beta
112
+ # => 1
113
+ # puts rd.alpha_beta.results.gamma
114
+ # => 2
115
+ # puts rd.alpha_beta.results.delta
116
+ # => [3, 4]
117
+ #
118
+ class ResponseData < Hash
119
+ private
120
+ def initialize(data={})
121
+ data.each_pair {|k,v| self[k.to_s] = deep_parse(v) }
122
+ end
123
+
124
+ def deep_parse(data)
125
+ case data
126
+ when Hash
127
+ self.class.new(data)
128
+ when Array
129
+ data.map {|v| deep_parse(v) }
130
+ else
131
+ data
132
+ end
133
+ end
134
+
135
+ def method_missing(*args)
136
+ name = args[0].to_s
137
+ return self[name] if has_key? name
138
+
139
+ camelname = name.split('_').map do |w|
140
+ "#{w[0,1].upcase}#{w[1..-1]}"
141
+ end.join("")
142
+
143
+ if has_key? camelname
144
+ self[camelname]
145
+ else
146
+ super *args
147
+ end
148
+ end
149
+ end
150
+
151
+
152
+ private
153
+
154
+ ##
155
+ # Build search request URL.
156
+ #
157
+ # see list here for valid options
158
+ # http://code.google.com/apis/customsearch/v1/using_rest.html#query-params
159
+ def url(query, opts = {})
160
+ opts[:q] = query
161
+ opts[:alt] ||= "json"
162
+ uri = Addressable::URI.new
163
+ uri.query_values = opts
164
+ begin
165
+ params.merge!(GOOGLE_SEARCH_PARAMS)
166
+ rescue NameError
167
+ end
168
+ "https://www.googleapis.com/customsearch/v1?" \
169
+ "key=#{opts[:api_key]}&cx=#{opts[:cx_key]}&#{uri.query}"
170
+ end
171
+
172
+ ##
173
+ # Query Google, and make sure it responds.
174
+ #
175
+ def fetch(url)
176
+ return HTTParty.get(url)
177
+ end
178
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module GoogleCustomSearchApi
2
+ VERSION = "2.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sk_google_custom_search_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrey Skuratovsky
8
+ - Ben Wiseley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-02-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: addressable
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: vcr
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: webmock
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: json
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ description: Ruby lib for Google's Custom Search Api.
99
+ email:
100
+ - skuratowsky@gmail.com
101
+ - wiseleyb@gmail.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - CHANGELOG.rdoc
107
+ - Gemfile
108
+ - Gemfile.lock
109
+ - LICENSE
110
+ - README.md
111
+ - Rakefile
112
+ - init.rb
113
+ - lib/google_custom_search_api.rb
114
+ - lib/version.rb
115
+ homepage: http://github.com/askuratovsky/google_custom_search_api
116
+ licenses: []
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.4.3
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Ruby lib for Google's Custom Search Api.
138
+ test_files: []