Skip to content

Commit

Permalink
Label support.
Browse files Browse the repository at this point in the history
  • Loading branch information
jasiek committed Mar 7, 2012
1 parent a10f4df commit 7001195
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 38 deletions.
39 changes: 5 additions & 34 deletions lib/google_custom_search.rb
Expand Up @@ -6,17 +6,10 @@
require 'active_support/core_ext' require 'active_support/core_ext'


module GoogleCustomSearch module GoogleCustomSearch
extend self autoload :ResultSet, 'result_set'

autoload :Result, 'result'
##
# Quick Struct-based class to hold a collection of search result data.
#
class ResultSet < Struct.new(:total, :pages, :suggestion, :labels); end


## extend self
# Quick Struct-based class to hold data for a single search result.
#
class Result < Struct.new(:url, :title, :description); end


## ##
# Search the site. # Search the site.
Expand All @@ -30,17 +23,12 @@ def search(query, offset = 0, length = 20)


# Extract and return search result data, if exists. # Extract and return search result data, if exists.
if data['RES'] if data['RES']
ResultSet.new( ResultSet.create(data)
data['RES']['M'].to_i, # total
parse_results(data['RES']['R']), # pages
data['SPELLING'] ? data['SPELLING']['SUGGESTION'] : nil # suggestion
)
else else
ResultSet.new(0, [], nil) ResultSet.create_empty()
end end
end end



private # ------------------------------------------------------------------- private # -------------------------------------------------------------------


## ##
Expand Down Expand Up @@ -74,21 +62,4 @@ def fetch_xml(url)
rescue SocketError, TimeoutError; end rescue SocketError, TimeoutError; end
(resp and resp.code == "200") ? resp.body : nil (resp and resp.code == "200") ? resp.body : nil
end end

##
# Transform an array of Google search results (XML parsed by REXML) into
# a more useful format.
#
def parse_results(results)
out = []
results = [results] if results.is_a?(Hash) # no array if only one result
results.each do |r|
out << Result.new(
r['U'], # url
r['T'].try(:sub, / \[[^\]]*\]$/, ''), # title
r['S'].try(:gsub, '<br>', '') # desciption
)
end
out
end
end end
22 changes: 22 additions & 0 deletions lib/result.rb
@@ -0,0 +1,22 @@
##
# Single search result.
#
class GoogleCustomSearch::Result
attr_reader :url, :title, :description, :labels

def self.parse(res_r)
res_r = [res_r] if res_r.is_a?(Hash)

res_r.collect do |r|
self.new(r['U'], # url
r['T'].try(:sub, / \[[^\]]*\]$/, ''), # title
r['S'].try(:gsub, '<br>', ''), # desciption
r['Label'].is_a?(String) ? [r['Label']] : r['Label']) # array of labels
end
end

def initialize(url, title, description, labels)
@url, @title, @description, @labels = url, title, description, labels
end
end

36 changes: 36 additions & 0 deletions lib/result_set.rb
@@ -0,0 +1,36 @@
##
# Simple class to hold a collection of search result data.
#
class GoogleCustomSearch::ResultSet
attr_reader :total, :pages, :suggestion, :labels

def self.create(xml_hash)
self.new(xml_hash['RES']['M'].to_i,
parse_results(xml_hash['RES']['R']),
spelling = xml_hash['SPELLING'] ? spelling['SUGGESTION'] : nil,
parse_labels(xml_hash))
end

def self.create_empty
self.new(0, [], nil, {})
end

def self.parse_results(res_r)
GoogleCustomSearch::Result.parse(res_r)
end

def self.parse_labels(xml_hash)
return {} unless context = xml_hash['Context'] and facets = context['Facet']
facets.inject({}) do |h, facet_item|
facet_item['FacetItem'].each do |element|
h[element['label']] = element['anchor_text']
end
h
end
end

def initialize(total, pages, suggestion, labels)
@total, @pages, @suggestion, @labels = total, pages, suggestion, labels
end
end

20 changes: 18 additions & 2 deletions test/google_custom_search_test.rb
Expand Up @@ -2,8 +2,24 @@


class GoogleCustomSearchTest < ActiveSupport::TestCase class GoogleCustomSearchTest < ActiveSupport::TestCase
test "returns an array of results" do test "returns an array of results" do
results = GoogleCustomSearch.search('science') results = GoogleCustomSearch.search('engineer')
assert(results.pages.size > 0) assert(! results.pages.empty?)
assert(! results.labels.empty?)

label_set = results.pages.inject(Set[]) do |label_set, page|
assert(page.title.is_a?(String))
assert(! page.title.empty?)

assert(page.url.is_a?(String))
URI.parse(page.url)

assert(page.description.is_a?(String))
assert(! page.description.empty?)

label_set += page.labels
end

assert(! (label_set & results.labels.keys.to_set).empty?)
end end
end end


11 changes: 9 additions & 2 deletions test/test_helper.rb
Expand Up @@ -4,5 +4,12 @@
require 'test/unit' require 'test/unit'
require 'google_custom_search' require 'google_custom_search'


# http://groups.google.com/a/googleproductforums.com/forum/#!category-topic/customsearch/implementation/EMyXtR5CV4E # Google Custom Search (Google Jobs) :)
GOOGLE_SEARCH_CX = '014399221313847880480:c7jsxy-iymw' # GOOGLE_SEARCH_CX = '016766180714503271468:t099t-w3qse'

# IBM Magazine
# GOOGLE_SEARCH_CX = '003630504832992121813:duvzt8xkd_8'

# fbi.gov

GOOGLE_SEARCH_CX = '004748461833896749646:e41lgwqry7w'

0 comments on commit 7001195

Please sign in to comment.