Skip to content

Commit 5cee00d

Browse files
committed
rename API_KEY to SERPAPI_KEY
minor doc improvements
1 parent 32cdb5a commit 5cee00d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+287
-247
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ jobs:
2222
run: bundle exec rake lint
2323
- name: tests
2424
env:
25-
API_KEY: ${{ secrets.API_KEY }}
25+
SERPAPI_KEY: ${{ secrets.SERPAPI_KEY }}
2626
run: bundle exec rake test
2727
- name: oobt
2828
env:
29-
API_KEY: ${{ secrets.API_KEY }}
29+
SERPAPI_KEY: ${{ secrets.SERPAPI_KEY }}
3030
run: bundle exec rake oobt

README.md

Lines changed: 81 additions & 71 deletions
Large diffs are not rendered by default.

README.md.erb

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def snippet(format, path, demo = false)
1313
slice.map! { |l| l.gsub(/(^\s\s\s\s)/, '')}
1414
buf = slice.join
1515
buf.gsub!('# pp ', 'pp ')
16-
buf.gsub!('api_key)', "ENV['API_KEY'])")
16+
buf.gsub!('api_key)', "ENV['SERPAPI_KEY'])")
1717
end
1818
%Q(```#{format}\nrequire 'serpapi'\n#{buf}```\n\n * source code: [#{path}](https://github.com/serpapi/serpapi-ruby/blob/master/#{path}))
1919
end
@@ -26,20 +26,19 @@ end
2626
[![Gem Version](https://badge.fury.io/rb/serpapi.svg)](https://badge.fury.io/rb/serpapi) [![serpapi-ruby](https://github.com/serpapi/serpapi-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/serpapi/serpapi-ruby/actions/workflows/ci.yml)
2727
</div>
2828

29-
Integrate search data into your Ruby application. This library is the official wrapper for SerpApi (https://serpapi.com).
29+
Integrate search data into your AI workflow or ruby application. This library is the official wrapper for [SerpApi](https://serpapi.com).
3030
SerpApi supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and more.
3131
Fast query at scale a vast range of data, including web search results, flight schedule, stock market data, news headlines, and more.
3232

3333
## Features
34-
* `persistent`:Keep socket connection open to save on SSL handshake / reconnection (2x
35-
faster). [default: true] [Search at scale](#Search-At-Scale)
36-
* `async`: [Boolean] Support non-blocking job submission. [default: false] [Search Asynchronous](#Search-Asynchronous)
37-
* extensive documentations
38-
* real world examples
34+
* `persistent` → Keep socket connection open to save on SSL handshake / reconnection (2x faster). [Search at scale](#Search-At-Scale)
35+
* `async` → Support non-blocking job submission. [Search Asynchronous](#Search-Asynchronous)
36+
* extensive documentation → easy to follow
37+
* real world examples → included throughout
3938

4039
## Installation
4140

42-
To achieve optimal performance, it is essential to have Ruby 3.x (preferably version 3.4) installed.
41+
To achieve optimal performance, it is essential to have Ruby 3.1+ (preferably version 3.4) installed.
4342

4443
| Older versions such as Ruby 1.9, 2.x, and JRuby are compatible with [serpapi older library](https://github.com/serpapi/google-search-results-ruby), which continues to function effectively.
4544

@@ -67,8 +66,12 @@ pp results
6766
This example runs a search for "coffee" on Google. It then returns the results as a regular Ruby Hash.
6867
See the [playground](https://serpapi.com/playground) to generate your own code.
6968

70-
The `SERPAPI_KEY` should be replaced with your actual API key obtained from
71-
https://serpapi.com/users/sign_up?plan=free.
69+
The SerpApi key can be obtained from [serpapi.com/signup](https://serpapi.com/users/sign_up?plan=free).
70+
71+
Environment variables are a secure, safe, and easy way to manage secrets.
72+
Set `export SERPAPI_KEY=<secret_serpapi_key>` in your shell.
73+
Ruby accesses these variables from `ENV['SERPAPI_KEY']`.
74+
7275

7376
## Search API advanced Usage
7477

@@ -80,10 +83,10 @@ require 'serpapi'
8083
client = SerpApi::Client.new(
8184
engine: 'google',
8285
api_key: ENV['SERPAPI_KEY'],
83-
# HTTP client behavior
84-
async: false, # non blocking HTTP request see [Search Asynchronous](#Search-Asynchronous)
85-
persistent: true, # leave socket connection open for faster response time [Search at scale](#Search-At-Scale)
86-
timeout: 5, # HTTP timeout in seconds on the client side only.
86+
# HTTP client configuration
87+
async: false, # non blocking HTTP request see: Search Asynchronous (default: false)
88+
persistent: true, # leave socket connection open for faster response time see: Search at scale (default: true)
89+
timeout: 5, # HTTP timeout in seconds on the client side only. (default: 120s)
8790
)
8891

8992
# search query overview (more fields available depending on search engine)
@@ -136,7 +139,7 @@ Search API features non-blocking search using the option: `async=true`.
136139

137140
Search API enables `async` search.
138141
- Non-blocking (`async=true`) : the development is more complex, but this allows handling many simultaneous connections.
139-
- Blocking (`async=false`) : it's easy to write the code but more compute-intensive when the parent process needs to hold many connections.
142+
- Blocking (`async=false`) : it is easy to write the code but more compute-intensive when the parent process needs to hold many connections.
140143

141144
Here is an example of asynchronous searches using Ruby
142145
<%= snippet('ruby', 'demo/demo_async.rb', true) %>
@@ -153,7 +156,7 @@ require 'connection_pool'
153156

154157
# create a thread pool of 4 threads with a persistent connection to serpapi.com
155158
pool = ConnectionPool.new(size: n, timeout: 5) do
156-
SerpApi::Client.new(engine: 'google', api_key: ENV['API_KEY'], timeout: 30, persistent: true)
159+
SerpApi::Client.new(engine: 'google', api_key: ENV['SERPAPI_KEY'], timeout: 30, persistent: true)
157160
end
158161

159162
# run user thread to search for your favorites coffee type
@@ -524,7 +527,7 @@ The directory spec/ includes specification which serves the dual purposes of exa
524527

525528
Set your secret API key in your shell before running a test.
526529
```bash
527-
export API_KEY="your_secret_key"
530+
export SERPAPI_KEY="your_secret_key"
528531
```
529532
Install testing dependency
530533
```bash

Rakefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ end
8888

8989
# private
9090
task :check do
91-
if ENV['API_KEY']
92-
puts 'check: found $API_KEY'
91+
if ENV['SERPAPI_KEY']
92+
puts 'check: found $SERPAPI_KEY'
9393
else
94-
puts 'check: API_KEY must be defined'
94+
puts 'check: SERPAPI_KEY must be defined'
9595
exit 1
9696
end
9797
end

demo/demo.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
#
44
# **Key Points:**
55
#
6-
# * **API Key:** The code requires an API key to be set in the `API_KEY` environment variable.
7-
# * **Serpapi Client:** A SerpApi client is created with default parameters, including the engine, client, language,
6+
# * **API Key:** The code requires an API key to be set in the `SERPAPI_KEY` environment variable.
7+
# * **Serpapi Client:** A SerpApi client is created with default parameters, including the engine, client, language,
88
# country, API key, persistence settings, and timeout.
99
# * **Search Parameters:** A search request is made with the query "coffee".
1010
# * **Suggestions Retrieval:** The `suggestions` key in the response is checked for availability and non-emptiness.
1111
# * **Output:** The suggestions are printed using the `pp` gem.
1212
#
1313
# **Purpose:**
1414
#
15-
# The code is designed to demonstrate how to use the SerpApi client to retrieve autocomplete suggestions from Google. It
15+
# The code is designed to demonstrate how to use the SerpApi client to retrieve autocomplete suggestions from Google. It
1616
# verifies that suggestions are returned and outputs them for demonstration purposes.
1717
#
1818
# **Usage:**
1919
#
20-
# To run the code, you need to set the `API_KEY` environment variable to your actual SerpApi API key.
20+
# To run the code, you need to set the `SERPAPI_KEY` environment variable to your actual SerpApi API key.
2121
# Obtain your free key from: serpapi.com
2222
#
2323
# **Output:**
@@ -34,14 +34,14 @@
3434
require 'serpapi'
3535
require 'pp'
3636

37-
raise 'API_KEY environment variable must be set' if ENV['API_KEY'].nil?
37+
raise 'SERPAPI_KEY environment variable must be set' if ENV['SERPAPI_KEY'].nil?
3838

3939
default_params = {
4040
engine: 'google_autocomplete',
4141
client: 'safari',
4242
hl: 'en',
4343
gl: 'us',
44-
api_key: ENV['API_KEY'],
44+
api_key: ENV.fetch('SERPAPI_KEY', nil),
4545
persistent: false,
4646
timeout: 2
4747
}

demo/demo_async.rb

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,73 @@
22
# The request are non-blocking which allows batching a large amount of query, and wait before fetching the result back.
33
#
44
# **Process:**
5-
# 1. **Request Queue:** The company list is iterated over, and each company is queried using the SerpApi client. Requests
5+
# 1. **Request Queue:** The company list is iterated over, and each company is queried using the SerpApi client. Requests
66
# are stored in a queue to avoid blocking the main thread.
77
#
8-
# 2. **Client Retrieval:** After each request, the code checks the status of the search result. If it's cached or
9-
# successful, the company name is printed, and the request is skipped. Otherwise, the result is added to the queue for
8+
# 2. **Client Retrieval:** After each request, the code checks the status of the search result. If it's cached or
9+
# successful, the company name is printed, and the request is skipped. Otherwise, the result is added to the queue for
1010
# further processing.
1111
#
12-
# 3. **Queue Processing:** The queue is processed until it's empty. In each iteration, the last result is retrieved and
12+
# 3. **Queue Processing:** The queue is processed until it's empty. In each iteration, the last result is retrieved and
1313
# its client ID is extracted.
1414
#
15-
# 4. **Archived Client Retrieval:** Using the client ID, the code retrieves the archived client and checks its status. If
16-
# it's cached or successful, the company name is printed, and the client is skipped. Otherwise, the result is added back
15+
# 4. **Archived Client Retrieval:** Using the client ID, the code retrieves the archived client and checks its status. If
16+
# it's cached or successful, the company name is printed, and the client is skipped. Otherwise, the result is added back
1717
# to the queue for further processing.
1818
#
1919
# 5. **Completion:** The queue is closed, and a message is printed indicating that the process is complete.
2020
#
21-
# * **Asynchronous Requests:** The `async: true` option ensures that search requests are processed in parallel, improving
21+
# * **Asynchronous Requests:** The `async: true` option ensures that search requests are processed in parallel, improving
2222
# efficiency.
2323
# * **Queue Management:** The queue allows requests to be processed asynchronously without blocking the main thread.
2424
# * **Status Checking:** The code checks the status of each search result before processing it, avoiding unnecessary work.
2525
# * **Queue Processing:** The queue ensures that all requests are processed in the order they were submitted.
2626

27-
# **Overall, the code snippet demonstrates a well-structured approach to improve the efficiency of searching for company
27+
# **Overall, the code snippet demonstrates a well-structured approach to improve the efficiency of searching for company
2828
# information using SerpApi.**
2929

3030
# load serpapi library
3131
require 'serpapi'
3232

3333
# target MAANG companies
34-
company_list = %w(meta amazon apple netflix google)
35-
client = SerpApi::Client.new(engine: 'google', async: true, persistent: true, api_key: ENV['API_KEY'])
34+
company_list = %w[meta amazon apple netflix google]
35+
client = SerpApi::Client.new(engine: 'google', async: true, persistent: true, api_key: ENV.fetch('SERPAPI_KEY', nil))
3636
search_queue = Queue.new
3737
company_list.each do |company|
3838
# store request into a search_queue - no-blocker
39-
result = client.search({q: company})
40-
if result[:search_metadata][:status] =~ /Cached|Success/
39+
result = client.search({ q: company })
40+
if result[:search_metadata][:status] =~ /Cached/
4141
puts "#{company}: search results found in cache for: #{company}"
42-
next
4342
end
4443

4544
# add results to the client queue
46-
search_queue.push(result)
45+
search_queue.push(result[:search_metadata][:id])
4746
end
4847

49-
puts "wait until all searches are cached or success"
50-
while !search_queue.empty?
51-
result = search_queue.pop
48+
# wait for all requests to be completed
49+
puts 'wait for all requests to be completed'
50+
# wait for 10 seconds to allow all requests to be processed
51+
sleep(10)
52+
53+
puts 'wait until all searches are cached or success'
54+
until search_queue.empty?
5255
# extract client id
53-
search_id = result[:search_metadata][:id]
56+
search_id = search_queue.pop
5457

5558
# retrieve client from the archive - blocker
5659
search_archived = client.search_archive(search_id)
60+
61+
# read original company name from the search parameters
62+
company = search_archived[:search_parameters][:q]
63+
64+
# check if the search is cached or successful
5765
if search_archived[:search_metadata][:status] =~ /Cached|Success/
5866
puts "#{search_archived[:search_parameters][:q]}: search results found in archive for: #{company}"
5967
next
6068
end
6169

62-
# add results to the client queue
70+
# add results back to the client queue
71+
# if the search is still in progress
6372
search_queue.push(result)
6473
end
6574

demo/demo_thread_pool.rb

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,54 @@
1-
2-
# The provided code snippet is a Ruby spec test case that
3-
# demonstrates the use of thread pools to execute multiple HTTP
1+
# The provided code snippet is a Ruby spec test case that
2+
# demonstrates the use of thread pools to execute multiple HTTP
43
# requests concurrently.
54
#
65
# **Key Points:**
76
#
8-
# * The `connection_pool` gem is used to create a thread pool of
7+
# * The `connection_pool` gem is used to create a thread pool of
98
# `HTTP` connections.
10-
# * The `Thread` class is used to spawn multiple threads, each of
9+
# * The `Thread` class is used to spawn multiple threads, each of
1110
# which makes a GET request to the specified endpoint.
12-
# * The `pool.with` method is used to acquire a connection from the
11+
# * The `pool.with` method is used to acquire a connection from the
1312
# thread pool and use it to make the HTTP request.
1413
# * The `to_s` method converts the HTTP response to a string.
15-
# * The `total` method from the `Benchmark` class is used to measure
14+
# * The `total` method from the `Benchmark` class is used to measure
1615
# the total execution time of the code block.
1716

1817
# **Purpose:**
1918

20-
# The code aims to demonstrate how thread pools can be used to
21-
# improve performance by executing multiple tasks concurrently. In
22-
# this case, it makes multiple HTTP requests to an API endpoint using
19+
# The code aims to demonstrate how thread pools can be used to
20+
# improve performance by executing multiple tasks concurrently. In
21+
# this case, it makes multiple HTTP requests to an API endpoint using
2322
# a thread pool of connections.
2423
#
2524
# **Benefits:**
2625
#
27-
# * Improved performance by avoiding the overhead of creating and
26+
# * Improved performance by avoiding the overhead of creating and
2827
# destroying connections for each request.
29-
# * Efficient use of resources by sharing connections among multiple
28+
# * Efficient use of resources by sharing connections among multiple
3029
# threads.
31-
# * Concurrency and parallelism, allowing multiple requests to be
30+
# * Concurrency and parallelism, allowing multiple requests to be
3231
# processed simultaneously.
3332
#
3433
# **Usage:**
3534
#
36-
# The code snippet can be used as a reference to implement thread
37-
# pools in Ruby applications. It provides an example of how to use
38-
# the `connection_pool` gem to create a thread pool of connections
35+
# The code snippet can be used as a reference to implement thread
36+
# pools in Ruby applications. It provides an example of how to use
37+
# the `connection_pool` gem to create a thread pool of connections
3938
# and make concurrent HTTP requests.
4039
#
4140
# **Additional Notes:**
4241
#
43-
# * The number of threads created should be set to an appropriate
44-
# value based on the available resources and the expected request
42+
# * The number of threads created should be set to an appropriate
43+
# value based on the available resources and the expected request
4544
# load.
46-
# * The `timeout` option in the `ConnectionPool` constructor
47-
# specifies the maximum time a thread should wait to acquire a
45+
# * The `timeout` option in the `ConnectionPool` constructor
46+
# specifies the maximum time a thread should wait to acquire a
4847
# connection from the pool.
49-
# * The `HTTP.persistent` method is used to create persistent
50-
# connections, which can improve performance by reusing connections
48+
# * The `HTTP.persistent` method is used to create persistent
49+
# connections, which can improve performance by reusing connections
5150
# between requests.
52-
# * The `benchmark` gem is used to measure the execution time of the
51+
# * The `benchmark` gem is used to measure the execution time of the
5352
# code block.
5453
# reference: https://github.com/httprb/http/wiki/Thread-Safety
5554

@@ -59,18 +58,18 @@
5958

6059
# number of thread == number of HTTP persistent connection
6160
n = 4
62-
runtime = Benchmark.measure do
61+
runtime = Benchmark.measure do
6362
# create a thread pool of 4 threads with a persistent connection to serpapi.com
6463
pool = ConnectionPool.new(size: n, timeout: 5) do
65-
SerpApi::Client.new(engine: 'google', api_key: ENV['API_KEY'], timeout: 30, persistent: true)
64+
SerpApi::Client.new(engine: 'google', api_key: ENV.fetch('SERPAPI_KEY', nil), timeout: 30, persistent: true)
6665
end
6766

6867
# run user thread to search for your favorites coffee type
69-
threads = %w(latte espresso cappuccino americano mocha macchiato frappuccino cold_brew).map do |query|
68+
threads = %w[latte espresso cappuccino americano mocha macchiato frappuccino cold_brew].map do |query|
7069
Thread.new do
71-
pool.with { |socket| socket.search({q: query }).to_s }
70+
pool.with { |socket| socket.search({ q: query }).to_s }
7271
end
7372
end
74-
responses = threads.map(&:value)
73+
threads.map(&:value)
7574
end.total
7675
puts "total runtime: #{runtime}s for #{n} threads == #{n} HTTP connections"

spec/serpapi/client/account_api_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
describe 'account API' do
44
it 'fetch user account information' do
5-
client = SerpApi::Client.new(api_key: ENV['API_KEY'])
5+
client = SerpApi::Client.new(api_key: ENV['SERPAPI_KEY'])
66

7-
# mock response if no API_KEY specified
8-
if ENV['API_KEY'].nil?
7+
# mock response if no SERPAPI_KEY specified
8+
if ENV['SERPAPI_KEY'].nil?
99
allow(search).to receive(:get_results) {
1010
'{
1111
"account_id": "5ac54d6adefb2f1dba1663f5",
12-
"api_key": "SECRET_API_KEY",
12+
"api_key": "SECRET_SERPAPI_KEY",
1313
"account_email": "demo@serpapi.com",
1414
"plan_id": "bigdata",
1515
"plan_name": "Big Data Plan",

spec/serpapi/client/benchmark/benchmark_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
it 'regular get' do
2323
runtime = Benchmark.measure do
24-
client = SerpApi::Client.new(persistent: false, engine: 'google', api_key: ENV['API_KEY'])
24+
client = SerpApi::Client.new(persistent: false, engine: 'google', api_key: ENV['SERPAPI_KEY'])
2525
results = n.times.map { |x| client.search(q: "coffee #{x}") }
2626
client.close
2727
end.total
@@ -30,7 +30,7 @@
3030

3131
it 'keep alive' do
3232
runtime = Benchmark.measure do
33-
client = SerpApi::Client.new(persistent: true, engine: 'google', api_key: ENV['API_KEY'],)
33+
client = SerpApi::Client.new(persistent: true, engine: 'google', api_key: ENV['SERPAPI_KEY'],)
3434
results = n.times.map { |x| client.search(q: "coffee #{n+x}") }
3535
client.close
3636
end.total

0 commit comments

Comments
 (0)