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,89 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class GoogleNewsPortalRequest < Request
|
|
3
|
+
|
|
4
|
+
def search( query = nil, options = nil, &block )
|
|
5
|
+
if options
|
|
6
|
+
options = options.is_a?( GoogleNewsPortalOptions ) ? options : GoogleNewsPortalOptions.build!( options.to_h )
|
|
7
|
+
options = options.to_h
|
|
8
|
+
else
|
|
9
|
+
options = { engine: 'google_news_portal' }
|
|
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
|
+
GoogleNewsPortalResult.new( attributes || {} )
|
|
18
|
+
else
|
|
19
|
+
ErrorResult.new( response.status, attributes )
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
ResponseMethods.install( response, result )
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def story( story_token, options = nil, &block )
|
|
26
|
+
if options
|
|
27
|
+
options = options.is_a?( GoogleNewsPortalOptions ) ? options : GoogleNewsPortalOptions.build!( options.to_h )
|
|
28
|
+
options = options.to_h
|
|
29
|
+
else
|
|
30
|
+
options = { engine: 'google_news_portal' }
|
|
31
|
+
end
|
|
32
|
+
options[ :story_token ] = story_token.to_s
|
|
33
|
+
|
|
34
|
+
response = get( "#{ BASE_URI }/search", options, &block )
|
|
35
|
+
attributes = ( JSON.parse( response.body, symbolize_names: true ) rescue nil )
|
|
36
|
+
|
|
37
|
+
result = if response.success?
|
|
38
|
+
GoogleNewsPortalResult.new( attributes || {} )
|
|
39
|
+
else
|
|
40
|
+
ErrorResult.new( response.status, attributes )
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
ResponseMethods.install( response, result )
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def topic( topic_token, options = nil, &block )
|
|
47
|
+
if options
|
|
48
|
+
options = options.is_a?( GoogleNewsPortalOptions ) ? options : GoogleNewsPortalOptions.build!( options.to_h )
|
|
49
|
+
options = options.to_h
|
|
50
|
+
else
|
|
51
|
+
options = { engine: 'google_news_portal' }
|
|
52
|
+
end
|
|
53
|
+
options[ :topic_token ] = topic_token.to_s
|
|
54
|
+
|
|
55
|
+
response = get( "#{ BASE_URI }/search", options, &block )
|
|
56
|
+
attributes = ( JSON.parse( response.body, symbolize_names: true ) rescue nil )
|
|
57
|
+
|
|
58
|
+
result = if response.success?
|
|
59
|
+
GoogleNewsPortalResult.new( attributes || {} )
|
|
60
|
+
else
|
|
61
|
+
ErrorResult.new( response.status, attributes )
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
ResponseMethods.install( response, result )
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def publication( publication_token, options = nil, &block )
|
|
68
|
+
if options
|
|
69
|
+
options = options.is_a?( GoogleNewsPortalOptions ) ? options : GoogleNewsPortalOptions.build!( options.to_h )
|
|
70
|
+
options = options.to_h
|
|
71
|
+
else
|
|
72
|
+
options = { engine: 'google_news_portal' }
|
|
73
|
+
end
|
|
74
|
+
options[ :publication_token ] = publication_token.to_s
|
|
75
|
+
|
|
76
|
+
response = get( "#{ BASE_URI }/search", options, &block )
|
|
77
|
+
attributes = ( JSON.parse( response.body, symbolize_names: true ) rescue nil )
|
|
78
|
+
|
|
79
|
+
result = if response.success?
|
|
80
|
+
GoogleNewsPortalResult.new( attributes || {} )
|
|
81
|
+
else
|
|
82
|
+
ErrorResult.new( response.status, attributes )
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
ResponseMethods.install( response, result )
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module SearchAPI
|
|
4
|
+
|
|
5
|
+
GoogleNewsPortalMetadataSchema = DynamicSchema::Struct.define do
|
|
6
|
+
id String
|
|
7
|
+
status String
|
|
8
|
+
created_at String, as: :created_at
|
|
9
|
+
request_time_taken Float, as: :request_time_taken
|
|
10
|
+
parsing_time_taken Float, as: :parsing_time_taken
|
|
11
|
+
total_time_taken Float, as: :total_time_taken
|
|
12
|
+
request_url String, as: :request_url
|
|
13
|
+
html_url String, as: :html_url
|
|
14
|
+
json_url String, as: :json_url
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class GoogleNewsPortalMetadata < GoogleNewsPortalMetadataSchema
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
GoogleNewsPortalParametersSchema = DynamicSchema::Struct.define do
|
|
21
|
+
engine String
|
|
22
|
+
q String
|
|
23
|
+
ceid String
|
|
24
|
+
story_token String, as: :story_token
|
|
25
|
+
topic_token String, as: :topic_token
|
|
26
|
+
publication_token String, as: :publication_token
|
|
27
|
+
section_token String, as: :section_token
|
|
28
|
+
sort_by String, as: :sort_by
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class GoogleNewsPortalParameters < GoogleNewsPortalParametersSchema
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
GoogleNewsPortalSourceSchema = DynamicSchema::Struct.define do
|
|
35
|
+
name String
|
|
36
|
+
favicon String
|
|
37
|
+
authors String, array: true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class GoogleNewsPortalSource < GoogleNewsPortalSourceSchema
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
GoogleNewsPortalArticleSchema = DynamicSchema::Struct.define do
|
|
44
|
+
position Integer
|
|
45
|
+
title String
|
|
46
|
+
link String
|
|
47
|
+
thumbnail String
|
|
48
|
+
iso_date String, as: :iso_date
|
|
49
|
+
story_token String, as: :story_token
|
|
50
|
+
story_title String, as: :story_title
|
|
51
|
+
section String
|
|
52
|
+
source GoogleNewsPortalSource
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class GoogleNewsPortalArticle < GoogleNewsPortalArticleSchema
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
GoogleNewsPortalMenuTopicSchema = DynamicSchema::Struct.define do
|
|
59
|
+
title String
|
|
60
|
+
topic_token String, as: :topic_token
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class GoogleNewsPortalMenuTopic < GoogleNewsPortalMenuTopicSchema
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
GoogleNewsPortalRelatedTopicSchema = DynamicSchema::Struct.define do
|
|
67
|
+
title String
|
|
68
|
+
topic_token String, as: :topic_token
|
|
69
|
+
thumbnail String
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class GoogleNewsPortalRelatedTopic < GoogleNewsPortalRelatedTopicSchema
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
GoogleNewsPortalRelatedPublicationSchema = DynamicSchema::Struct.define do
|
|
76
|
+
name String
|
|
77
|
+
publication_token String, as: :publication_token
|
|
78
|
+
thumbnail String
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class GoogleNewsPortalRelatedPublication < GoogleNewsPortalRelatedPublicationSchema
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
GoogleNewsPortalSubMenuSectionSchema = DynamicSchema::Struct.define do
|
|
85
|
+
title String
|
|
86
|
+
section_token String, as: :section_token
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class GoogleNewsPortalSubMenuSection < GoogleNewsPortalSubMenuSectionSchema
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
GoogleNewsPortalPostOnXSchema = DynamicSchema::Struct.define do
|
|
93
|
+
link String
|
|
94
|
+
snippet String
|
|
95
|
+
author String
|
|
96
|
+
author_link String, as: :author_link
|
|
97
|
+
author_thumbnail String, as: :author_thumbnail
|
|
98
|
+
date String
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class GoogleNewsPortalPostOnX < GoogleNewsPortalPostOnXSchema
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
GoogleNewsPortalFAQSchema = DynamicSchema::Struct.define do
|
|
105
|
+
question String
|
|
106
|
+
answer String
|
|
107
|
+
link String
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
class GoogleNewsPortalFAQ < GoogleNewsPortalFAQSchema
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
GoogleNewsPortalResultSchema = DynamicSchema::Struct.define do
|
|
114
|
+
search_metadata GoogleNewsPortalMetadata, as: :search_metadata
|
|
115
|
+
search_parameters GoogleNewsPortalParameters, as: :search_parameters
|
|
116
|
+
organic_results GoogleNewsPortalArticle, array: true, as: :organic_results
|
|
117
|
+
menu_topics GoogleNewsPortalMenuTopic, array: true, as: :menu_topics
|
|
118
|
+
related_topics GoogleNewsPortalRelatedTopic, array: true, as: :related_topics
|
|
119
|
+
related_publications GoogleNewsPortalRelatedPublication, array: true, as: :related_publications
|
|
120
|
+
sub_menu_sections GoogleNewsPortalSubMenuSection, array: true, as: :sub_menu_sections
|
|
121
|
+
posts_on_x GoogleNewsPortalPostOnX, array: true, as: :posts_on_x
|
|
122
|
+
frequently_asked_questions GoogleNewsPortalFAQ, array: true, as: :frequently_asked_questions
|
|
123
|
+
error String
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class GoogleNewsPortalResult < GoogleNewsPortalResultSchema
|
|
127
|
+
extend Forwardable
|
|
128
|
+
include Enumerable
|
|
129
|
+
|
|
130
|
+
def_delegators :organic_results, :each, :[], :count, :size, :length, :first, :last, :empty?
|
|
131
|
+
|
|
132
|
+
def success?
|
|
133
|
+
self.error.nil?
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class GoogleNewsRequest < Request
|
|
3
|
+
|
|
4
|
+
def search( query, options = nil, &block )
|
|
5
|
+
if options
|
|
6
|
+
options = options.is_a?( GoogleNewsOptions ) ? options : GoogleNewsOptions.build!( options.to_h )
|
|
7
|
+
options = options.to_h
|
|
8
|
+
else
|
|
9
|
+
options = { engine: 'google_news' }
|
|
10
|
+
end
|
|
11
|
+
options[ :q ] = query.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
|
+
GoogleNewsResult.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,129 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module SearchAPI
|
|
4
|
+
|
|
5
|
+
GoogleNewsMetadataSchema = DynamicSchema::Struct.define do
|
|
6
|
+
id String
|
|
7
|
+
status String
|
|
8
|
+
created_at String, as: :created_at
|
|
9
|
+
request_time_taken Float, as: :request_time_taken
|
|
10
|
+
parsing_time_taken Float, as: :parsing_time_taken
|
|
11
|
+
total_time_taken Float, as: :total_time_taken
|
|
12
|
+
request_url String, as: :request_url
|
|
13
|
+
html_url String, as: :html_url
|
|
14
|
+
json_url String, as: :json_url
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class GoogleNewsMetadata < GoogleNewsMetadataSchema
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
GoogleNewsParametersSchema = DynamicSchema::Struct.define do
|
|
21
|
+
engine String
|
|
22
|
+
q String
|
|
23
|
+
device String
|
|
24
|
+
uule String
|
|
25
|
+
location String
|
|
26
|
+
location_used String, as: :location_used
|
|
27
|
+
google_domain String, as: :google_domain
|
|
28
|
+
hl String
|
|
29
|
+
gl String
|
|
30
|
+
lr String
|
|
31
|
+
cr String
|
|
32
|
+
nfpr String
|
|
33
|
+
filter String
|
|
34
|
+
safe String
|
|
35
|
+
page String
|
|
36
|
+
time_period String, as: :time_period
|
|
37
|
+
time_period_min String, as: :time_period_min
|
|
38
|
+
time_period_max String, as: :time_period_max
|
|
39
|
+
sort_by String, as: :sort_by
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class GoogleNewsParameters < GoogleNewsParametersSchema
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
GoogleNewsSearchInformationSchema = DynamicSchema::Struct.define do
|
|
46
|
+
query_displayed String, as: :query_displayed
|
|
47
|
+
total_results Integer, as: :total_results
|
|
48
|
+
page Integer
|
|
49
|
+
time_taken_displayed Float, as: :time_taken_displayed
|
|
50
|
+
detected_location String, as: :detected_location
|
|
51
|
+
did_you_mean String, as: :did_you_mean
|
|
52
|
+
has_no_results_for [ TrueClass, FalseClass ], as: :has_no_results_for
|
|
53
|
+
showing_results_for String, as: :showing_results_for
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class GoogleNewsSearchInformation < GoogleNewsSearchInformationSchema
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
GoogleNewsArticleSchema = DynamicSchema::Struct.define do
|
|
60
|
+
position Integer
|
|
61
|
+
title String
|
|
62
|
+
link String
|
|
63
|
+
source String
|
|
64
|
+
date String
|
|
65
|
+
snippet String
|
|
66
|
+
is_live [ TrueClass, FalseClass ], as: :is_live
|
|
67
|
+
favicon String
|
|
68
|
+
thumbnail String
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class GoogleNewsArticle < GoogleNewsArticleSchema
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
GoogleNewsTopStorySchema = DynamicSchema::Struct.define do
|
|
75
|
+
title String
|
|
76
|
+
link String
|
|
77
|
+
author String
|
|
78
|
+
author_link String, as: :author_link
|
|
79
|
+
source String
|
|
80
|
+
date String
|
|
81
|
+
snippet String
|
|
82
|
+
is_live [ TrueClass, FalseClass ], as: :is_live
|
|
83
|
+
is_video [ TrueClass, FalseClass ], as: :is_video
|
|
84
|
+
thumbnail String
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class GoogleNewsTopStory < GoogleNewsTopStorySchema
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
GoogleNewsMoreLinkSchema = DynamicSchema::Struct.define do
|
|
91
|
+
link String
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class GoogleNewsMoreLink < GoogleNewsMoreLinkSchema
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
GoogleNewsPaginationSchema = DynamicSchema::Struct.define do
|
|
98
|
+
current Integer
|
|
99
|
+
previous String
|
|
100
|
+
_value :next, type: String
|
|
101
|
+
other_pages Hash, as: :other_pages
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class GoogleNewsPagination < GoogleNewsPaginationSchema
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
GoogleNewsResultSchema = DynamicSchema::Struct.define do
|
|
108
|
+
search_metadata GoogleNewsMetadata, as: :search_metadata
|
|
109
|
+
search_parameters GoogleNewsParameters, as: :search_parameters
|
|
110
|
+
search_information GoogleNewsSearchInformation, as: :search_information
|
|
111
|
+
organic_results GoogleNewsArticle, array: true, as: :organic_results
|
|
112
|
+
top_stories GoogleNewsTopStory, array: true, as: :top_stories
|
|
113
|
+
top_stories_more_link GoogleNewsMoreLink, as: :top_stories_more_link
|
|
114
|
+
pagination GoogleNewsPagination
|
|
115
|
+
error String
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class GoogleNewsResult < GoogleNewsResultSchema
|
|
119
|
+
extend Forwardable
|
|
120
|
+
include Enumerable
|
|
121
|
+
|
|
122
|
+
def_delegators :organic_results, :each, :[], :count, :size, :length, :first, :last, :empty?
|
|
123
|
+
|
|
124
|
+
def success?
|
|
125
|
+
self.error.nil?
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class GoogleScholarOptions
|
|
3
|
+
include DynamicSchema::Definable
|
|
4
|
+
include Helpers
|
|
5
|
+
|
|
6
|
+
SAFE_SEARCH = %w[ active off ]
|
|
7
|
+
NORMALIZE_DOWNCASE = ->(v) { v.to_s.downcase }
|
|
8
|
+
|
|
9
|
+
schema do
|
|
10
|
+
q String
|
|
11
|
+
cites String
|
|
12
|
+
cluster String
|
|
13
|
+
hl String
|
|
14
|
+
lr String
|
|
15
|
+
safe String, in: SAFE_SEARCH, normalize: NORMALIZE_DOWNCASE
|
|
16
|
+
filter Integer
|
|
17
|
+
as_ylo Integer
|
|
18
|
+
as_yhi Integer
|
|
19
|
+
scisbd Integer
|
|
20
|
+
as_vis Integer
|
|
21
|
+
as_rr Integer
|
|
22
|
+
as_sdt String
|
|
23
|
+
source String
|
|
24
|
+
num Integer, in: 1..20
|
|
25
|
+
page Integer
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.build( options = nil, &block )
|
|
29
|
+
new( api_options: builder.build( options, &block ) )
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.build!( options = nil, &block )
|
|
33
|
+
new( api_options: builder.build!( options, &block ) )
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def initialize( options = {}, api_options: nil )
|
|
37
|
+
@options = self.class.builder.build( options || {} )
|
|
38
|
+
@options = api_options.merge( @options ) if api_options
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def to_h
|
|
42
|
+
result = @options.to_h
|
|
43
|
+
result[ :engine ] = 'google_scholar'
|
|
44
|
+
result
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module SearchAPI
|
|
2
|
+
class GoogleScholarRequest < Request
|
|
3
|
+
|
|
4
|
+
def search( query = nil, options = nil, &block )
|
|
5
|
+
if options
|
|
6
|
+
options = options.is_a?( GoogleScholarOptions ) ? options : GoogleScholarOptions.build!( options.to_h )
|
|
7
|
+
options = options.to_h
|
|
8
|
+
else
|
|
9
|
+
options = { engine: 'google_scholar' }
|
|
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
|
+
GoogleScholarResult.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,195 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module SearchAPI
|
|
4
|
+
|
|
5
|
+
GoogleScholarMetadataSchema = DynamicSchema::Struct.define do
|
|
6
|
+
id String
|
|
7
|
+
status String
|
|
8
|
+
created_at String, as: :created_at
|
|
9
|
+
request_time_taken Float, as: :request_time_taken
|
|
10
|
+
parsing_time_taken Float, as: :parsing_time_taken
|
|
11
|
+
total_time_taken Float, as: :total_time_taken
|
|
12
|
+
request_url String, as: :request_url
|
|
13
|
+
html_url String, as: :html_url
|
|
14
|
+
json_url String, as: :json_url
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class GoogleScholarMetadata < GoogleScholarMetadataSchema
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
GoogleScholarParametersSchema = DynamicSchema::Struct.define do
|
|
21
|
+
engine String
|
|
22
|
+
q String
|
|
23
|
+
cites String
|
|
24
|
+
cluster String
|
|
25
|
+
hl String
|
|
26
|
+
lr String
|
|
27
|
+
scisbd Integer
|
|
28
|
+
as_ylo Integer, as: :as_ylo
|
|
29
|
+
as_yhi Integer, as: :as_yhi
|
|
30
|
+
as_rr Integer, as: :as_rr
|
|
31
|
+
as_vis Integer, as: :as_vis
|
|
32
|
+
as_sdt String, as: :as_sdt
|
|
33
|
+
filter Integer
|
|
34
|
+
safe String
|
|
35
|
+
source String
|
|
36
|
+
num Integer
|
|
37
|
+
page Integer
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class GoogleScholarParameters < GoogleScholarParametersSchema
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
GoogleScholarDidYouMeanSchema = DynamicSchema::Struct.define do
|
|
44
|
+
text String
|
|
45
|
+
link String
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class GoogleScholarDidYouMean < GoogleScholarDidYouMeanSchema
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
GoogleScholarSearchInformationSchema = DynamicSchema::Struct.define do
|
|
52
|
+
total_results Integer, as: :total_results
|
|
53
|
+
page Integer
|
|
54
|
+
time_taken_displayed Float, as: :time_taken_displayed
|
|
55
|
+
query_displayed String, as: :query_displayed
|
|
56
|
+
did_you_mean GoogleScholarDidYouMean, as: :did_you_mean
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class GoogleScholarSearchInformation < GoogleScholarSearchInformationSchema
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
GoogleScholarCitedBySchema = DynamicSchema::Struct.define do
|
|
63
|
+
total Integer
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class GoogleScholarCitedBy < GoogleScholarCitedBySchema
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
GoogleScholarProfileSchema = DynamicSchema::Struct.define do
|
|
70
|
+
name String
|
|
71
|
+
link String
|
|
72
|
+
author_id String, as: :author_id
|
|
73
|
+
affiliations String
|
|
74
|
+
email String
|
|
75
|
+
cited_by GoogleScholarCitedBy, as: :cited_by
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class GoogleScholarProfile < GoogleScholarProfileSchema
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
GoogleScholarOrganizationSchema = DynamicSchema::Struct.define do
|
|
82
|
+
name String
|
|
83
|
+
link String
|
|
84
|
+
org_id String, as: :org_id
|
|
85
|
+
university String
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class GoogleScholarOrganization < GoogleScholarOrganizationSchema
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
GoogleScholarResourceSchema = DynamicSchema::Struct.define do
|
|
92
|
+
name String
|
|
93
|
+
format String
|
|
94
|
+
link String
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class GoogleScholarResource < GoogleScholarResourceSchema
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
GoogleScholarAuthorSchema = DynamicSchema::Struct.define do
|
|
101
|
+
name String
|
|
102
|
+
id String
|
|
103
|
+
link String
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class GoogleScholarAuthor < GoogleScholarAuthorSchema
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
GoogleScholarCitedByLinkSchema = DynamicSchema::Struct.define do
|
|
110
|
+
total Integer
|
|
111
|
+
link String
|
|
112
|
+
cites_id String, as: :cites_id
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
class GoogleScholarCitedByLink < GoogleScholarCitedByLinkSchema
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
GoogleScholarVersionsSchema = DynamicSchema::Struct.define do
|
|
119
|
+
total Integer
|
|
120
|
+
link String
|
|
121
|
+
cluster_id String, as: :cluster_id
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class GoogleScholarVersions < GoogleScholarVersionsSchema
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
GoogleScholarInlineLinksSchema = DynamicSchema::Struct.define do
|
|
128
|
+
cited_by GoogleScholarCitedByLink, as: :cited_by
|
|
129
|
+
versions GoogleScholarVersions
|
|
130
|
+
related_articles_link String, as: :related_articles_link
|
|
131
|
+
cached_page_link String, as: :cached_page_link
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
class GoogleScholarInlineLinks < GoogleScholarInlineLinksSchema
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
GoogleScholarArticleSchema = DynamicSchema::Struct.define do
|
|
138
|
+
position Integer
|
|
139
|
+
title String
|
|
140
|
+
link String
|
|
141
|
+
data_cid String, as: :data_cid
|
|
142
|
+
type String
|
|
143
|
+
publication String
|
|
144
|
+
snippet String
|
|
145
|
+
resource GoogleScholarResource
|
|
146
|
+
authors GoogleScholarAuthor, array: true
|
|
147
|
+
inline_links GoogleScholarInlineLinks, as: :inline_links
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
class GoogleScholarArticle < GoogleScholarArticleSchema
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
GoogleScholarRelatedSearchSchema = DynamicSchema::Struct.define do
|
|
154
|
+
query String
|
|
155
|
+
highlighted String, array: true
|
|
156
|
+
link String
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
class GoogleScholarRelatedSearch < GoogleScholarRelatedSearchSchema
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
GoogleScholarPaginationSchema = DynamicSchema::Struct.define do
|
|
163
|
+
current Integer
|
|
164
|
+
previous String
|
|
165
|
+
_value :next, type: String
|
|
166
|
+
other_pages Hash, as: :other_pages
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
class GoogleScholarPagination < GoogleScholarPaginationSchema
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
GoogleScholarResultSchema = DynamicSchema::Struct.define do
|
|
173
|
+
search_metadata GoogleScholarMetadata, as: :search_metadata
|
|
174
|
+
search_parameters GoogleScholarParameters, as: :search_parameters
|
|
175
|
+
search_information GoogleScholarSearchInformation, as: :search_information
|
|
176
|
+
profiles GoogleScholarProfile, array: true
|
|
177
|
+
organizations GoogleScholarOrganization, array: true
|
|
178
|
+
organic_results GoogleScholarArticle, array: true, as: :organic_results
|
|
179
|
+
related_searches GoogleScholarRelatedSearch, array: true, as: :related_searches
|
|
180
|
+
pagination GoogleScholarPagination
|
|
181
|
+
error String
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
class GoogleScholarResult < GoogleScholarResultSchema
|
|
185
|
+
extend Forwardable
|
|
186
|
+
include Enumerable
|
|
187
|
+
|
|
188
|
+
def_delegators :organic_results, :each, :[], :count, :size, :length, :first, :last, :empty?
|
|
189
|
+
|
|
190
|
+
def success?
|
|
191
|
+
self.error.nil?
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
end
|