scrapeunblocker 0.1.8 → 0.2.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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +59 -0
- data/lib/scrapeunblocker/client.rb +54 -4
- data/lib/scrapeunblocker/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d921e3453928431b4e1715efd3f8ae53fa1175f5b4fdbf4a67db12c0409cab18
|
|
4
|
+
data.tar.gz: 59bcc76323226693b74aa96d8a3f969118f6df95328a6e3424bed1ec8dfa78e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4d0791186d046ebe36897a987c7fd08fdfa98c1c78754fc7a32bc9552ac782a903ec1e10bde22fa7d1b442972586ab8a85d6777a00dc5d310e1c9cfe40f9e372
|
|
7
|
+
data.tar.gz: b132825a15081702a1e76ab431ae9835f88ffa7a589241775688f1820ee58c14d438e0a9150afa995e70fee3ee97df63de6f0dd6b9ba78c17adbacd0ba00510b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 (2026-08-29)
|
|
4
|
+
|
|
5
|
+
- `get_page_source` now accepts `steps:` - an ordered Array of browser-action Hashes the API runs in the real browser after the page loads (`wait_for`, `wait_for_text`, `wait`, `click`, `type`, `select`, `press_key`, `scroll`). The array is JSON-encoded into the `steps` query parameter. Steps run once and are not idempotent; a failed step returns HTTP 422 and raises `ScrapeUnblocker::ValidationError`, whose `body` names the failed step (`step_index`, `action`, `reason`, `selector`, `html`).
|
|
6
|
+
- `get_page_source` now accepts `list_elements:` - pass `true` to get a JSON summary of the matched elements (`{"url", "count", "elements"}`) instead of HTML. When set, the method returns the parsed Hash rather than an HTML String, mirroring `get_parsed`.
|
|
7
|
+
|
|
8
|
+
No breaking changes.
|
|
9
|
+
|
|
10
|
+
## 0.1.9 (2026-08-28)
|
|
11
|
+
|
|
12
|
+
- Added `amazon_product` and `amazon_search` for the new Amazon plugin. `amazon_product(asin:/url:)` returns one product - title, brand, numeric price and currency, list price and savings, availability, rating, review count, seller, feature bullets, categories and images. `amazon_search(keyword, ...)` returns a keyword search's cards - asin, title, price, list price, rating, review count, a clean product URL, image and the sponsored/prime flags - on any of 20 regional marketplaces.
|
|
13
|
+
- Prices come back in the right currency automatically: `proxy_country` defaults to the marketplace's home country (amazon.com -> US, amazon.de -> DE), pinning the exit over our ISP pool.
|
|
14
|
+
|
|
3
15
|
## 0.1.8 (2026-07-31)
|
|
4
16
|
|
|
5
17
|
- Added `ebay_search` for the new eBay Search plugin: listings from any of the 19 regional eBay marketplaces as structured JSON - title, numeric price and currency, condition with a normalised `conditionCode`, seller username and feedback, shipping cost, sold/watcher/bid counts, image and a clean item URL.
|
data/README.md
CHANGED
|
@@ -62,6 +62,47 @@ html = su.get_page_source(
|
|
|
62
62
|
)
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
## Browser steps
|
|
66
|
+
|
|
67
|
+
Drive the page after it loads with an ordered list of browser actions - fill a form, click through, wait for content, then capture the rendered result. Steps run once in the real browser, in order.
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
html = su.get_page_source(
|
|
71
|
+
"https://example.com/search",
|
|
72
|
+
steps: [
|
|
73
|
+
{ action: "type", selector: "input#q", value: "web scraping", clear: true },
|
|
74
|
+
{ action: "press_key", value: "Enter" },
|
|
75
|
+
{ action: "wait_for", selector: "#results" },
|
|
76
|
+
{ action: "scroll", value: "bottom" }
|
|
77
|
+
]
|
|
78
|
+
)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Supported actions and their fields:
|
|
82
|
+
|
|
83
|
+
| Action | Fields |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `wait_for` | `selector`, `selector_type` (`css` default, `xPath`, `className`, `tagName`), `timeout_ms` |
|
|
86
|
+
| `wait_for_text` | `value` (text to await), `timeout_ms` |
|
|
87
|
+
| `wait` | `value` (milliseconds) |
|
|
88
|
+
| `click` | `selector`, `selector_type`, `timeout_ms` |
|
|
89
|
+
| `type` | `selector`, `selector_type`, `value`, `clear` (bool), `timeout_ms` - types like a human |
|
|
90
|
+
| `select` | `selector`, `selector_type`, `value`, `timeout_ms` |
|
|
91
|
+
| `press_key` | `value` - one of `Enter`, `Tab`, `Escape`, `Backspace`, `Delete`, `Space`, `ArrowUp`, `ArrowDown`, `ArrowLeft`, `ArrowRight`, `Home`, `End`, `PageUp`, `PageDown` |
|
|
92
|
+
| `scroll` | `value` - `"bottom"` or a pixel count |
|
|
93
|
+
|
|
94
|
+
Steps are not idempotent (they submit forms, click buttons), so a call is not safe to blindly retry. If a step fails, the API answers HTTP 422 and the client raises `ScrapeUnblocker::ValidationError`; its `body` is the JSON describing which step failed (`error: "step_failed"`, `step_index`, `action`, `reason`, `selector`, `html`).
|
|
95
|
+
|
|
96
|
+
## List elements
|
|
97
|
+
|
|
98
|
+
Pass `list_elements: true` to get a JSON summary of the matched elements instead of the full HTML. The method then returns a parsed Hash (`{"url", "count", "elements"}`) rather than an HTML String.
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
result = su.get_page_source("https://example.com", list_elements: true)
|
|
102
|
+
puts result["count"]
|
|
103
|
+
result["elements"].each { |el| p el }
|
|
104
|
+
```
|
|
105
|
+
|
|
65
106
|
## Get parsed JSON
|
|
66
107
|
|
|
67
108
|
```ruby
|
|
@@ -96,6 +137,24 @@ goods["results"].each { |item| puts "#{item['title']} #{item['price']} #{item['u
|
|
|
96
137
|
|
|
97
138
|
`channel` is one of `"1688"` (default), `"taobao"` or `"official"`. `sort` is one of `"default"`, `"price_asc"`, `"price_desc"` or `"best_selling"`. `page_size` max is 60. Oopbuy trademark-blocks brand keywords at its own backend: those come back as a successful `200` with `keywordRejected: true` and an empty `results` array, not an error.
|
|
98
139
|
|
|
140
|
+
## Amazon
|
|
141
|
+
|
|
142
|
+
Product and search data as a Hash, priced in the marketplace's own currency:
|
|
143
|
+
|
|
144
|
+
```ruby
|
|
145
|
+
# One product by ASIN (or url: "https://www.amazon.de/dp/B0BSHF7WHW")
|
|
146
|
+
product = su.amazon_product(asin: "B0BSHF7WHW", marketplace: "amazon.com")
|
|
147
|
+
puts [product["title"], product["price"], product["currency"], product["rating"]].join(" | ")
|
|
148
|
+
|
|
149
|
+
# Keyword search
|
|
150
|
+
results = su.amazon_search("wireless headphones", sort: "price_asc")
|
|
151
|
+
results["results"].each do |item|
|
|
152
|
+
puts [item["title"], item["price"], item["currency"], item["asin"]].join(" | ")
|
|
153
|
+
end
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`proxy_country` defaults to the marketplace's home country (`amazon.com` -> US, `amazon.de` -> DE), so prices come back in the right currency with no configuration.
|
|
157
|
+
|
|
99
158
|
## eBay search
|
|
100
159
|
|
|
101
160
|
```ruby
|
|
@@ -37,10 +37,31 @@ module ScrapeUnblocker
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# Fetch a URL and return the fully rendered HTML.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
#
|
|
41
|
+
# +steps+ is an ordered Array of browser-action Hashes the API runs in the
|
|
42
|
+
# real browser after the page loads (each Hash carries an +action+ and its
|
|
43
|
+
# fields): +wait_for+ {selector, selector_type?, timeout_ms?}, +wait_for_text+
|
|
44
|
+
# {value, timeout_ms?}, +wait+ {value}, +click+ {selector, selector_type?,
|
|
45
|
+
# timeout_ms?}, +type+ {selector, selector_type?, value, clear?, timeout_ms?},
|
|
46
|
+
# +select+ {selector, selector_type?, value, timeout_ms?}, +press_key+ {value},
|
|
47
|
+
# +scroll+ {value}. +selector_type+ is one of "css" (default), "xPath",
|
|
48
|
+
# "className" or "tagName". The steps run once and are not idempotent; if a
|
|
49
|
+
# step fails the API answers HTTP 422 with a JSON body naming the failed step,
|
|
50
|
+
# which surfaces here as a ScrapeUnblocker::ValidationError.
|
|
51
|
+
#
|
|
52
|
+
# +list_elements+, when true, makes the API return a JSON summary of the
|
|
53
|
+
# matched elements ({"url", "count", "elements"}) instead of HTML. This method
|
|
54
|
+
# then returns that parsed Hash rather than an HTML String.
|
|
55
|
+
def get_page_source(url, proxy_country: nil, time_sleep: nil, method: nil, value: nil, method_timeout: nil,
|
|
56
|
+
steps: nil, list_elements: nil)
|
|
57
|
+
body = request("/getPageSource",
|
|
58
|
+
url: url, proxy_country: proxy_country, time_sleep: time_sleep,
|
|
59
|
+
method: method, value: value, method_timeout: method_timeout,
|
|
60
|
+
steps: (steps ? JSON.generate(steps) : nil),
|
|
61
|
+
list_elements: (list_elements ? true : nil))[:body]
|
|
62
|
+
return JSON.parse(body) if list_elements
|
|
63
|
+
|
|
64
|
+
body
|
|
44
65
|
end
|
|
45
66
|
|
|
46
67
|
# Fetch a URL and return structured JSON instead of HTML.
|
|
@@ -121,6 +142,35 @@ module ScrapeUnblocker
|
|
|
121
142
|
proxy_country: proxy_country)
|
|
122
143
|
end
|
|
123
144
|
|
|
145
|
+
# Scrape one Amazon product by ASIN or URL and return it as a Hash.
|
|
146
|
+
#
|
|
147
|
+
# Returns title, brand, numeric price and currency, list price and savings,
|
|
148
|
+
# availability, rating, review count, seller, feature bullets, categories
|
|
149
|
+
# and images. Prices come back in the marketplace's own currency:
|
|
150
|
+
# +proxy_country+ defaults to the marketplace's home country
|
|
151
|
+
# (amazon.com -> US), pinning the exit over the ISP pool. Pass either
|
|
152
|
+
# +asin+ (with +marketplace+) or a full product +url+.
|
|
153
|
+
def amazon_product(asin: nil, url: nil, marketplace: "amazon.com", proxy_country: nil)
|
|
154
|
+
post_json("/marketplace/amazon-product",
|
|
155
|
+
asin: asin, url: url, marketplace: marketplace,
|
|
156
|
+
proxy_country: proxy_country)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Search Amazon and return the result cards as an Array of Hashes.
|
|
160
|
+
#
|
|
161
|
+
# Each card carries asin, title, numeric price and currency, list price,
|
|
162
|
+
# rating, review count, a clean product URL, image and the sponsored /
|
|
163
|
+
# prime flags. +sort+ is "featured" (default), "price_asc", "price_desc",
|
|
164
|
+
# "avg_review" or "newest". Prices are in the marketplace's own currency;
|
|
165
|
+
# +proxy_country+ defaults to the marketplace's home country.
|
|
166
|
+
def amazon_search(keyword, marketplace: "amazon.com", page: 1, sort: "featured",
|
|
167
|
+
min_price: nil, max_price: nil, proxy_country: nil)
|
|
168
|
+
post_json("/marketplace/amazon-search",
|
|
169
|
+
keyword: keyword, marketplace: marketplace, page: page,
|
|
170
|
+
sort: sort, min_price: min_price, max_price: max_price,
|
|
171
|
+
proxy_country: proxy_country)
|
|
172
|
+
end
|
|
173
|
+
|
|
124
174
|
# Fetch an image URL through the bypass chain and return its raw bytes.
|
|
125
175
|
def get_image(url, proxy_country: nil)
|
|
126
176
|
request("/getImage", url: url, proxy_country: proxy_country)[:body]
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: scrapeunblocker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ScrapeUnblocker
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: JS-rendered pages that bypass Cloudflare, DataDome, PerimeterX and Akamai,
|
|
14
14
|
plus Google SERP and Skyscanner flights/hotels/car-hire scraping as JSON.
|