webcrawlerapi-js 2.2.5 → 2.2.6
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.
- package/dist/@types/model.d.ts +2 -0
- package/dist/api.js +19 -7
- package/package.json +1 -1
package/dist/@types/model.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ export interface ScrapeResponse {
|
|
|
29
29
|
page_title?: string;
|
|
30
30
|
structured_data?: any;
|
|
31
31
|
links?: string[];
|
|
32
|
+
/** Server-recommended delay before the next status poll, if provided */
|
|
33
|
+
recommended_pull_delay_ms?: number;
|
|
32
34
|
}
|
|
33
35
|
export interface ScrapeResponseError {
|
|
34
36
|
success: boolean;
|
package/dist/api.js
CHANGED
|
@@ -24,6 +24,9 @@ const BASE_PATH = "https://api.webcrawlerapi.com";
|
|
|
24
24
|
const initialPullDelayMs = 2000;
|
|
25
25
|
const MaxPullRetries = 100;
|
|
26
26
|
const DEFAULT_POLL_DELAY_SECONDS = 2;
|
|
27
|
+
const SCRAPE_MAX_WAIT_MS = 400 * 1000;
|
|
28
|
+
// Effectively unbounded by count at the 2s default; elapsed time is the real limit
|
|
29
|
+
const SCRAPE_MAX_POLLS = 1000;
|
|
27
30
|
const AgentTerminalStatuses = ["done", "error", "canceled"];
|
|
28
31
|
__exportStar(require("./model"), exports);
|
|
29
32
|
const SCRAPE_VERSION = "v2";
|
|
@@ -183,17 +186,21 @@ class WebcrawlerClient {
|
|
|
183
186
|
return {
|
|
184
187
|
success: false,
|
|
185
188
|
status: status,
|
|
186
|
-
page_status_code: 0
|
|
189
|
+
page_status_code: 0,
|
|
190
|
+
recommended_pull_delay_ms: responseData.recommended_pull_delay_ms
|
|
187
191
|
};
|
|
188
192
|
}
|
|
189
193
|
}
|
|
190
|
-
async scrape(request, maxPolls =
|
|
194
|
+
async scrape(request, maxPolls = SCRAPE_MAX_POLLS) {
|
|
191
195
|
// Start the scraping job
|
|
192
196
|
const scrapeIdResponse = await this.scrapeAsync(request);
|
|
193
197
|
const scrapeId = scrapeIdResponse.id;
|
|
198
|
+
const startedAt = Date.now();
|
|
194
199
|
let polls = 0;
|
|
200
|
+
let delayMs = DEFAULT_POLL_DELAY_SECONDS * 1000;
|
|
195
201
|
let result;
|
|
196
|
-
|
|
202
|
+
// Bounded by both elapsed time (SCRAPE_MAX_WAIT_MS) and maxPolls
|
|
203
|
+
while (polls < maxPolls && Date.now() - startedAt < SCRAPE_MAX_WAIT_MS) {
|
|
197
204
|
result = await this.getScrape(scrapeId);
|
|
198
205
|
// Return immediately if scrape is done
|
|
199
206
|
if ('status' in result && result.status === "done") {
|
|
@@ -203,12 +210,17 @@ class WebcrawlerClient {
|
|
|
203
210
|
if ('error_code' in result) {
|
|
204
211
|
return result;
|
|
205
212
|
}
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
213
|
+
// Use server-recommended delay when present, otherwise keep the default
|
|
214
|
+
const recommended = result.recommended_pull_delay_ms;
|
|
215
|
+
delayMs = recommended && recommended > 0 ? recommended : DEFAULT_POLL_DELAY_SECONDS * 1000;
|
|
216
|
+
// Don't sleep past the overall deadline
|
|
217
|
+
const remainingMs = SCRAPE_MAX_WAIT_MS - (Date.now() - startedAt);
|
|
218
|
+
if (remainingMs <= 0)
|
|
219
|
+
break;
|
|
220
|
+
await new Promise(resolve => setTimeout(resolve, Math.min(delayMs, remainingMs)));
|
|
209
221
|
polls++;
|
|
210
222
|
}
|
|
211
|
-
// Return the last known state
|
|
223
|
+
// Return the last known state on timeout
|
|
212
224
|
return result;
|
|
213
225
|
}
|
|
214
226
|
async crawl(crawlRequest, maxPolls = MaxPullRetries) {
|