scrapeunblocker 0.9.0 → 0.10.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +42 -32
- data/lib/scrapeunblocker/client.rb +10 -4
- data/lib/scrapeunblocker/plugins.rb +3814 -0
- data/lib/scrapeunblocker/version.rb +1 -1
- data/lib/scrapeunblocker.rb +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 14be9ee13840a5574c9924bf39c16b15ecf05c7e4cde02091840034013474c90
|
|
4
|
+
data.tar.gz: e915ed083458bad3fcc0bdbf1be03347052582a97f8e0955daa86ede3b535eff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d9ccb478cbf809a1c747b578946a08e0fb30a0e8d968d5eda0cd8389f7c572825e37772c1f0ec590b8ba618d47748262de8a65c773e8fa0ade262b0cb75d471
|
|
7
|
+
data.tar.gz: c43112450a0ffebabf538bb3a0cb50d2a74be3c0de0712f8e138a34d226b8eb7710f6e9b78560280412d2001e7860439ef3c1d1975559f67519df0bb6d838262
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.10.1 (2026-10-13)
|
|
4
|
+
|
|
5
|
+
- `tiktok_shop_search` takes its keyword as optional, so a category-only search works (`category` option).
|
|
6
|
+
- `aldi_au_specials` takes `category`: a Special Buys drop date such as `2026-10-14`.
|
|
7
|
+
- `capterra_search` no longer offers `page` and `app_store_reviews` no longer offers `lang`; the API ignored both for those calls.
|
|
8
|
+
- Method docs say "proxy country" where they said "exit-IP country", and drop internal routing notes.
|
|
9
|
+
|
|
10
|
+
## 0.10.0 (2026-10-13)
|
|
11
|
+
|
|
12
|
+
- 104 new plugin methods on `ScrapeUnblocker::Client`, one for every public plugin endpoint: e-commerce (Walmart, Target, Best Buy, Home Depot, Etsy, Temu, SHEIN, Zalando, AliExpress, Alibaba, 1688, TikTok Shop, Amazon Best Sellers and reviews), groceries (Woolworths, Coles, ALDI Australia), travel (Booking.com reviews, Airbnb listings and reviews, Tripadvisor), Google (Trends, Shopping, Jobs, Maps place details), Bing / DuckDuckGo / Yahoo / Brave search and images, real estate (Zillow, Redfin, Rightmove, Idealista, ImmobilienScout24), vehicles (mobile.de, AutoScout24), jobs (Indeed, Glassdoor, Naukri, Wellfound, company career sites), reviews and companies (Trustpilot, G2, Capterra, Product Hunt, Crunchbase), Yelp, Naver Place, Google Play, the App Store, YouTube, Spotify, Telegram, Quora, Similarweb, Ahrefs and Semrush. The README lists them by category; every parameter is on the docs plugin pages.
|
|
13
|
+
- Each method takes the plugin's main input positionally and the rest as keyword options; options left `nil` are not sent, so the API's defaults apply. Methods for one mode of a multi-mode endpoint set the mode themselves (`woolworths_product("888137")`, `spotify_artist(...)`).
|
|
14
|
+
- New `plugin(path, **params)` calls any plugin endpoint by path. Array values are sent as a repeated query parameter.
|
|
15
|
+
|
|
16
|
+
No breaking changes.
|
|
17
|
+
|
|
3
18
|
## 0.9.0 (2026-10-07)
|
|
4
19
|
|
|
5
20
|
- New `ScrapeUnblocker::BudgetExceededError` (a subclass of `PaymentRequiredError`): raised when the API answers 402 with `User set budget exceeded`, meaning this billing period's spend reached the monthly budget limit (EUR, excluding VAT) set in the [profile](https://app.scrapeunblocker.com/dashboard/profile). It clears at the start of the next billing period, or within about a minute after the limit is raised or removed. Like the other 402s it is never retried and not billed. Before, this body surfaced as a plain `PaymentRequiredError`.
|
data/README.md
CHANGED
|
@@ -114,6 +114,48 @@ p result.data # the fields
|
|
|
114
114
|
fresh = su.get_parsed(url, refresh_rules: true, rules_hint: "price is missing")
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
+
## Plugins
|
|
118
|
+
|
|
119
|
+
Ready-made scrapers for specific sites that return structured JSON. Each
|
|
120
|
+
method takes the plugin's main input positionally and everything else as
|
|
121
|
+
keyword options; options you leave out are not sent, so the API's own
|
|
122
|
+
defaults apply. Every parameter is documented on the
|
|
123
|
+
[plugin pages](https://docs.scrapeunblocker.com/plugins/overview?utm_source=rubygems&utm_medium=integration&utm_campaign=ruby-sdk).
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
products = su.target_search("coffee maker", sort: "price_low", max_results: 48)
|
|
127
|
+
milk = su.woolworths_product("888137") # one product, with nutrition
|
|
128
|
+
trends = su.google_trends(%w[coffee tea], geo: "US") # a list is sent comma-separated
|
|
129
|
+
reviews = su.trustpilot_reviews("www.nike.com", stars: [4, 5])
|
|
130
|
+
jobs = su.career_site_jobs("https://jobs.ashbyhq.com/ramp", keyword: "engineer")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
<!-- plugin-methods:start -->
|
|
134
|
+
| Category | Methods |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| Travel | `skyscanner.flights`, `skyscanner.hotels`, `skyscanner.carhire`, `booking_hotels`, `booking_reviews`, `airbnb_search`, `airbnb_room`, `airbnb_reviews`, `tripadvisor_list`, `tripadvisor_reviews` |
|
|
137
|
+
| Google | `google_local`, `google_images`, `maps_place_details`, `google_trends`, `google_shopping`, `google_jobs` |
|
|
138
|
+
| Search engines | `bing_search`, `bing_images`, `duckduckgo_search`, `yahoo_search`, `yahoo_images`, `brave_search`, `brave_images` |
|
|
139
|
+
| E-commerce | `amazon_product`, `amazon_search`, `amazon_bestsellers`, `amazon_reviews`, `walmart_search`, `target_search`, `bestbuy_search`, `homedepot_search`, `etsy_search`, `temu_search`, `temu_product`, `shein_search`, `zalando_search`, `aliexpress_search`, `alibaba_search`, `alibaba_product`, `alibaba1688_search`, `alibaba1688_product`, `tiktok_shop_search`, `tiktok_shop_product`, `tiktok_shop_store`, `oopbuy_search` |
|
|
140
|
+
| Classifieds & Resale | `ebay_search`, `vinted_search`, `leboncoin_search` |
|
|
141
|
+
| Groceries | `woolworths_search`, `woolworths_category`, `woolworths_specials`, `woolworths_product`, `coles_search`, `coles_category`, `coles_specials`, `coles_product`, `aldi_au_search`, `aldi_au_category`, `aldi_au_specials`, `aldi_au_product` |
|
|
142
|
+
| Real estate | `zillow_search`, `zillow_detail`, `redfin_search`, `redfin_detail`, `rightmove_search`, `idealista_search`, `idealista_detail`, `immobilienscout24_search` |
|
|
143
|
+
| Vehicles | `mobile_de`, `autoscout24_search` |
|
|
144
|
+
| Jobs | `indeed_jobs`, `glassdoor_jobs`, `glassdoor_reviews`, `glassdoor_salaries`, `naukri_jobs`, `wellfound_jobs`, `wellfound_job`, `wellfound_company`, `wellfound_company_search`, `career_site_jobs` |
|
|
145
|
+
| Reviews & Companies | `trustpilot_reviews`, `g2_reviews`, `g2_search`, `capterra_reviews`, `capterra_search`, `product_hunt`, `crunchbase_company`, `crunchbase_search` |
|
|
146
|
+
| Local & Maps | `yelp_search`, `yelp_business`, `yelp_reviews`, `naver_place_search`, `naver_place_details` |
|
|
147
|
+
| Apps | `google_play_app`, `google_play_search`, `app_store_app`, `app_store_search`, `app_store_reviews` |
|
|
148
|
+
| Video, Music & Communities | `youtube_channel`, `youtube_search`, `youtube_comments`, `youtube_transcript`, `spotify_search`, `spotify_artist`, `spotify_album`, `spotify_track`, `spotify_playlist`, `telegram_channel`, `quora_question`, `quora_profile` |
|
|
149
|
+
| SEO & Ads | `similarweb_overview`, `ahrefs`, `semrush_overview`, `meta_ad_library` |
|
|
150
|
+
<!-- plugin-methods:end -->
|
|
151
|
+
|
|
152
|
+
Any plugin endpoint can also be called by path, with parameters named as the
|
|
153
|
+
API names them - handy for an endpoint added after your gem version:
|
|
154
|
+
|
|
155
|
+
```ruby
|
|
156
|
+
data = su.plugin("/marketplace/target-search", query: "tv", max_results: 24)
|
|
157
|
+
```
|
|
158
|
+
|
|
117
159
|
## Google search (SERP)
|
|
118
160
|
|
|
119
161
|
```ruby
|
|
@@ -184,19 +226,6 @@ end
|
|
|
184
226
|
|
|
185
227
|
`marketplace` is any of the 19 regional eBay hosts (`ebay.com` default). `condition` is one of `"new"`, `"open_box"`, `"refurbished"`, `"used"` or `"for_parts"`; `sort` is one of `"best_match"` (default), `"newly_listed"`, `"ending_soon"`, `"price_asc"` or `"price_desc"`; `page_size` is 60, 120 or 240. `exactMatches` is `false` when eBay found nothing for the keyword and answered with its own loosely-related suggestions instead, so check it before using the listings.
|
|
186
228
|
|
|
187
|
-
### TikTok
|
|
188
|
-
|
|
189
|
-
```ruby
|
|
190
|
-
profile = su.tiktok_profile("nasa", max_videos: 5) # exact stats + newest videos
|
|
191
|
-
video = su.tiktok_video("https://www.tiktok.com/@nasa/video/7665075736742530317", include_transcript: true)
|
|
192
|
-
tag = su.tiktok_hashtag("nasa", max_videos: 10)
|
|
193
|
-
results = su.tiktok_search("space telescope", max_results: 25) # TikTok's own ranking
|
|
194
|
-
comments = su.tiktok_comments("https://www.tiktok.com/@nasa/video/7665075736742530317", max_comments: 40)
|
|
195
|
-
puts profile["stats"]["followers"], video["stats"]["plays"], tag["stats"]["views"], comments["totalComments"]
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
Profiles and hashtags list up to 10 videos in a couple of seconds from TikTok's server-rendered widget; ask for more (up to 200) and the real grid is scrolled in a browser session.
|
|
199
|
-
|
|
200
229
|
## Cookies and the serving proxy
|
|
201
230
|
|
|
202
231
|
```ruby
|
|
@@ -229,25 +258,6 @@ hotels = su.skyscanner.hotels(destination: "Madrid", checkin: "2026-09-01", chec
|
|
|
229
258
|
cars = su.skyscanner.carhire(pickup: "Madrid", pickup_datetime: "2026-09-01T10:00", dropoff_datetime: "2026-09-03T10:00")
|
|
230
259
|
```
|
|
231
260
|
|
|
232
|
-
## Southwest plugin
|
|
233
|
-
|
|
234
|
-
Southwest Airlines flight quotes as JSON. `origin` and `dest` are IATA airport codes; omit `return_date` for a one-way search.
|
|
235
|
-
|
|
236
|
-
```ruby
|
|
237
|
-
flights = su.southwest.flights(
|
|
238
|
-
origin: "DAL", dest: "HOU",
|
|
239
|
-
depart_date: "2026-10-20", return_date: "2026-10-27"
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
# One-way, priced in Rapid Rewards points
|
|
243
|
-
oneway = su.southwest.flights(
|
|
244
|
-
origin: "DAL", dest: "HOU",
|
|
245
|
-
depart_date: "2026-10-20", adults: 2, fare_type: "points"
|
|
246
|
-
)
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
`adults` is 1-8 (default 1), `fare_type` is `"dollars"` (default) or `"points"`, `proxy_country` defaults to `"US"` and `max_attempts` is 1-5 (default 3). The call returns the raw booking / shopping JSON.
|
|
250
|
-
|
|
251
261
|
## Error handling
|
|
252
262
|
|
|
253
263
|
Non-2xx responses raise typed errors, all subclasses of `ScrapeUnblocker::Error`.
|
|
@@ -6,6 +6,7 @@ require "json"
|
|
|
6
6
|
|
|
7
7
|
require_relative "errors"
|
|
8
8
|
require_relative "parsed_page"
|
|
9
|
+
require_relative "plugins"
|
|
9
10
|
require_relative "skyscanner"
|
|
10
11
|
require_relative "southwest"
|
|
11
12
|
require_relative "version"
|
|
@@ -16,6 +17,8 @@ module ScrapeUnblocker
|
|
|
16
17
|
# su = ScrapeUnblocker::Client.new(api_key: "YOUR_API_KEY")
|
|
17
18
|
# html = su.get_page_source("https://example.com")
|
|
18
19
|
class Client
|
|
20
|
+
include Plugins
|
|
21
|
+
|
|
19
22
|
DEFAULT_BASE_URL = "https://api.scrapeunblocker.com"
|
|
20
23
|
API_KEY_HEADER = "x-scrapeunblocker-key"
|
|
21
24
|
RETRYABLE = [429, 502, 503, 504].freeze
|
|
@@ -148,7 +151,7 @@ module ScrapeUnblocker
|
|
|
148
151
|
# originalPrice, priceCny, monthSold, image and url. +channel+ is one of
|
|
149
152
|
# "1688" (default), "taobao" or "official"; +sort+ is one of "default",
|
|
150
153
|
# "price_asc", "price_desc" or "best_selling". +page_size+ max is 60.
|
|
151
|
-
#
|
|
154
|
+
# A brand keyword returns 200 with keywordRejected = true and no products.
|
|
152
155
|
def oopbuy_search(keyword, channel: "1688", page: 1, page_size: 20, sort: "default", proxy_country: nil)
|
|
153
156
|
post_json("/goods/oopbuy-search",
|
|
154
157
|
keyword: keyword, channel: channel, page: page,
|
|
@@ -189,7 +192,7 @@ module ScrapeUnblocker
|
|
|
189
192
|
# availability, rating, review count, seller, feature bullets, categories
|
|
190
193
|
# and images. Prices come back in the marketplace's own currency:
|
|
191
194
|
# +proxy_country+ defaults to the marketplace's home country
|
|
192
|
-
# (amazon.com -> US)
|
|
195
|
+
# (amazon.com -> US). Pass either
|
|
193
196
|
# +asin+ (with +marketplace+) or a full product +url+.
|
|
194
197
|
def amazon_product(asin: nil, url: nil, marketplace: "amazon.com", proxy_country: nil)
|
|
195
198
|
post_json("/marketplace/amazon-product",
|
|
@@ -302,8 +305,11 @@ module ScrapeUnblocker
|
|
|
302
305
|
params.each_with_object([]) do |(key, value), acc|
|
|
303
306
|
next if value.nil?
|
|
304
307
|
|
|
305
|
-
|
|
306
|
-
|
|
308
|
+
# A list is a repeated parameter (stars=4&stars=5), as the API reads it.
|
|
309
|
+
Array(value).each do |item|
|
|
310
|
+
item = item ? "true" : "false" if item == true || item == false
|
|
311
|
+
acc << "#{key}=#{URI.encode_www_form_component(item.to_s)}"
|
|
312
|
+
end
|
|
307
313
|
end.join("&")
|
|
308
314
|
end
|
|
309
315
|
|