searchapi 1.0.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.
- checksums.yaml +7 -0
- data/README.md +175 -0
- data/bin/test +14 -0
- data/lib/searchapi/error_result.rb +50 -0
- data/lib/searchapi/google_finance_options.rb +40 -0
- data/lib/searchapi/google_finance_request.rb +26 -0
- data/lib/searchapi/google_finance_result.rb +262 -0
- data/lib/searchapi/google_flights_options.rb +85 -0
- data/lib/searchapi/google_flights_request.rb +25 -0
- data/lib/searchapi/google_flights_result.rb +275 -0
- data/lib/searchapi/google_images_options.rb +64 -0
- data/lib/searchapi/google_images_request.rb +26 -0
- data/lib/searchapi/google_images_result.rb +133 -0
- data/lib/searchapi/google_light_options.rb +43 -0
- data/lib/searchapi/google_light_request.rb +26 -0
- data/lib/searchapi/google_light_result.rb +198 -0
- data/lib/searchapi/google_local_options.rb +40 -0
- data/lib/searchapi/google_local_request.rb +26 -0
- data/lib/searchapi/google_local_result.rb +85 -0
- data/lib/searchapi/google_news_light_options.rb +47 -0
- data/lib/searchapi/google_news_light_request.rb +26 -0
- data/lib/searchapi/google_news_light_result.rb +94 -0
- data/lib/searchapi/google_news_options.rb +53 -0
- data/lib/searchapi/google_news_portal_options.rb +40 -0
- data/lib/searchapi/google_news_portal_request.rb +89 -0
- data/lib/searchapi/google_news_portal_result.rb +137 -0
- data/lib/searchapi/google_news_request.rb +26 -0
- data/lib/searchapi/google_news_result.rb +129 -0
- data/lib/searchapi/google_scholar_options.rb +48 -0
- data/lib/searchapi/google_scholar_request.rb +26 -0
- data/lib/searchapi/google_scholar_result.rb +195 -0
- data/lib/searchapi/google_search_options.rb +67 -0
- data/lib/searchapi/google_search_request.rb +26 -0
- data/lib/searchapi/google_search_result.rb +301 -0
- data/lib/searchapi/helpers.rb +10 -0
- data/lib/searchapi/instagram_profile_options.rb +31 -0
- data/lib/searchapi/instagram_profile_request.rb +26 -0
- data/lib/searchapi/instagram_profile_result.rb +117 -0
- data/lib/searchapi/module_methods.rb +80 -0
- data/lib/searchapi/request.rb +25 -0
- data/lib/searchapi/response_methods.rb +14 -0
- data/lib/searchapi/tiktok_profile_options.rb +31 -0
- data/lib/searchapi/tiktok_profile_request.rb +26 -0
- data/lib/searchapi/tiktok_profile_result.rb +71 -0
- data/lib/searchapi/version.rb +3 -0
- data/lib/searchapi/youtube_search_options.rb +62 -0
- data/lib/searchapi/youtube_search_request.rb +26 -0
- data/lib/searchapi/youtube_search_result.rb +411 -0
- data/lib/searchapi.rb +70 -0
- data/searchapi.gemspec +37 -0
- metadata +164 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class GoogleSearchOptions
|
|
3
|
+
include DynamicSchema::Definable
|
|
4
|
+
include Helpers
|
|
5
|
+
|
|
6
|
+
DEVICES = %w[ desktop mobile tablet ]
|
|
7
|
+
SAFE_SEARCH = %w[ active off ]
|
|
8
|
+
TIME_PERIODS = %w[ last_hour last_day last_week last_month last_year ]
|
|
9
|
+
OPTIMIZATION_STRATEGIES = %w[ performance ads ]
|
|
10
|
+
|
|
11
|
+
NORMALIZE_DOWNCASE = ->(v) { v.to_s.downcase }
|
|
12
|
+
|
|
13
|
+
schema do
|
|
14
|
+
# search query (q or kgmid required)
|
|
15
|
+
q String
|
|
16
|
+
kgmid String
|
|
17
|
+
|
|
18
|
+
# device
|
|
19
|
+
device String, in: DEVICES, normalize: NORMALIZE_DOWNCASE
|
|
20
|
+
|
|
21
|
+
# geographic location
|
|
22
|
+
location String
|
|
23
|
+
uule String
|
|
24
|
+
|
|
25
|
+
# localization
|
|
26
|
+
google_domain String
|
|
27
|
+
gl String
|
|
28
|
+
hl String
|
|
29
|
+
lr String
|
|
30
|
+
cr String
|
|
31
|
+
|
|
32
|
+
# filters
|
|
33
|
+
nfpr String
|
|
34
|
+
filter String
|
|
35
|
+
safe String, in: SAFE_SEARCH, normalize: NORMALIZE_DOWNCASE
|
|
36
|
+
time_period String, in: TIME_PERIODS, normalize: NORMALIZE_DOWNCASE
|
|
37
|
+
time_period_min String
|
|
38
|
+
time_period_max String
|
|
39
|
+
|
|
40
|
+
# pagination
|
|
41
|
+
page Integer
|
|
42
|
+
|
|
43
|
+
# optimization
|
|
44
|
+
optimization_strategy String, in: OPTIMIZATION_STRATEGIES, normalize: NORMALIZE_DOWNCASE
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.build( options = nil, &block )
|
|
48
|
+
new( api_options: builder.build( options, &block ) )
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.build!( options = nil, &block )
|
|
52
|
+
new( api_options: builder.build!( options, &block ) )
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def initialize( options = {}, api_options: nil )
|
|
56
|
+
@options = self.class.builder.build( options || {} )
|
|
57
|
+
@options = api_options.merge( @options ) if api_options
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_h
|
|
61
|
+
result = @options.to_h
|
|
62
|
+
result[ :engine ] = 'google'
|
|
63
|
+
result
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class GoogleSearchRequest < Request
|
|
3
|
+
|
|
4
|
+
def search( query = nil, options = nil, &block )
|
|
5
|
+
if options
|
|
6
|
+
options = options.is_a?( GoogleSearchOptions ) ? options : GoogleSearchOptions.build!( options.to_h )
|
|
7
|
+
options = options.to_h
|
|
8
|
+
else
|
|
9
|
+
options = { engine: 'google' }
|
|
10
|
+
end
|
|
11
|
+
options[ :q ] = query.to_s if query
|
|
12
|
+
|
|
13
|
+
response = get( "#{ BASE_URI }/search", options, &block )
|
|
14
|
+
attributes = ( JSON.parse( response.body, symbolize_names: true ) rescue nil )
|
|
15
|
+
|
|
16
|
+
result = if response.success?
|
|
17
|
+
GoogleSearchResult.new( attributes || {} )
|
|
18
|
+
else
|
|
19
|
+
ErrorResult.new( response.status, attributes )
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
ResponseMethods.install( response, result )
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module SearchAPI
|
|
4
|
+
|
|
5
|
+
# Search metadata
|
|
6
|
+
GoogleSearchMetadataSchema = DynamicSchema::Struct.define do
|
|
7
|
+
id String
|
|
8
|
+
status String
|
|
9
|
+
created_at String, as: :created_at
|
|
10
|
+
request_time_taken Float, as: :request_time_taken
|
|
11
|
+
parsing_time_taken Float, as: :parsing_time_taken
|
|
12
|
+
total_time_taken Float, as: :total_time_taken
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class GoogleSearchMetadata < GoogleSearchMetadataSchema
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Search parameters
|
|
19
|
+
GoogleSearchParametersSchema = DynamicSchema::Struct.define do
|
|
20
|
+
engine String
|
|
21
|
+
q String
|
|
22
|
+
kgmid String
|
|
23
|
+
location String
|
|
24
|
+
location_used String, as: :location_used
|
|
25
|
+
uule String
|
|
26
|
+
google_domain String, as: :google_domain
|
|
27
|
+
hl String
|
|
28
|
+
gl String
|
|
29
|
+
lr String
|
|
30
|
+
cr String
|
|
31
|
+
device String
|
|
32
|
+
page Integer
|
|
33
|
+
num Integer
|
|
34
|
+
safe String
|
|
35
|
+
filter String
|
|
36
|
+
nfpr String
|
|
37
|
+
time_period String, as: :time_period
|
|
38
|
+
time_period_min String, as: :time_period_min
|
|
39
|
+
time_period_max String, as: :time_period_max
|
|
40
|
+
optimization_strategy String, as: :optimization_strategy
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class GoogleSearchParameters < GoogleSearchParametersSchema
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Search information
|
|
47
|
+
GoogleSearchInformationSchema = DynamicSchema::Struct.define do
|
|
48
|
+
query_displayed String, as: :query_displayed
|
|
49
|
+
total_results Integer, as: :total_results
|
|
50
|
+
page Integer
|
|
51
|
+
time_taken_displayed String, as: :time_taken_displayed
|
|
52
|
+
detected_location String, as: :detected_location
|
|
53
|
+
did_you_mean String, as: :did_you_mean
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class GoogleSearchInformation < GoogleSearchInformationSchema
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Organic result sitelinks
|
|
60
|
+
GoogleSitelinkSchema = DynamicSchema::Struct.define do
|
|
61
|
+
title String
|
|
62
|
+
link String
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class GoogleSitelink < GoogleSitelinkSchema
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Organic result
|
|
69
|
+
GoogleOrganicResultSchema = DynamicSchema::Struct.define do
|
|
70
|
+
position Integer
|
|
71
|
+
title String
|
|
72
|
+
link String
|
|
73
|
+
displayed_link String, as: :displayed_link
|
|
74
|
+
favicon String
|
|
75
|
+
snippet String
|
|
76
|
+
snippet_highlighted_words String, array: true, as: :snippet_highlighted_words
|
|
77
|
+
date String
|
|
78
|
+
sitelinks GoogleSitelink, array: true
|
|
79
|
+
source String
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class GoogleOrganicResult < GoogleOrganicResultSchema
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Ad result
|
|
86
|
+
GoogleAdSchema = DynamicSchema::Struct.define do
|
|
87
|
+
position Integer
|
|
88
|
+
title String
|
|
89
|
+
link String
|
|
90
|
+
displayed_link String, as: :displayed_link
|
|
91
|
+
tracking_link String, as: :tracking_link
|
|
92
|
+
description String
|
|
93
|
+
sitelinks GoogleSitelink, array: true
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
class GoogleAd < GoogleAdSchema
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Shopping ad
|
|
100
|
+
GoogleShoppingAdSchema = DynamicSchema::Struct.define do
|
|
101
|
+
position Integer
|
|
102
|
+
title String
|
|
103
|
+
link String
|
|
104
|
+
source String
|
|
105
|
+
price String
|
|
106
|
+
rating Float
|
|
107
|
+
reviews Integer
|
|
108
|
+
thumbnail String
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class GoogleShoppingAd < GoogleShoppingAdSchema
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Knowledge graph
|
|
115
|
+
GoogleKnowledgeGraphSchema = DynamicSchema::Struct.define do
|
|
116
|
+
title String
|
|
117
|
+
type String
|
|
118
|
+
description String
|
|
119
|
+
source Hash
|
|
120
|
+
image String
|
|
121
|
+
attributes Hash
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class GoogleKnowledgeGraph < GoogleKnowledgeGraphSchema
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Related question
|
|
128
|
+
GoogleRelatedQuestionSchema = DynamicSchema::Struct.define do
|
|
129
|
+
question String
|
|
130
|
+
answer String
|
|
131
|
+
title String
|
|
132
|
+
link String
|
|
133
|
+
displayed_link String, as: :displayed_link
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
class GoogleRelatedQuestion < GoogleRelatedQuestionSchema
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Related search
|
|
140
|
+
GoogleRelatedSearchSchema = DynamicSchema::Struct.define do
|
|
141
|
+
query String
|
|
142
|
+
link String
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
class GoogleRelatedSearch < GoogleRelatedSearchSchema
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Video result
|
|
149
|
+
GoogleVideoSchema = DynamicSchema::Struct.define do
|
|
150
|
+
position Integer
|
|
151
|
+
title String
|
|
152
|
+
link String
|
|
153
|
+
source String
|
|
154
|
+
channel String
|
|
155
|
+
date String
|
|
156
|
+
duration String
|
|
157
|
+
thumbnail String
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
class GoogleVideo < GoogleVideoSchema
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Top story
|
|
164
|
+
GoogleTopStorySchema = DynamicSchema::Struct.define do
|
|
165
|
+
title String
|
|
166
|
+
link String
|
|
167
|
+
source String
|
|
168
|
+
date String
|
|
169
|
+
thumbnail String
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
class GoogleTopStory < GoogleTopStorySchema
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Local result
|
|
176
|
+
GoogleLocalResultSchema = DynamicSchema::Struct.define do
|
|
177
|
+
position Integer
|
|
178
|
+
title String
|
|
179
|
+
place_id String, as: :place_id
|
|
180
|
+
data_cid String, as: :data_cid
|
|
181
|
+
rating Float
|
|
182
|
+
reviews Integer
|
|
183
|
+
price String
|
|
184
|
+
type String
|
|
185
|
+
address String
|
|
186
|
+
hours String
|
|
187
|
+
phone String
|
|
188
|
+
website String
|
|
189
|
+
thumbnail String
|
|
190
|
+
gps_coordinates Hash, as: :gps_coordinates
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
class GoogleLocalResult < GoogleLocalResultSchema
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Pagination
|
|
197
|
+
GooglePaginationSchema = DynamicSchema::Struct.define do
|
|
198
|
+
current Integer
|
|
199
|
+
_value :next, type: Integer
|
|
200
|
+
previous Integer
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
class GooglePagination < GooglePaginationSchema
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# AI Overview reference link
|
|
207
|
+
GoogleAIOverviewReferenceSchema = DynamicSchema::Struct.define do
|
|
208
|
+
link String
|
|
209
|
+
title String
|
|
210
|
+
source String
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
class GoogleAIOverviewReference < GoogleAIOverviewReferenceSchema
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# AI Overview text block
|
|
217
|
+
GoogleAIOverviewTextBlockSchema = DynamicSchema::Struct.define do
|
|
218
|
+
text String
|
|
219
|
+
position Integer
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
class GoogleAIOverviewTextBlock < GoogleAIOverviewTextBlockSchema
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# AI Overview
|
|
226
|
+
GoogleAIOverviewSchema = DynamicSchema::Struct.define do
|
|
227
|
+
text_blocks GoogleAIOverviewTextBlock, array: true, as: :text_blocks
|
|
228
|
+
markdown String
|
|
229
|
+
reference_links GoogleAIOverviewReference, array: true, as: :reference_links
|
|
230
|
+
error String
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
class GoogleAIOverview < GoogleAIOverviewSchema
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Answer box
|
|
237
|
+
GoogleAnswerBoxSchema = DynamicSchema::Struct.define do
|
|
238
|
+
type String
|
|
239
|
+
title String
|
|
240
|
+
answer String
|
|
241
|
+
link String
|
|
242
|
+
snippet String
|
|
243
|
+
date String
|
|
244
|
+
thumbnail String
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
class GoogleAnswerBox < GoogleAnswerBoxSchema
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Inline image
|
|
251
|
+
GoogleInlineImageSchema = DynamicSchema::Struct.define do
|
|
252
|
+
title String
|
|
253
|
+
source String
|
|
254
|
+
link String
|
|
255
|
+
thumbnail String
|
|
256
|
+
original String
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
class GoogleInlineImage < GoogleInlineImageSchema
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Inline images container
|
|
263
|
+
GoogleInlineImagesSchema = DynamicSchema::Struct.define do
|
|
264
|
+
images GoogleInlineImage, array: true
|
|
265
|
+
more_link String, as: :more_link
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
class GoogleInlineImages < GoogleInlineImagesSchema
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# Main search result
|
|
272
|
+
GoogleSearchResultSchema = DynamicSchema::Struct.define do
|
|
273
|
+
search_metadata GoogleSearchMetadata, as: :search_metadata
|
|
274
|
+
search_parameters GoogleSearchParameters, as: :search_parameters
|
|
275
|
+
search_information GoogleSearchInformation, as: :search_information
|
|
276
|
+
ai_overview GoogleAIOverview, as: :ai_overview
|
|
277
|
+
answer_box GoogleAnswerBox, as: :answer_box
|
|
278
|
+
knowledge_graph GoogleKnowledgeGraph, as: :knowledge_graph
|
|
279
|
+
ads GoogleAd, array: true
|
|
280
|
+
shopping_ads GoogleShoppingAd, array: true, as: :shopping_ads
|
|
281
|
+
organic_results GoogleOrganicResult, array: true, as: :organic_results
|
|
282
|
+
related_questions GoogleRelatedQuestion, array: true, as: :related_questions
|
|
283
|
+
inline_videos GoogleVideo, array: true, as: :inline_videos
|
|
284
|
+
top_stories GoogleTopStory, array: true, as: :top_stories
|
|
285
|
+
local_results GoogleLocalResult, array: true, as: :local_results
|
|
286
|
+
related_searches GoogleRelatedSearch, array: true, as: :related_searches
|
|
287
|
+
pagination GooglePagination
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
class GoogleSearchResult < GoogleSearchResultSchema
|
|
291
|
+
extend Forwardable
|
|
292
|
+
include Enumerable
|
|
293
|
+
|
|
294
|
+
def_delegators :organic_results, :each, :[], :count, :size, :length, :first, :last, :empty?
|
|
295
|
+
|
|
296
|
+
def success?
|
|
297
|
+
true
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class InstagramProfileOptions
|
|
3
|
+
include DynamicSchema::Definable
|
|
4
|
+
include Helpers
|
|
5
|
+
|
|
6
|
+
schema do
|
|
7
|
+
# required
|
|
8
|
+
username String
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.build( options = nil, &block )
|
|
12
|
+
new( api_options: builder.build( options, &block ) )
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.build!( options = nil, &block )
|
|
16
|
+
new( api_options: builder.build!( options, &block ) )
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize( options = {}, api_options: nil )
|
|
20
|
+
@options = self.class.builder.build( options || {} )
|
|
21
|
+
@options = api_options.merge( @options ) if api_options
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_h
|
|
25
|
+
result = @options.to_h
|
|
26
|
+
result[ :engine ] = 'instagram_profile'
|
|
27
|
+
result
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class InstagramProfileRequest < Request
|
|
3
|
+
|
|
4
|
+
def profile( username, options = nil, &block )
|
|
5
|
+
if options
|
|
6
|
+
options = options.is_a?( InstagramProfileOptions ) ? options : InstagramProfileOptions.build!( options.to_h )
|
|
7
|
+
options = options.to_h
|
|
8
|
+
else
|
|
9
|
+
options = { engine: 'instagram_profile' }
|
|
10
|
+
end
|
|
11
|
+
options[ :username ] = username.to_s
|
|
12
|
+
|
|
13
|
+
response = get( "#{ BASE_URI }/search", options, &block )
|
|
14
|
+
attributes = ( JSON.parse( response.body, symbolize_names: true ) rescue nil )
|
|
15
|
+
|
|
16
|
+
result = if response.success?
|
|
17
|
+
InstagramProfileResult.new( attributes || {} )
|
|
18
|
+
else
|
|
19
|
+
ErrorResult.new( response.status, attributes )
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
ResponseMethods.install( response, result )
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module SearchAPI
|
|
4
|
+
|
|
5
|
+
# Instagram Search metadata
|
|
6
|
+
InstagramProfileMetadataSchema = DynamicSchema::Struct.define do
|
|
7
|
+
id String
|
|
8
|
+
status String
|
|
9
|
+
created_at String, as: :created_at
|
|
10
|
+
request_time_taken Float, as: :request_time_taken
|
|
11
|
+
parsing_time_taken Float, as: :parsing_time_taken
|
|
12
|
+
total_time_taken Float, as: :total_time_taken
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class InstagramProfileMetadata < InstagramProfileMetadataSchema
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Instagram Search parameters
|
|
19
|
+
InstagramProfileParametersSchema = DynamicSchema::Struct.define do
|
|
20
|
+
engine String
|
|
21
|
+
username String
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class InstagramProfileParameters < InstagramProfileParametersSchema
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Bio link
|
|
28
|
+
InstagramBioLinkSchema = DynamicSchema::Struct.define do
|
|
29
|
+
title String
|
|
30
|
+
url String
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class InstagramBioLink < InstagramBioLinkSchema
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Tagged user
|
|
37
|
+
InstagramTaggedUserSchema = DynamicSchema::Struct.define do
|
|
38
|
+
username String
|
|
39
|
+
x Float
|
|
40
|
+
y Float
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class InstagramTaggedUser < InstagramTaggedUserSchema
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Carousel item
|
|
47
|
+
InstagramCarouselItemSchema = DynamicSchema::Struct.define do
|
|
48
|
+
type String
|
|
49
|
+
link String
|
|
50
|
+
width Integer
|
|
51
|
+
height Integer
|
|
52
|
+
thumbnail String
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class InstagramCarouselItem < InstagramCarouselItemSchema
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Post
|
|
59
|
+
InstagramPostSchema = DynamicSchema::Struct.define do
|
|
60
|
+
position Integer
|
|
61
|
+
id String
|
|
62
|
+
permalink String
|
|
63
|
+
type String
|
|
64
|
+
link String
|
|
65
|
+
width Integer
|
|
66
|
+
height Integer
|
|
67
|
+
thumbnail String
|
|
68
|
+
caption String
|
|
69
|
+
likes Integer
|
|
70
|
+
comments Integer
|
|
71
|
+
iso_date String, as: :iso_date
|
|
72
|
+
tagged_users InstagramTaggedUser, array: true, as: :tagged_users
|
|
73
|
+
carousel_items InstagramCarouselItem, array: true, as: :carousel_items
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class InstagramPost < InstagramPostSchema
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Profile
|
|
80
|
+
InstagramProfileSchema = DynamicSchema::Struct.define do
|
|
81
|
+
username String
|
|
82
|
+
name String
|
|
83
|
+
bio String
|
|
84
|
+
avatar String
|
|
85
|
+
avatar_hd String, as: :avatar_hd
|
|
86
|
+
is_verified [ TrueClass, FalseClass ], as: :is_verified
|
|
87
|
+
is_business [ TrueClass, FalseClass ], as: :is_business
|
|
88
|
+
posts Integer
|
|
89
|
+
followers Integer
|
|
90
|
+
following Integer
|
|
91
|
+
external_link String, as: :external_link
|
|
92
|
+
bio_links InstagramBioLink, array: true, as: :bio_links
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
class InstagramProfile < InstagramProfileSchema
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Main Instagram profile result
|
|
99
|
+
InstagramProfileResultSchema = DynamicSchema::Struct.define do
|
|
100
|
+
search_metadata InstagramProfileMetadata, as: :search_metadata
|
|
101
|
+
search_parameters InstagramProfileParameters, as: :search_parameters
|
|
102
|
+
profile InstagramProfile
|
|
103
|
+
posts InstagramPost, array: true
|
|
104
|
+
error String
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
class InstagramProfileResult < InstagramProfileResultSchema
|
|
108
|
+
extend Forwardable
|
|
109
|
+
|
|
110
|
+
def_delegators :profile, :username, :name, :bio, :avatar, :followers, :following
|
|
111
|
+
|
|
112
|
+
def success?
|
|
113
|
+
self.error.nil?
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
module ModuleMethods
|
|
3
|
+
|
|
4
|
+
def connection( connection = nil )
|
|
5
|
+
@connection = connection if connection
|
|
6
|
+
@connection ||= Faraday.new { | builder | builder.adapter Faraday.default_adapter }
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def api_key( api_key = nil )
|
|
10
|
+
@api_key = api_key || @api_key
|
|
11
|
+
@api_key
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Google Search
|
|
15
|
+
def google( query = nil, options = nil, &block )
|
|
16
|
+
GoogleSearchRequest.new.search( query, options, &block )
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# YouTube Search
|
|
20
|
+
def youtube( query, options = nil, &block )
|
|
21
|
+
YouTubeSearchRequest.new.search( query, options, &block )
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Instagram Profile
|
|
25
|
+
def instagram( username, options = nil, &block )
|
|
26
|
+
InstagramProfileRequest.new.profile( username, options, &block )
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# TikTok Profile
|
|
30
|
+
def tiktok( username, options = nil, &block )
|
|
31
|
+
TikTokProfileRequest.new.profile( username, options, &block )
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Google Finance
|
|
35
|
+
def finance( symbol, options = nil, &block )
|
|
36
|
+
GoogleFinanceRequest.new.quote( symbol, options, &block )
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Google Flights
|
|
40
|
+
def flights( options = nil, &block )
|
|
41
|
+
GoogleFlightsRequest.new.search( options, &block )
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Google Light (fast, lightweight search)
|
|
45
|
+
def google_light( query, options = nil, &block )
|
|
46
|
+
GoogleLightRequest.new.search( query, options, &block )
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Google News
|
|
50
|
+
def news( query, options = nil, &block )
|
|
51
|
+
GoogleNewsRequest.new.search( query, options, &block )
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Google News Portal
|
|
55
|
+
def news_portal( query = nil, options = nil, &block )
|
|
56
|
+
GoogleNewsPortalRequest.new.search( query, options, &block )
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Google News Light
|
|
60
|
+
def news_light( query, options = nil, &block )
|
|
61
|
+
GoogleNewsLightRequest.new.search( query, options, &block )
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Google Images
|
|
65
|
+
def images( query, options = nil, &block )
|
|
66
|
+
GoogleImagesRequest.new.search( query, options, &block )
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Google Local
|
|
70
|
+
def local( query, options = nil, &block )
|
|
71
|
+
GoogleLocalRequest.new.search( query, options, &block )
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Google Scholar
|
|
75
|
+
def scholar( query = nil, options = nil, &block )
|
|
76
|
+
GoogleScholarRequest.new.search( query, options, &block )
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class Request
|
|
3
|
+
|
|
4
|
+
BASE_URI = 'https://www.searchapi.io/api/v1'
|
|
5
|
+
|
|
6
|
+
def initialize( connection: nil, api_key: nil )
|
|
7
|
+
@connection = connection || SearchAPI.connection
|
|
8
|
+
@api_key = api_key || SearchAPI.api_key
|
|
9
|
+
raise ArgumentError,
|
|
10
|
+
"The API key is required but was not provided; configure it using " \
|
|
11
|
+
"'SearchAPI.api_key' or pass it directly." unless @api_key
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
protected
|
|
15
|
+
|
|
16
|
+
def get( uri, params = {}, &block )
|
|
17
|
+
@connection.get( uri ) do | request |
|
|
18
|
+
request.headers[ 'Authorization' ] = "Bearer #{ @api_key }"
|
|
19
|
+
request.params = params unless params.empty?
|
|
20
|
+
block.call( request ) if block
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|