Class: SerpCheap::Client
- Inherits:
-
Object
- Object
- SerpCheap::Client
- Defined in:
- lib/serpcheap/client.rb
Constant Summary collapse
- DEFAULT_BASE_URL =
"https://api.serp.cheap"- DEFAULT_TIMEOUT_MS =
15_000- DEFAULT_MAX_RETRIES =
2
Instance Method Summary collapse
-
#initialize(api_key, base_url: nil, timeout_ms: DEFAULT_TIMEOUT_MS, max_retries: DEFAULT_MAX_RETRIES) ⇒ Client
constructor
A new instance of Client.
-
#rank(url, q, gl: "us", hl: nil, tbs: nil, pages: 1, match_type: "domain") ⇒ Object
Find where a url/domain ranks for a keyword.
-
#scrape(url, render_js: nil, screenshot: nil, wait_for: nil, wait_ms: nil, screenshot_width: nil, screenshot_height: nil) ⇒ Object
Fetch and extract a single page.
-
#search(q, gl: "us", hl: nil, tbs: nil, page: 1, scrape: nil) ⇒ Object
Run a Google search.
-
#search_pages(q, from: 1, to: 10, **opts) ⇒ Object
Eagerly fetch pages [from..to] (inclusive).
Constructor Details
#initialize(api_key, base_url: nil, timeout_ms: DEFAULT_TIMEOUT_MS, max_retries: DEFAULT_MAX_RETRIES) ⇒ Client
Returns a new instance of Client.
13 14 15 16 17 18 19 20 |
# File 'lib/serpcheap/client.rb', line 13 def initialize(api_key, base_url: nil, timeout_ms: DEFAULT_TIMEOUT_MS, max_retries: DEFAULT_MAX_RETRIES) raise Error.new("missing_api_key", "An API key is required. Get one at https://app.serp.cheap.") if api_key.nil? || api_key.empty? @api_key = api_key @base_url = (base_url || DEFAULT_BASE_URL).sub(%r{/+\z}, "") @timeout_ms = timeout_ms @max_retries = max_retries end |
Instance Method Details
#rank(url, q, gl: "us", hl: nil, tbs: nil, pages: 1, match_type: "domain") ⇒ Object
Find where a url/domain ranks for a keyword. Retries transient errors with backoff.
65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/serpcheap/client.rb', line 65 def rank(url, q, gl: "us", hl: nil, tbs: nil, pages: 1, match_type: "domain") payload = { "url" => url, "q" => q, "gl" => gl, "pages" => pages, "match_type" => match_type } payload["hl"] = hl unless hl.nil? || hl.empty? payload["tbs"] = tbs unless tbs.nil? || tbs.empty? body = request("/v1/rank", payload) unless body["organic"].is_a?(Array) && body["matches"].is_a?(Array) raise Error.new("invalid_response", "The API response did not match the expected shape.") end RankResponse.from_hash(body) end |
#scrape(url, render_js: nil, screenshot: nil, wait_for: nil, wait_ms: nil, screenshot_width: nil, screenshot_height: nil) ⇒ Object
Fetch and extract a single page. Retries transient errors with backoff.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/serpcheap/client.rb', line 47 def scrape(url, render_js: nil, screenshot: nil, wait_for: nil, wait_ms: nil, screenshot_width: nil, screenshot_height: nil) payload = compact( "url" => url, "render_js" => render_js, "screenshot" => screenshot, "wait_for" => wait_for, "wait_ms" => wait_ms, "screenshot_width" => screenshot_width, "screenshot_height" => screenshot_height ) body = request("/v1/scrape", payload) raise Error.new("invalid_response", "The API response did not match the expected shape.") unless body["url"].is_a?(String) ScrapeResponse.from_hash(body) end |
#search(q, gl: "us", hl: nil, tbs: nil, page: 1, scrape: nil) ⇒ Object
Run a Google search. Retries transient errors (429/503/timeout) with backoff.
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/serpcheap/client.rb', line 23 def search(q, gl: "us", hl: nil, tbs: nil, page: 1, scrape: nil) payload = { "q" => q, "gl" => gl, "page" => page } payload["hl"] = hl unless hl.nil? || hl.empty? payload["tbs"] = tbs unless tbs.nil? || tbs.empty? payload["scrape"] = compact(scrape) if scrape.is_a?(Hash) && !scrape.empty? body = request("/v1/search", payload) raise Error.new("invalid_response", "The API response did not match the expected shape.") unless body["organic"].is_a?(Array) SearchResponse.from_hash(body) end |
#search_pages(q, from: 1, to: 10, **opts) ⇒ Object
Eagerly fetch pages [from..to] (inclusive). Stops on the first empty page.
36 37 38 39 40 41 42 43 44 |
# File 'lib/serpcheap/client.rb', line 36 def search_pages(q, from: 1, to: 10, **opts) pages = [] (from..to).each do |page| res = search(q, page: page, **opts) pages << res break if res.organic.empty? end pages end |