Files
ROC/library/gcse/src/gcse_api.e
jvelilla 9263f31521 Renamed module name to google_search (custom_search)
Clean code.
Updated google custom search to handle quota limit and no query submit.
Updated encoding issues for input searches: like "void safe" and "void + safe".
2015-10-14 11:51:59 -03:00

237 lines
7.5 KiB
Plaintext

note
description: "[
Simple API to call Google Custome Search Engine
Example call:
GET https://www.googleapis.com/customsearch/v1?key=INSERT_YOUR_API_KEY&cx=017576662512468239146:omuauf_lfve&q=lectures
]"
date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $"
revision: "$Revision: 97973 $"
EIS: "name=Google Custom Search Engine", "src=https://developers.google.com/custom-search/json-api/v1/using_rest", "protocol=uri"
class
GCSE_API
create
make
feature {NONE} -- Initialization
make (a_query_parameters: GCSE_QUERY_PARAMETERS)
-- Create an object GCSE with query_parameters `a_query_parameters'
do
query_parameter := a_query_parameters
ensure
query_parameters_set: query_parameter = a_query_parameters
end
feature -- Access
base_uri: STRING_8 = "https://www.googleapis.com/customsearch/v1"
-- Google custom search base URI.
query_parameter: GCSE_QUERY_PARAMETERS
-- Google custom search parameters.
last_result: detachable GCSE_RESPONSE
-- Search results.
feature -- Status Reports
errors: detachable LIST [READABLE_STRING_8]
-- optional list of error messages.
feature -- API
search
-- Search
local
l_parser: JSON_PARSER
l_gcse_response: detachable GCSE_RESPONSE
do
-- Data format for the response.
-- At the moment we are using the default value: json
-- but it's possible to define atom response using the alt parameter.
last_result := Void
if attached get as l_response then
create l_gcse_response
l_gcse_response.set_status (l_response.status)
l_gcse_response.set_status_nessage (l_response.status_message)
if attached l_response.body as l_body then
create l_parser.make_with_string (l_body)
l_parser.parse_content
if l_response.status = 200 and then l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv then
-- Queries
if attached {JSON_OBJECT} jv.item (queries_key) as jqueries then
-- Next Page
if attached {GCSE_PAGE} query_page (next_page_key, jqueries) as l_page then
l_gcse_response.set_next_page (l_page)
end
-- Current Page
if attached {GCSE_PAGE} query_page (request_key, jqueries) as l_page then
l_gcse_response.set_current_page (l_page)
end
-- Previous Page
if attached {GCSE_PAGE} query_page (previous_page_key, jqueries) as l_page then
l_gcse_response.set_previous_page (l_page)
end
end
if attached {JSON_ARRAY} jv.item (items_key) as jitems then
across jitems as ic loop
if attached{JSON_OBJECT} ic.item as j_item then
l_gcse_response.add_item (item (j_item))
end
end
end
else
put_error (l_body)
end
else
put_error (l_response.status.out)
end
else
put_error ("unknown")
end
last_result := l_gcse_response
end
feature {NONE} -- REST API
get: detachable RESPONSE
-- Reading Data.
local
l_request: REQUEST
do
create l_request.make ("GET", new_uri)
Result := l_request.execute
end
feature {NONE} -- Implementation
new_uri: STRING_8
-- new uri (BaseUri?key=secret_value&cx=a_cx_id&q=a_query
-- ?key=INSERT_YOUR_API_KEY&cx=017576662512468239146:omuauf_lfve&q=lectures
-- full template BaseUri?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&
-- safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&
-- googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&
-- siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&
-- orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&
-- searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&
-- imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json"
do
create Result.make_from_string (base_uri)
Result.append ("?key=")
Result.append (query_parameter.secret)
Result.append ("&cx=")
Result.append (query_parameter.cx)
Result.append ("&q=")
Result.append (query_parameter.query)
-- num
if attached query_parameter.num as l_num then
Result.append ("&num=")
Result.append (l_num)
end
if attached query_parameter.start as l_start then
Result.append ("&start=")
Result.append (l_start)
end
end
put_error (a_message: READABLE_STRING_GENERAL)
-- put error message `a_message'.
local
l_errors: like errors
utf: UTF_CONVERTER
do
l_errors := errors
if l_errors = Void then
create {ARRAYED_LIST [STRING]} l_errors.make (1)
errors := l_errors
end
l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_message))
end
item (a_item: JSON_OBJECT): GCSE_PAGE_ITEM
-- Google Result Metadata Item.
do
create Result
if attached {JSON_STRING} a_item.item ("kind") as l_kind then
Result.set_kind (l_kind.item)
end
if attached {JSON_STRING} a_item.item ("title") as l_title then
Result.set_title (l_title.item)
end
if attached {JSON_STRING} a_item.item ("htmlTitle") as l_htmltitle then
Result.set_html_title (l_htmltitle.unescaped_string_32)
end
if attached {JSON_STRING} a_item.item ("link") as l_link then
Result.set_link (l_link.item)
end
if attached {JSON_STRING} a_item.item ("displayLink") as l_display_link then
Result.set_display_link (l_display_link.item)
end
if attached {JSON_STRING} a_item.item ("snippet") as l_snippet then
Result.set_snippet (l_snippet.unescaped_string_8)
end
if attached {JSON_STRING} a_item.item ("htmlSnippet") as l_html_snippet then
Result.set_html_snippet (l_html_snippet.unescaped_string_32)
end
if attached {JSON_STRING} a_item.item ("formattedUrl") as l_formatted_url then
Result.set_formatted_url (l_formatted_url.item)
end
end
query_page (a_page_key: JSON_STRING; a_queries: JSON_OBJECT): detachable GCSE_PAGE
-- Google result medata query. Return a query page based for a query with page key `a_page_key', if any.
do
if
attached {JSON_ARRAY} a_queries.item (a_page_key) as jquerypage and then
jquerypage.count > 0 and then
attached {JSON_OBJECT} jquerypage.i_th (1) as jpage
then
create Result
if attached {JSON_STRING} jpage.item ("title") as l_title then
Result.set_title (l_title.item)
end
if attached {JSON_STRING} jpage.item ("totalResults") as l_results then
Result.set_total_results (l_results.item.to_integer)
end
if attached {JSON_STRING} jpage.item ("searchTerms") as l_search_terms then
Result.set_search_terms (l_search_terms.item)
end
-- TODO check if we should use INTEGER_64
if attached {JSON_NUMBER} jpage.item ("count") as l_count then
Result.set_count (l_count.integer_64_item.as_integer_32)
end
if attached {JSON_NUMBER} jpage.item ("startIndex") as l_index then
Result.set_start_index (l_index.integer_64_item.as_integer_32)
end
end
end
feature {NONE} -- JSON Keys
queries_key: STRING = "queries"
next_page_key: STRING = "nextPage"
request_key: STRING = "request"
previous_page_key: STRING = "previousPage"
items_key: STRING = "items"
note
copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end