@crawlee/basic 4.0.0-beta.82 → 4.0.0-beta.83
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/internals/basic-crawler.d.ts +8 -13
- package/internals/basic-crawler.js +22 -32
- package/package.json +7 -7
|
@@ -411,24 +411,19 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
411
411
|
* via {@link BasicCrawler.getRequestManager|`getRequestManager()`}.
|
|
412
412
|
*/
|
|
413
413
|
protected requestManager?: IRequestManager;
|
|
414
|
+
/** Backs the {@link BasicCrawler.sessionPool|`sessionPool`} getter. */
|
|
415
|
+
private sessionPoolDep;
|
|
414
416
|
/**
|
|
415
417
|
* A reference to the underlying session pool that manages the crawler's {@link Session|sessions}. Typed as
|
|
416
418
|
* {@link ISessionPool} so custom implementations can be plugged in via the `sessionPool` constructor option.
|
|
417
419
|
*/
|
|
418
|
-
|
|
420
|
+
get sessionPool(): ISessionPool;
|
|
419
421
|
/**
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
* pool is never owned and never torn down by the crawler.
|
|
422
|
+
* Tracks **only** the queue the crawler opens for itself — not the {@link RequestManagerTandem} that may wrap it
|
|
423
|
+
* around a user-supplied `requestList` — so the owned-only purge between repeated `run()` calls never reaches
|
|
424
|
+
* through to a borrowed loader. Filled lazily in {@link BasicCrawler.openOwnedRequestQueue|`openOwnedRequestQueue()`}.
|
|
424
425
|
*/
|
|
425
|
-
private
|
|
426
|
-
/**
|
|
427
|
-
* Set when the crawler constructed its own request manager (no `requestManager`, `requestQueue`, or `requestList`
|
|
428
|
-
* option was provided). The owned manager is purged (not dropped) between repeated `run()` calls.
|
|
429
|
-
* A user-supplied manager is never purged by the crawler.
|
|
430
|
-
*/
|
|
431
|
-
private ownedRequestManager?;
|
|
426
|
+
private ownedRequestQueue;
|
|
432
427
|
/**
|
|
433
428
|
* Whether the request-processing-time hint has already been forwarded to the request manager. The hint
|
|
434
429
|
* derives only from `requestHandlerTimeoutMillis` (constant for the crawler's lifetime) and is raise-only,
|
|
@@ -643,7 +638,7 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
643
638
|
getRequestQueue(): Promise<IRequestManager>;
|
|
644
639
|
/**
|
|
645
640
|
* Opens the default {@link RequestQueue}, applies the crawler's timeouts to it and records it as the
|
|
646
|
-
* crawler-owned
|
|
641
|
+
* crawler-owned queue (so it gets purged between repeated `run()` calls).
|
|
647
642
|
* @private
|
|
648
643
|
*/
|
|
649
644
|
private openOwnedRequestQueue;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeFile } from 'node:fs/promises';
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
|
-
import { AutoscaledPool, bindMethodsToServiceLocator, BLOCKED_STATUS_CODES, ContextPipeline, ContextPipelineCleanupError, ContextPipelineInitializationError, ContextPipelineInterruptedError, CriticalError, Dataset, enqueueLinks, EnqueueStrategy, KeyValueStore, log, LogLevel, mergeCookies, MissingSessionError, NavigationSkippedError, NonRetryableError, purgeDefaultStorages, RequestHandlerError, RequestManagerTandem, RequestQueue, RequestState, RetryRequestError, Router, ServiceLocator, serviceLocator, Session, SessionError, SessionPool, Statistics, validateUserData, validators, } from '@crawlee/core';
|
|
3
|
+
import { AutoscaledPool, bindMethodsToServiceLocator, BLOCKED_STATUS_CODES, ContextPipeline, ContextPipelineCleanupError, ContextPipelineInitializationError, ContextPipelineInterruptedError, CriticalError, Dataset, enqueueLinks, EnqueueStrategy, KeyValueStore, log, LogLevel, mergeCookies, MissingSessionError, NavigationSkippedError, NonRetryableError, OwnedOrInjected, purgeDefaultStorages, RequestHandlerError, RequestManagerTandem, RequestQueue, RequestState, RetryRequestError, Router, ServiceLocator, serviceLocator, Session, SessionError, SessionPool, Statistics, validateUserData, validators, } from '@crawlee/core';
|
|
4
4
|
import { FetchHttpClient } from '@crawlee/http-client';
|
|
5
5
|
import { getObjectType, isAsyncIterable, isIterable, RobotsTxtFile, ROTATE_PROXY_ERRORS } from '@crawlee/utils';
|
|
6
6
|
import { stringify } from 'csv-stringify/sync';
|
|
@@ -60,24 +60,21 @@ export class BasicCrawler {
|
|
|
60
60
|
* via {@link BasicCrawler.getRequestManager|`getRequestManager()`}.
|
|
61
61
|
*/
|
|
62
62
|
requestManager;
|
|
63
|
+
/** Backs the {@link BasicCrawler.sessionPool|`sessionPool`} getter. */
|
|
64
|
+
sessionPoolDep;
|
|
63
65
|
/**
|
|
64
66
|
* A reference to the underlying session pool that manages the crawler's {@link Session|sessions}. Typed as
|
|
65
67
|
* {@link ISessionPool} so custom implementations can be plugged in via the `sessionPool` constructor option.
|
|
66
68
|
*/
|
|
67
|
-
sessionPool
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
* Holds the same instance as `sessionPool`, but typed as the concrete class so the crawler can call
|
|
71
|
-
* lifecycle methods (`resetStore`, `teardown`) that aren't part of {@link ISessionPool}. A user-supplied
|
|
72
|
-
* pool is never owned and never torn down by the crawler.
|
|
73
|
-
*/
|
|
74
|
-
ownedSessionPool;
|
|
69
|
+
get sessionPool() {
|
|
70
|
+
return this.sessionPoolDep.value;
|
|
71
|
+
}
|
|
75
72
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
73
|
+
* Tracks **only** the queue the crawler opens for itself — not the {@link RequestManagerTandem} that may wrap it
|
|
74
|
+
* around a user-supplied `requestList` — so the owned-only purge between repeated `run()` calls never reaches
|
|
75
|
+
* through to a borrowed loader. Filled lazily in {@link BasicCrawler.openOwnedRequestQueue|`openOwnedRequestQueue()`}.
|
|
79
76
|
*/
|
|
80
|
-
|
|
77
|
+
ownedRequestQueue = OwnedOrInjected.resolve();
|
|
81
78
|
/**
|
|
82
79
|
* Whether the request-processing-time hint has already been forwarded to the request manager. The hint
|
|
83
80
|
* derives only from `requestHandlerTimeoutMillis` (constant for the crawler's lifetime) and is raise-only,
|
|
@@ -297,18 +294,12 @@ export class BasicCrawler {
|
|
|
297
294
|
'`proxyInfo` they were created with. Configure proxies on the pool instead, ' +
|
|
298
295
|
'e.g. via `addSession({ proxyInfo })` or a custom `createSessionFunction`.');
|
|
299
296
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
...opts?.sessionOptions,
|
|
307
|
-
proxyInfo: opts?.sessionOptions?.proxyInfo ?? (await this.proxyConfiguration?.newProxyInfo()),
|
|
308
|
-
}),
|
|
309
|
-
});
|
|
310
|
-
this.sessionPool = this.ownedSessionPool;
|
|
311
|
-
}
|
|
297
|
+
this.sessionPoolDep = OwnedOrInjected.resolve(sessionPool, () => new SessionPool({
|
|
298
|
+
createSessionFunction: async (opts) => new Session({
|
|
299
|
+
...opts?.sessionOptions,
|
|
300
|
+
proxyInfo: opts?.sessionOptions?.proxyInfo ?? (await this.proxyConfiguration?.newProxyInfo()),
|
|
301
|
+
}),
|
|
302
|
+
}));
|
|
312
303
|
this.blockedStatusCodes = new Set(blockedStatusCodesInput ?? BLOCKED_STATUS_CODES);
|
|
313
304
|
const maxSignedInteger = 2 ** 31 - 1;
|
|
314
305
|
if (this.requestHandlerTimeoutMillis > maxSignedInteger) {
|
|
@@ -634,17 +625,17 @@ export class BasicCrawler {
|
|
|
634
625
|
// we need to purge the RQ to allow processing the same requests again — this is important so users can
|
|
635
626
|
// pass in failed requests back to the `crawler.run()`, otherwise they would be considered as handled and
|
|
636
627
|
// ignored — as a failed request is still handled.
|
|
637
|
-
// By default (purgeRequestQueue unset
|
|
628
|
+
// By default (`purgeRequestQueue` unset), only the queue we opened ourselves is purged.
|
|
638
629
|
// When `purgeRequestQueue` is explicitly `true`, we also purge a user-supplied manager.
|
|
639
630
|
// When `purgeRequestQueue` is explicitly `false`, nothing is purged.
|
|
640
631
|
const shouldPurge = purgeRequestQueue !== false;
|
|
641
|
-
const managerToPurge = this.
|
|
632
|
+
const managerToPurge = this.ownedRequestQueue.maybeValue ?? (purgeRequestQueue === true ? this.requestManager : undefined);
|
|
642
633
|
if (managerToPurge?.purge && shouldPurge) {
|
|
643
634
|
await managerToPurge.purge();
|
|
644
635
|
}
|
|
645
636
|
this.stats.reset();
|
|
646
637
|
await this.stats.resetStore();
|
|
647
|
-
await this.
|
|
638
|
+
await this.sessionPoolDep.ifOwned((pool) => pool.resetStore());
|
|
648
639
|
}
|
|
649
640
|
this.unexpectedStop = false;
|
|
650
641
|
this.running = true;
|
|
@@ -756,7 +747,7 @@ export class BasicCrawler {
|
|
|
756
747
|
}
|
|
757
748
|
/**
|
|
758
749
|
* Opens the default {@link RequestQueue}, applies the crawler's timeouts to it and records it as the
|
|
759
|
-
* crawler-owned
|
|
750
|
+
* crawler-owned queue (so it gets purged between repeated `run()` calls).
|
|
760
751
|
* @private
|
|
761
752
|
*/
|
|
762
753
|
async openOwnedRequestQueue() {
|
|
@@ -764,8 +755,7 @@ export class BasicCrawler {
|
|
|
764
755
|
// subsequent instances get their own queue via a unique alias so they don't collide.
|
|
765
756
|
const identifier = this.identity.instanceIndex === 0 ? null : { alias: `__default_${this.identity.id}__` };
|
|
766
757
|
const requestQueue = await RequestQueue.open(identifier, { config: serviceLocator.getConfiguration() });
|
|
767
|
-
this.
|
|
768
|
-
return requestQueue;
|
|
758
|
+
return this.ownedRequestQueue.set(requestQueue);
|
|
769
759
|
}
|
|
770
760
|
/**
|
|
771
761
|
* Tells a request manager how long we expect to hold a fetched request, so that one backed by a
|
|
@@ -1364,7 +1354,7 @@ export class BasicCrawler {
|
|
|
1364
1354
|
if (this._closeEvents) {
|
|
1365
1355
|
await serviceLocator.getEventManager().close();
|
|
1366
1356
|
}
|
|
1367
|
-
await this.
|
|
1357
|
+
await this.sessionPoolDep.ifOwned((pool) => pool.teardown());
|
|
1368
1358
|
await this.autoscaledPool?.abort();
|
|
1369
1359
|
}
|
|
1370
1360
|
_getCookieHeaderFromRequest(request) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/basic",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.83",
|
|
4
4
|
"description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"@apify/datastructures": "^2.0.0",
|
|
43
43
|
"@apify/timeout": "^0.3.2",
|
|
44
44
|
"@apify/utilities": "^2.15.5",
|
|
45
|
-
"@crawlee/core": "4.0.0-beta.
|
|
46
|
-
"@crawlee/http-client": "4.0.0-beta.
|
|
47
|
-
"@crawlee/types": "4.0.0-beta.
|
|
48
|
-
"@crawlee/utils": "4.0.0-beta.
|
|
45
|
+
"@crawlee/core": "4.0.0-beta.83",
|
|
46
|
+
"@crawlee/http-client": "4.0.0-beta.83",
|
|
47
|
+
"@crawlee/types": "4.0.0-beta.83",
|
|
48
|
+
"@crawlee/utils": "4.0.0-beta.83",
|
|
49
49
|
"csv-stringify": "^6.5.2",
|
|
50
50
|
"fs-extra": "^11.3.0",
|
|
51
51
|
"ow": "^2.0.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"type-fest": "^4.41.0"
|
|
55
55
|
},
|
|
56
56
|
"optionalDependencies": {
|
|
57
|
-
"@crawlee/impit-client": "^4.0.0-beta.
|
|
57
|
+
"@crawlee/impit-client": "^4.0.0-beta.83"
|
|
58
58
|
},
|
|
59
59
|
"lerna": {
|
|
60
60
|
"command": {
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "5f25b90c4914d7e097732cf761e440aeba799137"
|
|
67
67
|
}
|