google_custom_search_api 0.0.1

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 ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ rdoc/*
3
+ *.gem
4
+ .bundle
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,2 @@
1
+ = Changelog
2
+
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ google_custom_search_api (0.0.1)
5
+ httparty
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ addressable (2.2.7)
11
+ crack (0.3.1)
12
+ diff-lcs (1.1.3)
13
+ httparty (0.8.1)
14
+ multi_json
15
+ multi_xml
16
+ json (1.6.5)
17
+ multi_json (1.1.0)
18
+ multi_xml (0.4.2)
19
+ rspec (2.9.0)
20
+ rspec-core (~> 2.9.0)
21
+ rspec-expectations (~> 2.9.0)
22
+ rspec-mocks (~> 2.9.0)
23
+ rspec-core (2.9.0)
24
+ rspec-expectations (2.9.0)
25
+ diff-lcs (~> 1.1.3)
26
+ rspec-mocks (2.9.0)
27
+ webmock (1.8.3)
28
+ addressable (>= 2.2.7)
29
+ crack (>= 0.1.7)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ google_custom_search_api!
36
+ json
37
+ rspec
38
+ webmock
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,126 @@
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 "google_custom_search_api"
12
+
13
+ then
14
+
15
+ bundle install
16
+
17
+ ## Configure
18
+
19
+ You need to configure ```GOOGLE_SEARCH_CX``` and ```GOOGLE_API_KEY``` to ```config/initializers/google_cse_api.rb```:
20
+
21
+ ```
22
+ GOOGLE_API_KEY = "..."
23
+ GOOGLE_SEARCH_CX = "..."
24
+ ```
25
+ You can get your ```GOOGLE_API_KEY``` from https://code.google.com/apis/console/b/0/?pli=1 - There are many choices - Simple API Access is probably what you want. There are more elaborate authorization schemes available for Google services but those aren't currently implemented.
26
+
27
+ You can get your ```GOOGLE_SEARCH_CX``` from http://www.google.com/cse/ Either create a custom engine or follow ```manage your existing search engines``` and go to your cse's Control panel. ```GOOGLE_SEARCH_CX``` == ```Search engine unique ID```
28
+
29
+ ### Searching the web, not just your site, with CSE
30
+
31
+ Google CSE was set up so search specific sites. To search the entire web simply go to http://www.google.com/cse/, find your CSE, go to it's control panel.
32
+
33
+ * in ```Basics``` under ```Search Preferences``` choose ```Search the entire web but emphasize included sites.```
34
+ * in ```Sites``` add ```www.google.com```
35
+
36
+ ## Use
37
+
38
+ To perform a search:
39
+
40
+ ```
41
+ results = GoogleCustomSearchApi.search("poker")
42
+ ```
43
+ Results now contains a raw version and a class'ed version of the data show in ```Sample results``` below.
44
+
45
+ This means you can do:
46
+
47
+ ```
48
+ results["items"].each do |item|
49
+ puts item["title"], item["link"]
50
+ end
51
+ ```
52
+
53
+ or
54
+
55
+ ```
56
+ results.items.each do |item|
57
+ puts item.title, item.link
58
+ end
59
+ ```
60
+
61
+ See [Custom Search](http://code.google.com/apis/customsearch/v1/using_rest.html) documentation for an explanation of all fields available.
62
+
63
+ ### Paging
64
+
65
+ By default CSE returns a maximum of 10 results at a time, you can't get more results without paging. BTW if you want fewer results just pass in the :num => 1-10 option when searching.
66
+
67
+ To do paging we pass in the :start option. Example:
68
+
69
+ ```
70
+ results = GoogleCustomSearchApi.search("poker", :start => 1)
71
+ ```
72
+
73
+ The maximum number of pages CSE allows is 10 - or 100 results in total. To walk through the pages you can use :start => 1, :start => 11, etc. Or you can use the results to find the next value, like so:
74
+
75
+ ```
76
+ start = 1
77
+ begin
78
+ results = GoogleCustomSearchApi.search("poker",:start => start)
79
+ if results.queries.keys.include?("nextPage")
80
+ start = results.queries.nextPage.first.startIndex
81
+ else
82
+ start = nil
83
+ end
84
+ end while start.nil? == false
85
+ ```
86
+
87
+ If you just want all results you can use the method ```search_and_return_all_results(query, opts = {})``` works just like the normal search but iterates through all available results and puts them in an array.
88
+
89
+ ### Encoding issues
90
+
91
+ TODO - this section needs work
92
+
93
+ 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:
94
+
95
+ ```
96
+ results.items.first.title.force_encoding(Encoding::UTF_8)
97
+ ```
98
+
99
+ More on this here: http://code.google.com/apis/customsearch/docs/ref_encoding.html
100
+
101
+ ## Contributing - Running tests
102
+
103
+ Pull requests welcome.
104
+
105
+ To run tests
106
+ ```
107
+ git clone git@github.com:wiseleyb/google_custom_search_api.git
108
+ cd google_custom_search_api
109
+ bundle install
110
+ bundle exec rspec spec
111
+ ```
112
+
113
+ ## Credits
114
+ * Based largely on the gem https://github.com/alexreisner/google_custom_search
115
+ * Awesome ResponseData class from https://github.com/mikedemers/rbing
116
+ * 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.
117
+
118
+ ## TODO
119
+ * pretty light on the tests
120
+
121
+ ## Sample results
122
+
123
+ See spec/fixtures/*.json for examples of data returned
124
+
125
+
126
+ 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
@@ -0,0 +1,107 @@
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 GoogleCustomSearchApi
6
+ extend self
7
+
8
+ ##
9
+ # Search the site.
10
+ #
11
+ # opts
12
+ # see list here for valid options http://code.google.com/apis/customsearch/v1/using_rest.html#query-params
13
+ def search(query, opts = {})
14
+ # Get and parse results.
15
+ url = url(query, opts)
16
+ puts url
17
+ return nil unless results = fetch(url)
18
+ results["items"] ||= []
19
+ ResponseData.new(results)
20
+ end
21
+
22
+ def search_and_return_all_results(query, opts = {})
23
+ res = []
24
+ opts[:start] ||= 1
25
+ begin
26
+ results = GoogleCustomSearchApi.search("poker",opts)
27
+ res << results
28
+ if results.queries.keys.include?("nextPage")
29
+ opts[:start] = results.queries.nextPage.first.startIndex
30
+ else
31
+ opts[:start] = nil
32
+ end
33
+ end while opts[:start].nil? == false
34
+ return res
35
+ end
36
+
37
+ # Convenience wrapper for the response Hash.
38
+ # Converts keys to Strings. Crawls through all
39
+ # member data and converts any other Hashes it
40
+ # finds. Provides access to values through
41
+ # method calls, which will convert underscored
42
+ # to camel case.
43
+ #
44
+ # Usage:
45
+ #
46
+ # rd = ResponseData.new("AlphaBeta" => 1, "Results" => {"Gamma" => 2, "delta" => [3, 4]})
47
+ # puts rd.alpha_beta
48
+ # => 1
49
+ # puts rd.alpha_beta.results.gamma
50
+ # => 2
51
+ # puts rd.alpha_beta.results.delta
52
+ # => [3, 4]
53
+ #
54
+ class ResponseData < Hash
55
+ private
56
+ def initialize(data={})
57
+ data.each_pair {|k,v| self[k.to_s] = deep_parse(v) }
58
+ end
59
+ def deep_parse(data)
60
+ case data
61
+ when Hash
62
+ self.class.new(data)
63
+ when Array
64
+ data.map {|v| deep_parse(v) }
65
+ else
66
+ data
67
+ end
68
+ end
69
+ def method_missing(*args)
70
+ name = args[0].to_s
71
+ return self[name] if has_key? name
72
+ camelname = name.split('_').map {|w| "#{w[0,1].upcase}#{w[1..-1]}" }.join("")
73
+ if has_key? camelname
74
+ self[camelname]
75
+ else
76
+ super *args
77
+ end
78
+ end
79
+ end
80
+
81
+
82
+ private # -------------------------------------------------------------------
83
+
84
+ ##
85
+ # Build search request URL.
86
+ #
87
+ # see list here for valid options http://code.google.com/apis/customsearch/v1/using_rest.html#query-params
88
+ def url(query, opts = {})
89
+ opts[:q] = query
90
+ opts[:alt] ||= "json"
91
+ uri = Addressable::URI.new
92
+ uri.query_values = opts
93
+ begin
94
+ params.merge!(GOOGLE_SEARCH_PARAMS)
95
+ rescue NameError
96
+ end
97
+ "https://www.googleapis.com/customsearch/v1?key=#{GOOGLE_API_KEY}&cx=#{GOOGLE_SEARCH_CX}&#{uri.query}"
98
+ end
99
+
100
+ ##
101
+ # Query Google, and make sure it responds.
102
+ #
103
+ def fetch(url)
104
+ return HTTParty.get(url)
105
+ end
106
+
107
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module GoogleCustomSearchApi
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,31 @@
1
+ {
2
+ "kind": "customsearch#search",
3
+ "url": {
4
+ "type": "application/json",
5
+ "template": "https://www.googleapis.com/customsearch/v1?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"
6
+ },
7
+ "queries": {
8
+ "request": [
9
+ {
10
+ "title": "Google Custom Search - asdfojasoidfjao sdfjaosdfj aosdijfoaisdjfoasjdofijas dofijweo fwoef jwoeifjw",
11
+ "totalResults": "0",
12
+ "searchTerms": "asdfojasoidfjao sdfjaosdfj aosdijfoaisdjfoasjdofijas dofijweo fwoef jwoeifjw",
13
+ "count": 10,
14
+ "inputEncoding": "utf8",
15
+ "outputEncoding": "utf8",
16
+ "safe": "off",
17
+ "cx": "002432975944642411257:ztx9u0hzbcw"
18
+ }
19
+ ]
20
+ },
21
+ "searchInformation": {
22
+ "searchTime": 0.121274,
23
+ "formattedSearchTime": "0.12",
24
+ "totalResults": "0",
25
+ "formattedTotalResults": "0"
26
+ },
27
+ "spelling": {
28
+ "correctedQuery": "asdf ojasoidfjao sdfj sdfj aosdijfoaisdjfoasjdofijas dofijweo fwoef jwoeifjw",
29
+ "htmlCorrectedQuery": "\u003cb\u003e\u003ci\u003easdf ojasoidfjao\u003c/i\u003e\u003c/b\u003e \u003cb\u003e\u003ci\u003esdfj sdfj\u003c/i\u003e\u003c/b\u003e aosdijfoaisdjfoasjdofijas dofijweo fwoef jwoeifjw"
30
+ }
31
+ }
@@ -0,0 +1,290 @@
1
+ {
2
+ "kind": "customsearch#search",
3
+ "url": {
4
+ "type": "application/json",
5
+ "template": "https://www.googleapis.com/customsearch/v1?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"
6
+ },
7
+ "queries": {
8
+ "nextPage": [
9
+ {
10
+ "title": "Google Custom Search - poker",
11
+ "totalResults": "40500000",
12
+ "searchTerms": "poker",
13
+ "count": 10,
14
+ "startIndex": 11,
15
+ "inputEncoding": "utf8",
16
+ "outputEncoding": "utf8",
17
+ "safe": "off",
18
+ "cx": "002432975944642411257:ztx9u0hzbcw"
19
+ }
20
+ ],
21
+ "request": [
22
+ {
23
+ "title": "Google Custom Search - poker",
24
+ "totalResults": "40500000",
25
+ "searchTerms": "poker",
26
+ "count": 10,
27
+ "startIndex": 1,
28
+ "inputEncoding": "utf8",
29
+ "outputEncoding": "utf8",
30
+ "safe": "off",
31
+ "cx": "002432975944642411257:ztx9u0hzbcw"
32
+ }
33
+ ]
34
+ },
35
+ "context": {
36
+ "title": "ICMS Dev"
37
+ },
38
+ "searchInformation": {
39
+ "searchTime": 0.193868,
40
+ "formattedSearchTime": "0.19",
41
+ "totalResults": "40500000",
42
+ "formattedTotalResults": "40,500,000"
43
+ },
44
+ "items": [
45
+ {
46
+ "kind": "customsearch#result",
47
+ "title": "Official World Series of Poker Online",
48
+ "htmlTitle": "Official World Series of \u003cb\u003ePoker\u003c/b\u003e Online",
49
+ "link": "http://www.wsop.com/",
50
+ "displayLink": "www.wsop.com",
51
+ "snippet": "Official website of the World Series of Poker Tournament. Featuring poker tournament coverage of events, schedules and news. Play online poker games like ...",
52
+ "htmlSnippet": "Official website of the World Series of \u003cb\u003ePoker\u003c/b\u003e Tournament. Featuring \u003cb\u003epoker\u003c/b\u003e \u003cbr\u003e tournament coverage of events, schedules and news. Play online \u003cb\u003epoker\u003c/b\u003e games \u003cbr\u003e like \u003cb\u003e...\u003c/b\u003e",
53
+ "cacheId": "T7q1CfbZcPwJ",
54
+ "formattedUrl": "www.wsop.com/",
55
+ "htmlFormattedUrl": "www.wsop.com/",
56
+ "pagemap": {
57
+ "cse_image": [
58
+ {
59
+ "src": "http://www.wsop.com/images/hm/download_image.jpg"
60
+ }
61
+ ],
62
+ "cse_thumbnail": [
63
+ {
64
+ "width": "185",
65
+ "height": "113",
66
+ "src": "https://encrypted-tbn1.google.com/images?q=tbn:ANd9GcQzUUbsQCEJ9huedBRALkpQPN6QBBwgwIFT2_cEA9hkkJYBehSvRygrQw"
67
+ }
68
+ ]
69
+ }
70
+ },
71
+ {
72
+ "kind": "customsearch#result",
73
+ "title": "Poker - Wikipedia, the free encyclopedia",
74
+ "htmlTitle": "\u003cb\u003ePoker\u003c/b\u003e - Wikipedia, the free encyclopedia",
75
+ "link": "http://en.wikipedia.org/wiki/Poker",
76
+ "displayLink": "en.wikipedia.org",
77
+ "snippet": "Poker is a family of card games involving betting and individualistic play whereby the winner is determined by the ranks and combinations of their cards, some of ...",
78
+ "htmlSnippet": "\u003cb\u003ePoker\u003c/b\u003e is a family of card games involving betting and individualistic play whereby \u003cbr\u003e the winner is determined by the ranks and combinations of their cards, some of \u003cb\u003e...\u003c/b\u003e",
79
+ "cacheId": "M0JijEuvEdkJ",
80
+ "formattedUrl": "en.wikipedia.org/wiki/Poker",
81
+ "htmlFormattedUrl": "en.wikipedia.org/wiki/\u003cb\u003ePoker\u003c/b\u003e",
82
+ "pagemap": {
83
+ "cse_image": [
84
+ {
85
+ "src": "http://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Holdem.jpg/300px-Holdem.jpg"
86
+ }
87
+ ],
88
+ "cse_thumbnail": [
89
+ {
90
+ "width": "240",
91
+ "height": "171",
92
+ "src": "https://encrypted-tbn2.google.com/images?q=tbn:ANd9GcStTlDjK3fS8LXRP2QSifQ1Q5dg0dwpak2LR9aGzPTavzts2b62_Q6t91k"
93
+ }
94
+ ]
95
+ }
96
+ },
97
+ {
98
+ "kind": "customsearch#result",
99
+ "title": "Online Poker - Play Online at Full Tilt Poker Room",
100
+ "htmlTitle": "Online \u003cb\u003ePoker\u003c/b\u003e - Play Online at Full Tilt \u003cb\u003ePoker\u003c/b\u003e Room",
101
+ "link": "http://www.fulltiltpoker.com/",
102
+ "displayLink": "www.fulltiltpoker.com",
103
+ "snippet": "Online Poker at the Fastest Growing Online Poker Room. Full Tilt Poker offers the best in online poker: world famous pros, a huge bonus, real or play money.",
104
+ "htmlSnippet": "Online \u003cb\u003ePoker\u003c/b\u003e at the Fastest Growing Online \u003cb\u003ePoker\u003c/b\u003e Room. Full Tilt \u003cb\u003ePoker\u003c/b\u003e offers the \u003cbr\u003e best in online \u003cb\u003epoker\u003c/b\u003e: world famous pros, a huge bonus, real or play money.",
105
+ "cacheId": "-0lVMr2LbU0J",
106
+ "formattedUrl": "www.fulltiltpoker.com/",
107
+ "htmlFormattedUrl": "www.fulltilt\u003cb\u003epoker\u003c/b\u003e.com/",
108
+ "pagemap": {
109
+ "cse_image": [
110
+ {
111
+ "src": "http://w.fulltiltcdn.net/images/global/content/home/video-player-still.png"
112
+ }
113
+ ],
114
+ "cse_thumbnail": [
115
+ {
116
+ "width": "206",
117
+ "height": "183",
118
+ "src": "https://encrypted-tbn3.google.com/images?q=tbn:ANd9GcQNl-iv7LDBN5OsGiWYzyH1ezgTvB2gwEIHhPLqJ0Tkd2OmQiywk0P7fyQ"
119
+ }
120
+ ],
121
+ "metatags": [
122
+ {
123
+ "uid": "10",
124
+ "nav_title": "Online Poker"
125
+ }
126
+ ]
127
+ }
128
+ },
129
+ {
130
+ "kind": "customsearch#result",
131
+ "title": "Poker.com - Online Poker Games, Free Tournaments, Rules & News",
132
+ "htmlTitle": "\u003cb\u003ePoker\u003c/b\u003e.com - Online \u003cb\u003ePoker\u003c/b\u003e Games, Free Tournaments, Rules &amp; News",
133
+ "link": "http://www.poker.com/",
134
+ "displayLink": "www.poker.com",
135
+ "snippet": "The world's #1 free poker information website, with poker game rules, news, tournaments and reviews of all the best online poker rooms.",
136
+ "htmlSnippet": "The world&#39;s #1 free \u003cb\u003epoker\u003c/b\u003e information website, with \u003cb\u003epoker\u003c/b\u003e game rules, news, \u003cbr\u003e tournaments and reviews of all the best online \u003cb\u003epoker\u003c/b\u003e rooms.",
137
+ "cacheId": "IlkL1Yc3_F8J",
138
+ "formattedUrl": "www.poker.com/",
139
+ "htmlFormattedUrl": "www.\u003cb\u003epoker\u003c/b\u003e.com/",
140
+ "pagemap": {
141
+ "cse_image": [
142
+ {
143
+ "src": "http://www.poker.com/pokernews/wp-content/uploads/2011/03/poker.jpg"
144
+ }
145
+ ],
146
+ "cse_thumbnail": [
147
+ {
148
+ "width": "115",
149
+ "height": "115",
150
+ "src": "https://encrypted-tbn3.google.com/images?q=tbn:ANd9GcRQrcdYcF0OGtXZ2SCv7CP55Z7O_is7guk6l-wEw5s85I-Z-UcBwJ3V9g"
151
+ }
152
+ ]
153
+ }
154
+ },
155
+ {
156
+ "kind": "customsearch#result",
157
+ "title": "Online Poker Sites Toplists & Bonus Offers, Poker Reviews and News",
158
+ "htmlTitle": "Online \u003cb\u003ePoker\u003c/b\u003e Sites Toplists &amp; Bonus Offers, \u003cb\u003ePoker\u003c/b\u003e Reviews and News",
159
+ "link": "http://www.pokerlistings.com/",
160
+ "displayLink": "www.pokerlistings.com",
161
+ "snippet": "5 hours ago ... PokerListings is the world's largest online poker guide with the best bonus offers guaranteed and exclusive free tournaments for new players.",
162
+ "htmlSnippet": "5 hours ago \u003cb\u003e...\u003c/b\u003e PokerListings is the world&#39;s largest online \u003cb\u003epoker\u003c/b\u003e guide with the best bonus offers \u003cbr\u003e guaranteed and exclusive free tournaments for new players.",
163
+ "cacheId": "dq71R1WBRMUJ",
164
+ "formattedUrl": "www.pokerlistings.com/",
165
+ "htmlFormattedUrl": "www.\u003cb\u003epoker\u003c/b\u003elistings.com/",
166
+ "pagemap": {
167
+ "cse_image": [
168
+ {
169
+ "src": "http://edge1.pokerlistings.com/assets/Uploads/EN-584x323-AffBanner-2.jpg"
170
+ }
171
+ ],
172
+ "cse_thumbnail": [
173
+ {
174
+ "width": "302",
175
+ "height": "167",
176
+ "src": "https://encrypted-tbn3.google.com/images?q=tbn:ANd9GcTXMaQ0pVWAUfo2V7ydD3a2sHYiFEPjA4zSEMJAKbC3GQ2Y2PzRAtttp1B3"
177
+ }
178
+ ]
179
+ }
180
+ },
181
+ {
182
+ "kind": "customsearch#result",
183
+ "title": "Governor of Poker - Hot Games at Miniclip.com - Play Free Online ...",
184
+ "htmlTitle": "Governor of \u003cb\u003ePoker\u003c/b\u003e - Hot Games at Miniclip.com - Play Free Online \u003cb\u003e...\u003c/b\u003e",
185
+ "link": "http://www.miniclip.com/games/governor-of-poker/en/",
186
+ "displayLink": "www.miniclip.com",
187
+ "snippet": "Win all your games in your hometown and become the Governor of Poker!",
188
+ "htmlSnippet": "Win all your games in your hometown and become the Governor of \u003cb\u003ePoker\u003c/b\u003e!"
189
+ },
190
+ {
191
+ "kind": "customsearch#result",
192
+ "title": "Online Poker | Play at Pacific poker online and get $8 FREE",
193
+ "htmlTitle": "Online \u003cb\u003ePoker\u003c/b\u003e | Play at Pacific \u003cb\u003epoker\u003c/b\u003e online and get $8 FREE",
194
+ "link": "http://www.pacificpoker.com/",
195
+ "displayLink": "www.pacificpoker.com",
196
+ "snippet": "Play online poker at Pacific Poker and get $8 FREE AND $400 bonus to play poker online at 888 poker - the largest and most trusted online poker room.",
197
+ "htmlSnippet": "Play online \u003cb\u003epoker\u003c/b\u003e at Pacific \u003cb\u003ePoker\u003c/b\u003e and get $8 FREE AND $400 bonus to play \u003cbr\u003e \u003cb\u003epoker\u003c/b\u003e online at 888 \u003cb\u003epoker\u003c/b\u003e - the largest and most trusted online \u003cb\u003epoker\u003c/b\u003e room.",
198
+ "cacheId": "sYy5C08rRZYJ",
199
+ "formattedUrl": "www.pacificpoker.com/",
200
+ "htmlFormattedUrl": "www.pacific\u003cb\u003epoker\u003c/b\u003e.com/",
201
+ "pagemap": {
202
+ "cse_image": [
203
+ {
204
+ "src": "http://images.888.com/newpoker/lang/en_new/PCP-main_december-400.jpg"
205
+ }
206
+ ],
207
+ "cse_thumbnail": [
208
+ {
209
+ "width": "339",
210
+ "height": "148",
211
+ "src": "https://encrypted-tbn3.google.com/images?q=tbn:ANd9GcQ0kVbE22EZPQE2iGUuqRFBEzh2odvIS7LfKBDNKBKkxOCoj4TAeMgEZ7c"
212
+ }
213
+ ]
214
+ }
215
+ },
216
+ {
217
+ "kind": "customsearch#result",
218
+ "title": "Online Poker Games | Play for Free Texas Holdem | PokerStars",
219
+ "htmlTitle": "Online \u003cb\u003ePoker\u003c/b\u003e Games | Play for Free Texas Holdem | PokerStars",
220
+ "link": "http://www.pokerstars.net/",
221
+ "displayLink": "www.pokerstars.net",
222
+ "snippet": "Play Texas Hold'em poker tournaments and other free poker games at the world's largest online poker room, with PokerStars free software download.",
223
+ "htmlSnippet": "Play Texas Hold&#39;em \u003cb\u003epoker\u003c/b\u003e tournaments and other free \u003cb\u003epoker\u003c/b\u003e games at the world&#39;s \u003cbr\u003e largest online \u003cb\u003epoker\u003c/b\u003e room, with PokerStars free software download.",
224
+ "cacheId": "QMONnAr9GUMJ",
225
+ "formattedUrl": "www.pokerstars.net/",
226
+ "htmlFormattedUrl": "www.\u003cb\u003epoker\u003c/b\u003estars.net/",
227
+ "pagemap": {
228
+ "cse_image": [
229
+ {
230
+ "src": "http://www.pokerstars.net/images/nightly-500-promo-net.jpg"
231
+ }
232
+ ],
233
+ "cse_thumbnail": [
234
+ {
235
+ "width": "141",
236
+ "height": "178",
237
+ "src": "https://encrypted-tbn1.google.com/images?q=tbn:ANd9GcRiMe-aAj1GQAKfrfatZqzE3BhRT9LjXr6r5v2sVQBfWI3jYqP8m_qMrQVr"
238
+ }
239
+ ]
240
+ }
241
+ },
242
+ {
243
+ "kind": "customsearch#result",
244
+ "title": "Poker News, Online Poker Reviews & Bonuses | PokerNews",
245
+ "htmlTitle": "\u003cb\u003ePoker\u003c/b\u003e News, Online \u003cb\u003ePoker\u003c/b\u003e Reviews &amp; Bonuses | PokerNews",
246
+ "link": "http://www.pokernews.com/",
247
+ "displayLink": "www.pokernews.com",
248
+ "snippet": "PokerNews is the world's No. 1 poker information source, offering: global poker news coverage, online poker reviews, special poker bonuses and deals, ...",
249
+ "htmlSnippet": "PokerNews is the world&#39;s No. 1 \u003cb\u003epoker\u003c/b\u003e information source, offering: global \u003cb\u003epoker\u003c/b\u003e \u003cbr\u003e news coverage, online \u003cb\u003epoker\u003c/b\u003e reviews, special \u003cb\u003epoker\u003c/b\u003e bonuses and deals, \u003cb\u003e...\u003c/b\u003e",
250
+ "cacheId": "Rdd35pvFIl8J",
251
+ "formattedUrl": "www.pokernews.com/",
252
+ "htmlFormattedUrl": "www.\u003cb\u003epoker\u003c/b\u003enews.com/",
253
+ "pagemap": {
254
+ "cse_image": [
255
+ {
256
+ "src": "http://www.pokernews.com/w/articles/4f5f/91ca6bf60.jpg"
257
+ }
258
+ ],
259
+ "cse_thumbnail": [
260
+ {
261
+ "width": "276",
262
+ "height": "183",
263
+ "src": "https://encrypted-tbn1.google.com/images?q=tbn:ANd9GcQ0X_cuK9XH4Ys7UmStdrxthiQmmRbklJxCPtYQtQsnkd9pHX7Yyp3Ioro"
264
+ }
265
+ ],
266
+ "metatags": [
267
+ {
268
+ "fb:admins": "100001502531544",
269
+ "application-name": "PokerNews Global",
270
+ "msapplication-starturl": "/",
271
+ "msapplication-navbutton-color": "#000000",
272
+ "msapplication-task": "name=News;action-uri=/news/;icon-uri=/img/jumplist/news.ico"
273
+ }
274
+ ]
275
+ }
276
+ },
277
+ {
278
+ "kind": "customsearch#result",
279
+ "title": "WPT | World Poker Tour Home",
280
+ "htmlTitle": "WPT | World \u003cb\u003ePoker\u003c/b\u003e Tour Home",
281
+ "link": "http://www.worldpokertour.com/",
282
+ "displayLink": "www.worldpokertour.com",
283
+ "snippet": "Official Site. Find show and tournament information. Watch clips, view WPT player bios and statistics, improve your game, and play online.",
284
+ "htmlSnippet": "Official Site. Find show and tournament information. Watch clips, view WPT \u003cbr\u003e player bios and statistics, improve your game, and play online.",
285
+ "cacheId": "NjGERrVM5rEJ",
286
+ "formattedUrl": "www.worldpokertour.com/",
287
+ "htmlFormattedUrl": "www.world\u003cb\u003epoker\u003c/b\u003etour.com/"
288
+ }
289
+ ]
290
+ }