google_custom_search 0.3.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/.gitignore +5 -0
- data/CHANGELOG.rdoc +8 -0
- data/LICENSE +20 -0
- data/README.rdoc +68 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/google_custom_search.gemspec +51 -0
- data/init.rb +1 -0
- data/lib/google_custom_search.rb +86 -0
- data/test/google_custom_search_test.rb +6 -0
- data/test/test_helper.rb +4 -0
- metadata +67 -0
data/CHANGELOG.rdoc
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Alex Reisner
|
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.rdoc
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
= Google Custom Search
|
2
|
+
|
3
|
+
Ruby API to Google Custom Search Engine (http://www.google.com/cse). Works with the paid version of CSE where you get results in XML format.
|
4
|
+
|
5
|
+
|
6
|
+
== 1. Install
|
7
|
+
|
8
|
+
Install either as a Rails plugin:
|
9
|
+
|
10
|
+
script/plugin install git://github.com/alexreisner/google_custom_search.git
|
11
|
+
|
12
|
+
or as a gem:
|
13
|
+
|
14
|
+
# add to config/environment.rb:
|
15
|
+
config.gem "google_custom_search", :source => "http://gemcutter.org/"
|
16
|
+
|
17
|
+
# at command prompt:
|
18
|
+
sudo rake gems:install
|
19
|
+
|
20
|
+
or as a standalone gem (outside of Rails):
|
21
|
+
|
22
|
+
sudo gem install google_custom_search --source http://gemcutter.org
|
23
|
+
|
24
|
+
|
25
|
+
== 2. Configure
|
26
|
+
|
27
|
+
You *must* define a constant in your application called <tt>GOOGLE_SEARCH_CX</tt>. For example, if you're using Rails, create a file <tt>config/initializers/google_custom_search.rb</tt>:
|
28
|
+
|
29
|
+
GOOGLE_SEARCH_CX = "..."
|
30
|
+
|
31
|
+
You can find the CX value for your custom search engine via the search control panel on Google's site (click the "Get code" link and you'll see a hidden "cx" field in the sample HTML form).
|
32
|
+
|
33
|
+
If you're working outside of Rails you'll also need some +require+ statements:
|
34
|
+
|
35
|
+
require 'rubygems'
|
36
|
+
require 'rexml/document'
|
37
|
+
require 'google_custom_search'
|
38
|
+
|
39
|
+
|
40
|
+
== 3. Use
|
41
|
+
|
42
|
+
To perform a search:
|
43
|
+
|
44
|
+
results = GoogleCustomSearch.search("Hank Aaron")
|
45
|
+
|
46
|
+
The +results+ variable is now a GoogleCustomSearch::ResultSet object:
|
47
|
+
|
48
|
+
results.total # 5080
|
49
|
+
results.pages # array of GoogleCustomSearch::Result objects
|
50
|
+
results.suggestion # string with suggested search term, if any
|
51
|
+
|
52
|
+
Iterate through the results:
|
53
|
+
|
54
|
+
results.pages.each do |r|
|
55
|
+
r.title # page title
|
56
|
+
r.url # page URL
|
57
|
+
r.description # Google's excerpt, with terms highlighted
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
== Future
|
62
|
+
|
63
|
+
* access to all data returned by Google
|
64
|
+
* support for features of CSE free version
|
65
|
+
* support for multiple CSEs in one app (GOOGLE_SEARCH_CX should be a hash)
|
66
|
+
|
67
|
+
|
68
|
+
Copyright (c) 2009 Alex Reisner, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "google_custom_search"
|
8
|
+
gem.summary = %Q{Ruby API to Google Custom Search Engine.}
|
9
|
+
gem.description = %Q{Ruby API to Google Custom Search Engine. Works with the paid version of CSE where you get results in XML format.}
|
10
|
+
gem.email = "alex@alexreisner.com"
|
11
|
+
gem.homepage = "http://github.com/alexreisner/google_custom_search"
|
12
|
+
gem.authors = ["Alex Reisner"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/*_test.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
if File.exist?('VERSION')
|
47
|
+
version = File.read('VERSION')
|
48
|
+
else
|
49
|
+
version = ""
|
50
|
+
end
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "Google Custom Search #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{google_custom_search}
|
8
|
+
s.version = "0.3.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Alex Reisner"]
|
12
|
+
s.date = %q{2009-10-14}
|
13
|
+
s.description = %q{Ruby API to Google Custom Search Engine. Works with the paid version of CSE where you get results in XML format.}
|
14
|
+
s.email = %q{alex@alexreisner.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"CHANGELOG.rdoc",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"google_custom_search.gemspec",
|
27
|
+
"init.rb",
|
28
|
+
"lib/google_custom_search.rb",
|
29
|
+
"test/google_custom_search_test.rb",
|
30
|
+
"test/test_helper.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/alexreisner/google_custom_search}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.5}
|
36
|
+
s.summary = %q{Ruby API to Google Custom Search Engine.}
|
37
|
+
s.test_files = [
|
38
|
+
"test/google_custom_search_test.rb",
|
39
|
+
"test/test_helper.rb"
|
40
|
+
]
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
47
|
+
else
|
48
|
+
end
|
49
|
+
else
|
50
|
+
end
|
51
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'google_custom_search'
|
@@ -0,0 +1,86 @@
|
|
1
|
+
##
|
2
|
+
# Add search functionality (via Google Custom Search). Protocol reference at:
|
3
|
+
# http://www.google.com/coop/docs/cse/resultsxml.html
|
4
|
+
#
|
5
|
+
module GoogleCustomSearch
|
6
|
+
|
7
|
+
##
|
8
|
+
# Quick Struct-based class to hold a collection of search result data.
|
9
|
+
#
|
10
|
+
class ResultSet < Struct.new(:total, :pages, :suggestion); end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Quick Struct-based class to hold data for a single search result.
|
14
|
+
#
|
15
|
+
class Result < Struct.new(:url, :title, :description); end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Search the site.
|
19
|
+
#
|
20
|
+
def self.search(query, offset = 0, length = 20)
|
21
|
+
|
22
|
+
# Get and parse results.
|
23
|
+
url = url(query, offset, length)
|
24
|
+
return nil unless xml = fetch_xml(url)
|
25
|
+
data = Hash.from_xml(xml)['GSP']
|
26
|
+
|
27
|
+
# Extract and return search result data, if exists.
|
28
|
+
if data['RES']
|
29
|
+
ResultSet.new(
|
30
|
+
data['RES']['M'].to_i, # total
|
31
|
+
parse_results(data['RES']['R']), # pages
|
32
|
+
data['SPELLING'] ? data['SPELLING']['SUGGESTION'] : nil # suggestion
|
33
|
+
)
|
34
|
+
else
|
35
|
+
ResultSet.new(0, [], nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
private # -------------------------------------------------------------------
|
41
|
+
|
42
|
+
##
|
43
|
+
# Build search request URL.
|
44
|
+
#
|
45
|
+
def self.url(query, offset = 0, length = 20)
|
46
|
+
params = {
|
47
|
+
:q => query,
|
48
|
+
:start => offset,
|
49
|
+
:num => length,
|
50
|
+
:client => "google-csbe",
|
51
|
+
:output => "xml_no_dtd",
|
52
|
+
:cx => GOOGLE_SEARCH_CX
|
53
|
+
}
|
54
|
+
"http://www.google.com/search?" + params.to_query
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Query Google, and make sure it responds.
|
59
|
+
#
|
60
|
+
def self.fetch_xml(url)
|
61
|
+
begin
|
62
|
+
resp = nil
|
63
|
+
timeout(3) do
|
64
|
+
resp = Net::HTTP.get_response(URI.parse(url))
|
65
|
+
end
|
66
|
+
rescue SocketError, TimeoutError; end
|
67
|
+
(resp and resp.code == "200") ? resp.body : nil
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Transform an array of Google search results (XML parsed by REXML) into
|
72
|
+
# a more useful format.
|
73
|
+
#
|
74
|
+
def self.parse_results(results)
|
75
|
+
out = []
|
76
|
+
results = [results] if results.is_a?(Hash) # no array if only one result
|
77
|
+
results.each do |r|
|
78
|
+
out << Result.new(
|
79
|
+
r['U'], # url
|
80
|
+
r['T'].sub(/ \[[^\]]*\]$/, ''), # title
|
81
|
+
r['S'].gsub('<br>', '') # desciption
|
82
|
+
)
|
83
|
+
end
|
84
|
+
out
|
85
|
+
end
|
86
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: google_custom_search
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex Reisner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-14 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Ruby API to Google Custom Search Engine. Works with the paid version of CSE where you get results in XML format.
|
17
|
+
email: alex@alexreisner.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- CHANGELOG.rdoc
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- google_custom_search.gemspec
|
33
|
+
- init.rb
|
34
|
+
- lib/google_custom_search.rb
|
35
|
+
- test/google_custom_search_test.rb
|
36
|
+
- test/test_helper.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/alexreisner/google_custom_search
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --charset=UTF-8
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.5
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Ruby API to Google Custom Search Engine.
|
65
|
+
test_files:
|
66
|
+
- test/google_custom_search_test.rb
|
67
|
+
- test/test_helper.rb
|