@crawlee/basic 4.0.0-beta.99 → 4.0.0-rc.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.
- package/README.md +1 -1
- package/index.d.ts +11 -1
- package/index.js +11 -0
- package/internals/autoscaling/autoscaled_pool.d.ts +178 -0
- package/internals/autoscaling/autoscaled_pool.js +387 -0
- package/internals/autoscaling/concurrency_system.d.ts +235 -0
- package/internals/autoscaling/concurrency_system.js +357 -0
- package/internals/autoscaling/cpu_load_signal.d.ts +43 -0
- package/internals/autoscaling/cpu_load_signal.js +46 -0
- package/internals/autoscaling/event_loop_load_signal.d.ts +51 -0
- package/internals/autoscaling/event_loop_load_signal.js +60 -0
- package/internals/autoscaling/index.d.ts +9 -0
- package/internals/autoscaling/index.js +9 -0
- package/internals/autoscaling/load_signal.d.ts +98 -0
- package/internals/autoscaling/load_signal.js +103 -0
- package/internals/autoscaling/memory_load_signal.d.ts +45 -0
- package/internals/autoscaling/memory_load_signal.js +104 -0
- package/internals/autoscaling/snapshotter.d.ts +84 -0
- package/internals/autoscaling/snapshotter.js +67 -0
- package/internals/autoscaling/storage_backend_load_signal.d.ts +56 -0
- package/internals/autoscaling/storage_backend_load_signal.js +73 -0
- package/internals/autoscaling/system_status.d.ts +112 -0
- package/internals/autoscaling/system_status.js +139 -0
- package/internals/autoscaling/weighted_avg.d.ts +5 -0
- package/internals/autoscaling/weighted_avg.js +14 -0
- package/internals/basic-crawler.d.ts +185 -389
- package/internals/basic-crawler.js +982 -684
- package/internals/cookie_utils.d.ts +40 -0
- package/internals/cookie_utils.js +122 -0
- package/internals/crawler-run.d.ts +76 -0
- package/internals/crawler-run.js +142 -0
- package/internals/crawlers/context_pipeline.d.ts +75 -0
- package/internals/crawlers/context_pipeline.js +109 -0
- package/internals/crawlers/crawler_commons.d.ts +216 -0
- package/internals/crawlers/crawler_commons.js +1 -0
- package/internals/crawlers/error_snapshotter.d.ts +29 -0
- package/internals/crawlers/error_snapshotter.js +116 -0
- package/internals/crawlers/error_tracker.d.ts +51 -0
- package/internals/crawlers/error_tracker.js +316 -0
- package/internals/crawlers/index.d.ts +4 -0
- package/internals/crawlers/index.js +3 -0
- package/internals/crawlers/internals/types.d.ts +7 -0
- package/internals/crawlers/internals/types.js +1 -0
- package/internals/crawlers/statistics.d.ts +316 -0
- package/internals/crawlers/statistics.js +525 -0
- package/internals/crawling_request.d.ts +86 -0
- package/internals/crawling_request.js +127 -0
- package/internals/enqueue_links/enqueue_links.d.ts +152 -0
- package/internals/enqueue_links/enqueue_links.js +76 -0
- package/internals/enqueue_links/index.d.ts +3 -0
- package/internals/enqueue_links/index.js +3 -0
- package/internals/enqueue_links/shared.d.ts +106 -0
- package/internals/enqueue_links/shared.js +258 -0
- package/internals/errors.d.ts +68 -0
- package/internals/errors.js +83 -0
- package/internals/http.d.ts +9 -0
- package/internals/http.js +28 -0
- package/internals/request-timeout.d.ts +6 -0
- package/internals/request-timeout.js +27 -2
- package/internals/router.d.ts +299 -0
- package/internals/router.js +312 -0
- package/internals/send-request.d.ts +2 -1
- package/internals/send-request.js +1 -0
- package/internals/session_pool/consts.d.ts +1 -0
- package/internals/session_pool/consts.js +1 -0
- package/internals/session_pool/errors.d.ts +7 -0
- package/internals/session_pool/errors.js +11 -0
- package/internals/session_pool/fingerprint.d.ts +9 -0
- package/internals/session_pool/fingerprint.js +30 -0
- package/internals/session_pool/index.d.ts +4 -0
- package/internals/session_pool/index.js +4 -0
- package/internals/session_pool/session.d.ts +151 -0
- package/internals/session_pool/session.js +225 -0
- package/internals/session_pool/session_pool.d.ts +193 -0
- package/internals/session_pool/session_pool.js +453 -0
- package/internals/sitemap_request_loader.d.ts +158 -0
- package/internals/sitemap_request_loader.js +432 -0
- package/internals/throttling_request_manager.d.ts +229 -0
- package/internals/throttling_request_manager.js +843 -0
- package/package.json +17 -14
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import type { AddRequestsBatchedOptions, AddRequestsBatchedResult,
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import type { AddRequestsBatchedOptions, AddRequestsBatchedResult, CrawleeLogger, DatasetExportOptions, IProxyConfiguration, IRequestLoader, IRequestManager, RequestsLike, Source, StorageIdentifier, StorageWritePolicy } from '@crawlee/core';
|
|
2
|
+
import { Configuration, Request, Dataset, EventManager, RequestQueue } from '@crawlee/core';
|
|
3
|
+
import { BaseHttpClient } from '@crawlee/http-client';
|
|
4
|
+
import type { Awaitable, Dictionary, ISessionPool, SetStatusMessageOptions, StorageBackend } from '@crawlee/types';
|
|
4
5
|
import { RobotsTxtFile } from '@crawlee/utils';
|
|
5
|
-
import type { ReadonlyDeep
|
|
6
|
-
import {
|
|
6
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { TaskLoopOptions } from './autoscaling/autoscaled_pool.js';
|
|
9
|
+
import type { ConcurrencySystemOptions, IConcurrencySystem } from './autoscaling/concurrency_system.js';
|
|
10
|
+
import { ConcurrencySystem } from './autoscaling/concurrency_system.js';
|
|
11
|
+
import type { FinalStatistics } from './autoscaling/system_status.js';
|
|
12
|
+
import { ContextPipeline } from './crawlers/context_pipeline.js';
|
|
13
|
+
import type { CrawlingContext, TypedRequestsLike } from './crawlers/crawler_commons.js';
|
|
14
|
+
import type { IStatistics, StatisticState } from './crawlers/statistics.js';
|
|
15
|
+
import type { EnqueueUrlsOptions, SkippedRequestCallback } from './enqueue_links/index.js';
|
|
16
|
+
import type { GetUserDataFromRequest, RouterHandler, RouterRoutes } from './router.js';
|
|
7
17
|
export interface BasicCrawlingContext<UserData extends Dictionary = Dictionary> extends CrawlingContext<UserData> {
|
|
8
18
|
}
|
|
9
19
|
export { navigationDeadlineKey, remainingNavigationWindowMillis } from './request-timeout.js';
|
|
@@ -27,7 +37,7 @@ export type StatusMessageCallback<Context extends CrawlingContext = BasicCrawlin
|
|
|
27
37
|
export type RequireContextPipeline<DefaultContextType extends CrawlingContext, FinalContextType extends DefaultContextType> = DefaultContextType extends FinalContextType ? {} : {
|
|
28
38
|
contextPipelineBuilder: () => ContextPipeline<CrawlingContext, FinalContextType>;
|
|
29
39
|
};
|
|
30
|
-
export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']
|
|
40
|
+
export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, StatisticStateExtension extends object = {}> {
|
|
31
41
|
/**
|
|
32
42
|
* User-provided function that performs the logic of the crawler. It is called for each URL to crawl.
|
|
33
43
|
*
|
|
@@ -43,7 +53,7 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
43
53
|
* To make this work, we should **always**
|
|
44
54
|
* let our function throw exceptions rather than catch them.
|
|
45
55
|
* The exceptions are logged to the request using the
|
|
46
|
-
* {@link
|
|
56
|
+
* {@link CrawlingRequest.pushErrorMessage|`request.pushErrorMessage()`} function.
|
|
47
57
|
*/
|
|
48
58
|
requestHandler?: RouterHandler<ExtendedContext, Routes> | RequestHandler<ExtendedContext>;
|
|
49
59
|
/**
|
|
@@ -135,7 +145,12 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
135
145
|
*/
|
|
136
146
|
maxRequestRetries?: number;
|
|
137
147
|
/**
|
|
138
|
-
* Indicates how much time (in seconds) to wait before crawling another same domain request.
|
|
148
|
+
* Indicates how much time (in seconds) to wait before crawling another same domain request. Subdomains are
|
|
149
|
+
* paced together with the site they belong to.
|
|
150
|
+
*
|
|
151
|
+
* Offered to the crawler's request manager as a `minIntervalEverywhere` {@link PacingSignal}; a manager that
|
|
152
|
+
* already paces every domain it dispatches to takes it, so no domain ends up with two clocks. Otherwise the
|
|
153
|
+
* crawler wraps its request manager in a {@link ThrottlingRequestManager} of its own.
|
|
139
154
|
* @default 0
|
|
140
155
|
*/
|
|
141
156
|
sameDomainDelaySecs?: number;
|
|
@@ -159,7 +174,7 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
159
174
|
* Concurrency is configured elsewhere — through the `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute`
|
|
160
175
|
* shortcuts, or a {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} for finer control.
|
|
161
176
|
*/
|
|
162
|
-
taskLoopOptions?:
|
|
177
|
+
taskLoopOptions?: TaskLoopOptions;
|
|
163
178
|
/**
|
|
164
179
|
* A pre-configured concurrency governor — the component that decides whether there is free compute for one more
|
|
165
180
|
* task. Typically a {@link ConcurrencySystem}, though any {@link IConcurrencySystem} is accepted. All
|
|
@@ -170,8 +185,8 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
170
185
|
* single budget. Each crawler still builds and drives its own {@link AutoscaledPool}; only the load/scaling
|
|
171
186
|
* accounting is shared.
|
|
172
187
|
*
|
|
173
|
-
* Mutually exclusive with the `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute`
|
|
174
|
-
* the default system this one replaces — combining the two throws.
|
|
188
|
+
* Mutually exclusive with the `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`maxRequestsPerMinute`
|
|
189
|
+
* shortcuts, which configure the default system this one replaces — combining the two throws.
|
|
175
190
|
*
|
|
176
191
|
* You own a supplied system's lifecycle: `start()` it before `run()` (which throws otherwise) and `stop()` it once
|
|
177
192
|
* every crawler borrowing it has finished. The crawler does neither on your behalf.
|
|
@@ -191,6 +206,12 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
191
206
|
* {@link ConcurrencySystem}.
|
|
192
207
|
*/
|
|
193
208
|
maxConcurrency?: number;
|
|
209
|
+
/**
|
|
210
|
+
* Sets the concurrency (parallelism) the crawl starts with, before any scaling happens. Shortcut for the
|
|
211
|
+
* {@link ConcurrencySystemOptions.desiredConcurrency|`desiredConcurrency`} option of the crawler's default
|
|
212
|
+
* {@link ConcurrencySystem}. Defaults to `minConcurrency`.
|
|
213
|
+
*/
|
|
214
|
+
initialConcurrency?: number;
|
|
194
215
|
/**
|
|
195
216
|
* The maximum number of requests per minute the crawler should run.
|
|
196
217
|
* By default, this is set to `Infinity`, but we can pass any positive, non-zero integer.
|
|
@@ -201,7 +222,16 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
201
222
|
/**
|
|
202
223
|
* Allows to keep the crawler alive even if the {@link RequestQueue} gets empty.
|
|
203
224
|
* By default, the `crawler.run()` will resolve once the queue is empty. With `keepAlive: true` it will keep running,
|
|
204
|
-
* waiting for more requests to come.
|
|
225
|
+
* waiting for more requests to come.
|
|
226
|
+
*
|
|
227
|
+
* `crawler.stop()` only stops the crawler from dispatching new requests — it does not wait for or drain
|
|
228
|
+
* requests already sitting in the queue. If this crawler is fed by another crawler or an external producer,
|
|
229
|
+
* calling `stop()` as soon as the producer finishes can abandon requests the producer already enqueued but
|
|
230
|
+
* this crawler had not yet picked up.
|
|
231
|
+
*
|
|
232
|
+
* To shut down only once the queue is genuinely empty and the producer has stopped, override
|
|
233
|
+
* {@link BasicCrawlerOptions.taskLoopOptions|`taskLoopOptions.isFinishedFunction`} to check both
|
|
234
|
+
* `(await requestManager.checkReadiness()).status === 'finished'` and the producer's own running/finished flag.
|
|
205
235
|
*/
|
|
206
236
|
keepAlive?: boolean;
|
|
207
237
|
/**
|
|
@@ -236,6 +266,10 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
236
266
|
statusMessageCallback?: StatusMessageCallback;
|
|
237
267
|
/**
|
|
238
268
|
* HTTP status codes that indicate the session should be retired.
|
|
269
|
+
*
|
|
270
|
+
* A 429 from a domain covered by a {@link ThrottlingRequestManager} is handled as a rate limit before
|
|
271
|
+
* this is consulted, so removing 429 here only affects domains that manager does not cover.
|
|
272
|
+
*
|
|
239
273
|
* @default [401, 403, 429]
|
|
240
274
|
*/
|
|
241
275
|
blockedStatusCodes?: number[];
|
|
@@ -263,14 +297,34 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
263
297
|
* 1. based on robots.txt file,
|
|
264
298
|
* 2. because they don't match enqueueLinks filters,
|
|
265
299
|
* 3. because they are redirected to a URL that doesn't match the enqueueLinks strategy,
|
|
266
|
-
* 4.
|
|
300
|
+
* 4. because the {@link BasicCrawlerOptions.maxRequestsPerCrawl|`maxRequestsPerCrawl`} limit has been reached,
|
|
301
|
+
* 5. or by {@link RestrictedCrawlingContext.skipRequest|`context.skipRequest()`}.
|
|
267
302
|
*/
|
|
268
303
|
onSkippedRequest?: SkippedRequestCallback;
|
|
269
304
|
/**
|
|
270
|
-
*
|
|
271
|
-
*
|
|
305
|
+
* A preconfigured statistics instance. When provided, the crawler records into it instead of building its own and
|
|
306
|
+
* will not `reset()` it between `run()` calls. Accepts the built-in {@link Statistics} or any object
|
|
307
|
+
* implementing {@link IStatistics}.
|
|
308
|
+
*
|
|
309
|
+
* Custom fields declared via {@link StatisticsOptions.stateExtension|`stateExtension`} are carried over to
|
|
310
|
+
* {@link BasicCrawler.statistics|`crawler.statistics.state`}:
|
|
311
|
+
*
|
|
312
|
+
* ```ts
|
|
313
|
+
* const statistics = new Statistics({ stateExtension: { defaultState: { productsFound: 0 } } });
|
|
314
|
+
*
|
|
315
|
+
* const crawler = new BasicCrawler({
|
|
316
|
+
* statistics,
|
|
317
|
+
* requestHandler: async () => {
|
|
318
|
+
* statistics.state.productsFound++;
|
|
319
|
+
* },
|
|
320
|
+
* });
|
|
321
|
+
*
|
|
322
|
+
* await crawler.run();
|
|
323
|
+
* // the custom fields are typed on `crawler.statistics` too
|
|
324
|
+
* console.log(crawler.statistics.state.productsFound);
|
|
325
|
+
* ```
|
|
272
326
|
*/
|
|
273
|
-
|
|
327
|
+
statistics?: IStatistics<StatisticStateExtension>;
|
|
274
328
|
/**
|
|
275
329
|
* HTTP client implementation for the `sendRequest` context helper and for plain HTTP crawling.
|
|
276
330
|
* Defaults to {@link ImpitHttpClient} when `@crawlee/impit-client` is installed, otherwise {@link FetchHttpClient}.
|
|
@@ -313,6 +367,20 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
313
367
|
*
|
|
314
368
|
*/
|
|
315
369
|
id?: string;
|
|
370
|
+
/**
|
|
371
|
+
* Makes the storage writes performed while handling a request atomic with respect to the request
|
|
372
|
+
* succeeding: they are recorded in a {@link StorageTransaction} spanning the whole request
|
|
373
|
+
* lifecycle and only applied when the request handler succeeds, so a thrown handler leaves no partial
|
|
374
|
+
* writes behind and a retry does not double-write. Reads within the handler see its own writes.
|
|
375
|
+
*
|
|
376
|
+
* `false` disables the mechanism entirely; an object overrides the per-storage-type
|
|
377
|
+
* {@link StorageWritePolicy} (e.g. `{ requestQueue: 'deferred' }` for all-or-nothing enqueues).
|
|
378
|
+
* {@link withDirectStorageAccess} is the per-call-site escape hatch; `useState()` is deliberately
|
|
379
|
+
* *not* transactional.
|
|
380
|
+
*
|
|
381
|
+
* @default true
|
|
382
|
+
*/
|
|
383
|
+
transactionalStorage?: boolean | Partial<StorageWritePolicy>;
|
|
316
384
|
/**
|
|
317
385
|
* An array of HTTP response [Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) to be excluded from error consideration.
|
|
318
386
|
* By default, status codes >= 500 trigger errors.
|
|
@@ -324,162 +392,39 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
324
392
|
*/
|
|
325
393
|
additionalHttpErrorStatusCodes?: number[];
|
|
326
394
|
}
|
|
327
|
-
|
|
328
|
-
* Provides a simple framework for parallel crawling of web pages.
|
|
329
|
-
* The URLs to crawl are fed either from a static list of URLs
|
|
330
|
-
* or from a dynamic queue of URLs enabling recursive crawling of websites.
|
|
331
|
-
*
|
|
332
|
-
* `BasicCrawler` is a low-level tool that requires the user to implement the page
|
|
333
|
-
* download and data extraction functionality themselves.
|
|
334
|
-
* If we want a crawler that already facilitates this functionality,
|
|
335
|
-
* we should consider using {@link CheerioCrawler}, {@link PuppeteerCrawler} or {@link PlaywrightCrawler}.
|
|
336
|
-
*
|
|
337
|
-
* `BasicCrawler` invokes the user-provided {@link BasicCrawlerOptions.requestHandler|`requestHandler`}
|
|
338
|
-
* for each {@link Request} object, which represents a single URL to crawl.
|
|
339
|
-
* The {@link Request} objects are fed from the {@link IRequestManager|request manager} provided via the
|
|
340
|
-
* {@link BasicCrawlerOptions.requestManager|`requestManager`} constructor option (a {@link RequestQueue} is
|
|
341
|
-
* itself a request manager). If no `requestManager` is provided, the crawler opens the default {@link RequestQueue}
|
|
342
|
-
* either when the {@link BasicCrawler.addRequests|`crawler.addRequests()`} function is called, or if the `requests`
|
|
343
|
-
* parameter (representing the initial requests) of the {@link BasicCrawler.run|`crawler.run()`} function is provided.
|
|
344
|
-
*
|
|
345
|
-
* To read requests from a read-only source such as a {@link RequestList} or {@link SitemapRequestLoader} while
|
|
346
|
-
* still being able to enqueue new ones, combine the loader with a queue into a {@link RequestManagerTandem} using
|
|
347
|
-
* {@link IRequestLoader.toTandem|`requestLoader.toTandem()`} and pass the result as `requestManager`. The tandem
|
|
348
|
-
* first processes URLs from the loader and automatically enqueues them into the queue, ensuring a single URL is not
|
|
349
|
-
* crawled multiple times.
|
|
350
|
-
*
|
|
351
|
-
* > The legacy {@link BasicCrawlerOptions.requestList|`requestList`} and
|
|
352
|
-
* > {@link BasicCrawlerOptions.requestQueue|`requestQueue`} options are deprecated. They are still accepted and
|
|
353
|
-
* > folded into a single `requestManager` (combined into a tandem when both are given), but new code should use
|
|
354
|
-
* > `requestManager` directly.
|
|
355
|
-
*
|
|
356
|
-
* The crawler finishes if there are no more {@link Request} objects to crawl.
|
|
357
|
-
*
|
|
358
|
-
* New requests are only dispatched when there is enough free CPU and memory available, as judged by the crawler's
|
|
359
|
-
* {@link ConcurrencySystem}.
|
|
360
|
-
* Concurrency is tuned via the {@link BasicCrawlerOptions.minConcurrency|`minConcurrency`},
|
|
361
|
-
* {@link BasicCrawlerOptions.maxConcurrency|`maxConcurrency`} and
|
|
362
|
-
* {@link BasicCrawlerOptions.maxRequestsPerMinute|`maxRequestsPerMinute`} shortcuts, or, for finer control, by
|
|
363
|
-
* injecting a pre-configured {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`}.
|
|
364
|
-
*
|
|
365
|
-
* **Example usage:**
|
|
366
|
-
*
|
|
367
|
-
* ```javascript
|
|
368
|
-
* import { BasicCrawler, Dataset } from 'crawlee';
|
|
369
|
-
*
|
|
370
|
-
* // Create a crawler instance
|
|
371
|
-
* const crawler = new BasicCrawler({
|
|
372
|
-
* async requestHandler({ request, sendRequest }) {
|
|
373
|
-
* // 'request' contains an instance of the Request class
|
|
374
|
-
* // Here we simply fetch the HTML of the page and store it to a dataset
|
|
375
|
-
* const { body } = await sendRequest({
|
|
376
|
-
* url: request.url,
|
|
377
|
-
* method: request.method,
|
|
378
|
-
* body: request.payload,
|
|
379
|
-
* headers: request.headers,
|
|
380
|
-
* });
|
|
381
|
-
*
|
|
382
|
-
* await Dataset.pushData({
|
|
383
|
-
* url: request.url,
|
|
384
|
-
* html: body,
|
|
385
|
-
* })
|
|
386
|
-
* },
|
|
387
|
-
* });
|
|
388
|
-
*
|
|
389
|
-
* // Enqueue the initial requests and run the crawler
|
|
390
|
-
* await crawler.run([
|
|
391
|
-
* 'http://www.example.com/page-1',
|
|
392
|
-
* 'http://www.example.com/page-2',
|
|
393
|
-
* ]);
|
|
394
|
-
* ```
|
|
395
|
-
* @category Crawlers
|
|
396
|
-
*/
|
|
397
|
-
/**
|
|
398
|
-
* Identifies a crawler instance for storage aliasing, `useState()` and status-message events.
|
|
399
|
-
*/
|
|
400
|
-
interface CrawlerIdentity {
|
|
401
|
-
/**
|
|
402
|
-
* 0-based instantiation order across all crawlers in the process.
|
|
403
|
-
* Note that the value can be subject to race conditions between different script invocations.
|
|
404
|
-
*/
|
|
405
|
-
readonly instanceIndex: number;
|
|
406
|
-
/** The user-supplied `id` option, or a fallback derived from `instanceIndex`. */
|
|
407
|
-
readonly id: string;
|
|
408
|
-
/** Whether `id` came from the user (as opposed to being derived from `instanceIndex`). */
|
|
409
|
-
readonly hasExplicitId: boolean;
|
|
410
|
-
}
|
|
411
|
-
export declare class BasicCrawler<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>> {
|
|
395
|
+
export declare class BasicCrawler<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, StatisticStateExtension extends object = {}> {
|
|
412
396
|
#private;
|
|
413
|
-
protected static readonly CRAWLEE_STATE_KEY = "CRAWLEE_STATE";
|
|
414
|
-
/**
|
|
415
|
-
* Tracks the number of crawler instances created. The first crawler uses the default
|
|
416
|
-
* request queue; subsequent ones get their own queue via a unique alias so they don't
|
|
417
|
-
* collide.
|
|
418
|
-
*/
|
|
419
|
-
private static instanceCount;
|
|
420
|
-
/**
|
|
421
|
-
* Tracks crawler instances that accessed shared state without having an explicit id.
|
|
422
|
-
* Used to detect and warn about multiple crawlers sharing the same state.
|
|
423
|
-
*/
|
|
424
|
-
private static useStateAnonymousIndices;
|
|
425
397
|
/**
|
|
426
|
-
*
|
|
398
|
+
* The statistics instance collecting the crawler's run statistics - either the injected `statistics` option or a
|
|
399
|
+
* crawler-built default. Typed as {@link IStatistics} so custom implementations can be plugged in.
|
|
427
400
|
*/
|
|
428
|
-
|
|
401
|
+
get statistics(): IStatistics<StatisticStateExtension>;
|
|
429
402
|
/**
|
|
430
403
|
* The main request-handling component of the crawler. It manages the requests that the crawler processes,
|
|
431
404
|
* combining any provided request loader and/or queue. It's initialized during the crawler startup or lazily
|
|
432
405
|
* via {@link BasicCrawler.getRequestManager|`getRequestManager()`}.
|
|
433
406
|
*/
|
|
434
|
-
protected requestManager
|
|
435
|
-
/** Backs the {@link BasicCrawler.sessionPool|`sessionPool`} getter. */
|
|
436
|
-
private sessionPoolDep;
|
|
407
|
+
protected get requestManager(): IRequestManager | undefined;
|
|
437
408
|
/**
|
|
438
409
|
* A reference to the underlying session pool that manages the crawler's {@link Session|sessions}. Typed as
|
|
439
410
|
* {@link ISessionPool} so custom implementations can be plugged in via the `sessionPool` constructor option.
|
|
440
411
|
*/
|
|
441
412
|
get sessionPool(): ISessionPool;
|
|
413
|
+
/** Whether a {@link BasicCrawler.run|`run()`} is in progress on this instance. */
|
|
414
|
+
get running(): boolean;
|
|
442
415
|
/**
|
|
443
|
-
*
|
|
444
|
-
* around a user-supplied `requestList` — so the owned-only purge between repeated `run()` calls never reaches
|
|
445
|
-
* through to a borrowed loader. Filled lazily in {@link BasicCrawler.openOwnedRequestQueue|`openOwnedRequestQueue()`}.
|
|
446
|
-
*/
|
|
447
|
-
private ownedRequestQueue;
|
|
448
|
-
/**
|
|
449
|
-
* Whether the request-processing-time hint has already been forwarded to the request manager. The hint
|
|
450
|
-
* derives only from `requestHandlerTimeoutMillis` (constant for the crawler's lifetime) and is raise-only,
|
|
451
|
-
* so it only needs to be applied once, at the first async access of the manager.
|
|
452
|
-
*/
|
|
453
|
-
private requestManagerTimeoutsApplied;
|
|
454
|
-
/**
|
|
455
|
-
* Resolves the governor for one run: either the injected
|
|
456
|
-
* {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} (borrowed) or a freshly built default with
|
|
457
|
-
* the concurrency shortcuts folded in (owned, so the crawler starts and stops it).
|
|
458
|
-
*/
|
|
459
|
-
private readonly resolveConcurrencySystem;
|
|
460
|
-
/** As resolved by `_init()`. Absent until the first run, so a `teardown()` before it is a no-op. */
|
|
461
|
-
private concurrencySystemDep?;
|
|
462
|
-
/**
|
|
463
|
-
* The concurrency governor this run is booking its requests against — either the
|
|
416
|
+
* The concurrency governor the run in progress is booking its requests against — either the
|
|
464
417
|
* {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} that was injected, or the default the
|
|
465
418
|
* crawler built for itself. Read it for telemetry: `desiredConcurrency`, `currentConcurrency`, `isRunning`.
|
|
466
419
|
*
|
|
467
|
-
* > *NOTE:* `undefined`
|
|
468
|
-
*
|
|
420
|
+
* > *NOTE:* `undefined` outside a run, and a crawler-owned default is rebuilt for every run — so read it
|
|
421
|
+
* during a run rather than caching it across runs.
|
|
469
422
|
*
|
|
470
423
|
* {@link IConcurrencySystem} is deliberately read-only. Tuning concurrency *while a crawl is running* means
|
|
471
424
|
* owning the instance: build a {@link ConcurrencySystem} yourself and inject it, then set
|
|
472
425
|
* `minConcurrency`/`maxConcurrency`/`desiredConcurrency` on your own reference.
|
|
473
426
|
*/
|
|
474
427
|
get concurrencySystem(): IConcurrencySystem | undefined;
|
|
475
|
-
/**
|
|
476
|
-
* The task loop that dispatches this run's requests. Private on purpose — it is a bare parallel task runner with
|
|
477
|
-
* no configuration left of its own (see {@link ConcurrencySystem}), and everything a caller legitimately did
|
|
478
|
-
* with it now has a crawler-level counterpart: {@link BasicCrawler.pause|`pause()`},
|
|
479
|
-
* {@link BasicCrawler.resume|`resume()`}, {@link BasicCrawler.teardown|`teardown()`} and
|
|
480
|
-
* {@link BasicCrawler.concurrencySystem|`concurrencySystem`}.
|
|
481
|
-
*/
|
|
482
|
-
private autoscaledPool?;
|
|
483
428
|
/**
|
|
484
429
|
* A reference to the underlying {@link IProxyConfiguration} instance that manages the crawler's proxies.
|
|
485
430
|
* Only available if used by the crawler.
|
|
@@ -490,135 +435,72 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
490
435
|
* See {@link Router.addHandler|`router.addHandler()`} and {@link Router.addDefaultHandler|`router.addDefaultHandler()`}.
|
|
491
436
|
*/
|
|
492
437
|
readonly router: RouterHandler<Context, Routes>;
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* The basic part of the context pipeline. Unlike the subclass pipeline, this
|
|
496
|
-
* part has no major side effects (e.g. launching a browser). It also makes typing more explicit, as subclass
|
|
497
|
-
* pipelines expect the basic crawler fields to already be present in the context at runtime.
|
|
498
|
-
*
|
|
499
|
-
* Context built with this pipeline can be passed into multiple crawler pipelines at once.
|
|
500
|
-
* This is used e.g. in the {@link AdaptivePlaywrightCrawler|`AdaptivePlaywrightCrawler`}.
|
|
501
|
-
*/
|
|
502
|
-
get basicContextPipeline(): ContextPipeline<{
|
|
503
|
-
request: Request;
|
|
504
|
-
}, CrawlingContext>;
|
|
505
|
-
private _contextPipeline?;
|
|
438
|
+
/** @internal */
|
|
506
439
|
get contextPipeline(): ContextPipeline<CrawlingContext, ExtendedContext>;
|
|
507
|
-
|
|
508
|
-
hasFinishedBefore: boolean;
|
|
509
|
-
private unexpectedStop;
|
|
440
|
+
/** Whether a `run()` on this instance has already finished - a repeated one continues where it left off. */
|
|
441
|
+
get hasFinishedBefore(): boolean;
|
|
510
442
|
get log(): CrawleeLogger;
|
|
511
443
|
protected readonly requestHandler: RequestHandler<ExtendedContext>;
|
|
512
|
-
protected readonly errorHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
|
|
513
|
-
protected readonly failedRequestHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
|
|
514
|
-
private requestHandlerTimeoutMillis;
|
|
515
444
|
protected readonly internalTimeoutMillis: number;
|
|
516
|
-
protected readonly maxRequestRetries: number;
|
|
517
|
-
protected readonly maxCrawlDepth?: number;
|
|
518
|
-
private sameDomainDelayMillis;
|
|
519
|
-
private domainAccessedTime;
|
|
520
|
-
protected readonly maxRequestsPerCrawl?: number;
|
|
521
|
-
private get handledRequestsCount();
|
|
522
|
-
private statusMessageLoggingInterval;
|
|
523
|
-
private statusMessageCallback?;
|
|
524
445
|
protected blockedStatusCodes: Set<number>;
|
|
525
446
|
protected readonly additionalHttpErrorStatusCodes: Set<number>;
|
|
526
|
-
private ignoreHttpErrorStatusCodes;
|
|
527
|
-
/**
|
|
528
|
-
* The resolved options for the crawler's own task loop — the crawler-owned `runTaskFunction`, the (possibly
|
|
529
|
-
* user-overridden) ready/finished predicates and cadence/logging. Concurrency configuration lives on the
|
|
530
|
-
* {@link ConcurrencySystem} instead, and the loop's `consumer` identity is the crawler's own, so neither is
|
|
531
|
-
* settable here.
|
|
532
|
-
*/
|
|
533
|
-
private taskLoopOptions;
|
|
534
447
|
protected readonly httpClient: BaseHttpClient;
|
|
535
448
|
protected readonly retryOnBlocked: boolean;
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
private loggedPerRun;
|
|
540
|
-
private readonly robotsTxtFileCache;
|
|
541
|
-
protected readonly identity: CrawlerIdentity;
|
|
542
|
-
private readonly contextPipelineOptions;
|
|
449
|
+
/**
|
|
450
|
+
* @internal
|
|
451
|
+
*/
|
|
543
452
|
protected static optionsShape: {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
retryOnBlocked: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
|
|
588
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
589
|
-
respectRobotsTxtFile: import("ow").AnyPredicate<boolean | object>;
|
|
590
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
591
|
-
onSkippedRequest: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
|
|
592
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
593
|
-
httpClient: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
594
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
595
|
-
configuration: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
596
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
597
|
-
storageBackend: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
598
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
599
|
-
eventManager: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
600
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
601
|
-
logger: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
602
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
603
|
-
minConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
604
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
605
|
-
maxConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
606
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
607
|
-
maxRequestsPerMinute: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
608
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
609
|
-
keepAlive: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
|
|
610
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
611
|
-
statisticsOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
612
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
613
|
-
id: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
|
|
453
|
+
contextPipelineBuilder: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
454
|
+
extendContext: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
455
|
+
requestList: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
456
|
+
requestQueue: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
457
|
+
requestManager: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
458
|
+
requestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
459
|
+
requestHandlerTimeoutSecs: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
460
|
+
errorHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
461
|
+
failedRequestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
462
|
+
maxRequestRetries: z.ZodDefault<z.ZodCustom<number, number>>;
|
|
463
|
+
sameDomainDelaySecs: z.ZodDefault<z.ZodCustom<number, number>>;
|
|
464
|
+
maxRequestsPerCrawl: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
465
|
+
maxCrawlDepth: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
466
|
+
taskLoopOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
467
|
+
concurrencySystem: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
468
|
+
sessionPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
469
|
+
proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
470
|
+
statusMessageLoggingInterval: z.ZodDefault<z.ZodCustom<number, number>>;
|
|
471
|
+
statusMessageCallback: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
472
|
+
additionalHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
|
|
473
|
+
ignoreHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
|
|
474
|
+
blockedStatusCodes: z.ZodOptional<z.ZodArray<z.ZodCustom<number, number>>>;
|
|
475
|
+
retryOnBlocked: z.ZodDefault<z.ZodBoolean>;
|
|
476
|
+
respectRobotsTxtFile: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCustom<Dictionary, Dictionary>]>>;
|
|
477
|
+
transactionalStorage: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
478
|
+
requestQueue: z.ZodOptional<z.ZodEnum<{
|
|
479
|
+
deferred: "deferred";
|
|
480
|
+
writeThrough: "writeThrough";
|
|
481
|
+
}>>;
|
|
482
|
+
}, z.core.$strict>]>>;
|
|
483
|
+
onSkippedRequest: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
484
|
+
httpClient: z.ZodOptional<z.ZodInstanceOf<BaseHttpClient>>;
|
|
485
|
+
configuration: z.ZodOptional<z.ZodInstanceOf<Configuration>>;
|
|
486
|
+
storageBackend: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
487
|
+
eventManager: z.ZodOptional<z.ZodInstanceOf<EventManager>>;
|
|
488
|
+
logger: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
489
|
+
minConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
490
|
+
maxConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
491
|
+
initialConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
492
|
+
maxRequestsPerMinute: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
493
|
+
keepAlive: z.ZodOptional<z.ZodBoolean>;
|
|
494
|
+
statistics: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
495
|
+
id: z.ZodOptional<z.ZodString>;
|
|
614
496
|
};
|
|
615
497
|
/**
|
|
616
498
|
* All `BasicCrawler` parameters are passed via an options object.
|
|
617
499
|
*/
|
|
618
|
-
constructor(options?: BasicCrawlerOptions<Context, ContextExtension, ExtendedContext, Routes> & RequireContextPipeline<CrawlingContext, Context>);
|
|
500
|
+
constructor(options?: BasicCrawlerOptions<Context, ContextExtension, ExtendedContext, Routes, StatisticStateExtension> & RequireContextPipeline<CrawlingContext, Context>);
|
|
619
501
|
/**
|
|
620
502
|
* Builds the crawler-owned default {@link ConcurrencySystem} from the resolved
|
|
621
|
-
* `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute` shortcuts. Not called when a
|
|
503
|
+
* `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`maxRequestsPerMinute` shortcuts. Not called when a
|
|
622
504
|
* {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} was injected.
|
|
623
505
|
*
|
|
624
506
|
* Subclasses may override this to tune the default system (e.g. {@link HttpCrawler} raises the starting
|
|
@@ -632,22 +514,6 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
632
514
|
* @returns `true` if the status code is considered an error, `false` otherwise
|
|
633
515
|
*/
|
|
634
516
|
protected isErrorStatusCode(status: number): boolean;
|
|
635
|
-
/**
|
|
636
|
-
* Builds the basic context pipeline that transforms `{ request }` into a full `CrawlingContext`.
|
|
637
|
-
* This handles base context creation, session resolution, and context helpers.
|
|
638
|
-
*/
|
|
639
|
-
private buildBasicContextPipeline;
|
|
640
|
-
private checkRobotsTxt;
|
|
641
|
-
/**
|
|
642
|
-
* Builds the subclass-specific context pipeline that transforms a `CrawlingContext` into the crawler's target context type.
|
|
643
|
-
* Subclasses should override this to add their own pipeline stages.
|
|
644
|
-
*/
|
|
645
|
-
protected buildContextPipeline(): ContextPipeline<CrawlingContext, CrawlingContext>;
|
|
646
|
-
private createBaseContext;
|
|
647
|
-
private resolveRequest;
|
|
648
|
-
private resolveSession;
|
|
649
|
-
private createContextHelpers;
|
|
650
|
-
private buildFinalContextPipeline;
|
|
651
517
|
/**
|
|
652
518
|
* Checks if the given error is a proxy error by comparing its message to a list of known proxy error messages.
|
|
653
519
|
* Used for retrying requests that failed due to proxy errors.
|
|
@@ -665,7 +531,6 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
665
531
|
* their status-reporting backend (e.g. the Apify platform).
|
|
666
532
|
*/
|
|
667
533
|
setStatusMessage(message: string, options?: SetStatusMessageOptions): void;
|
|
668
|
-
private getPeriodicLogger;
|
|
669
534
|
/**
|
|
670
535
|
* Runs the crawler. Returns a promise that resolves once every request has been processed and the crawler's
|
|
671
536
|
* finished-check ({@link BasicCrawlerOptions.taskLoopOptions|`taskLoopOptions.isFinishedFunction`}, or the
|
|
@@ -674,8 +539,12 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
674
539
|
* We can use the `requests` parameter to enqueue the initial requests — it is a shortcut for
|
|
675
540
|
* running {@link BasicCrawler.addRequests|`crawler.addRequests()`} before {@link BasicCrawler.run|`crawler.run()`}.
|
|
676
541
|
*
|
|
542
|
+
* Calling `run()` again on the same instance keeps crawling the same request manager - requests the previous
|
|
543
|
+
* run handled (a failed one counts as handled) are not processed again. Purge the queue or open a fresh one
|
|
544
|
+
* if that is what you want.
|
|
545
|
+
*
|
|
677
546
|
* @param [requests] The requests to add.
|
|
678
|
-
* @param [options] Options for the
|
|
547
|
+
* @param [options] Options for adding the initial requests.
|
|
679
548
|
*/
|
|
680
549
|
run(requests?: TypedRequestsLike<Routes>, options?: CrawlerRunOptions): Promise<FinalStatistics>;
|
|
681
550
|
/**
|
|
@@ -710,39 +579,18 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
710
579
|
* crawler's request manager, which is no longer guaranteed to be a {@link RequestQueue}.
|
|
711
580
|
*/
|
|
712
581
|
getRequestQueue(): Promise<IRequestManager>;
|
|
713
|
-
/**
|
|
714
|
-
* Opens the default {@link RequestQueue}, applies the crawler's timeouts to it and records it as the
|
|
715
|
-
* crawler-owned queue (so it gets purged between repeated `run()` calls).
|
|
716
|
-
* @private
|
|
717
|
-
*/
|
|
718
|
-
private openOwnedRequestQueue;
|
|
719
|
-
/**
|
|
720
|
-
* Tells a request manager how long we expect to hold a fetched request, so that one backed by a
|
|
721
|
-
* locking storage backend keeps it reserved for slightly longer than the request handler timeout
|
|
722
|
-
* (with some padding for overhead), but never for less than a minute. This prevents a long-running
|
|
723
|
-
* request from being handed out a second time while it is still being processed — and it works
|
|
724
|
-
* regardless of whether the manager is a plain {@link RequestQueue} or a `RequestManagerTandem`.
|
|
725
|
-
*/
|
|
726
|
-
private applyRequestManagerTimeouts;
|
|
727
|
-
/**
|
|
728
|
-
* Validates a request source's `userData` against the {@link RouteSchemas|Standard Schema} registered
|
|
729
|
-
* for its label on the crawler's schema-router (if any), throwing a {@link RequestValidationError} on
|
|
730
|
-
* mismatch. A no-op when the user's request handler is not a schema-router, or no schema is registered for
|
|
731
|
-
* the request's label. Applied by the crawler on the add paths it owns — `crawler.addRequests`,
|
|
732
|
-
* `crawler.run`, `context.addRequests` and `context.enqueueLinks`.
|
|
733
|
-
*/
|
|
734
|
-
private validateRequestUserData;
|
|
735
582
|
useState<State extends Dictionary = Dictionary>(defaultValue?: State): Promise<State>;
|
|
736
|
-
protected getPendingRequestCountApproximation(): Promise<number>;
|
|
737
|
-
protected calculateEnqueuedRequestLimit(explicitLimit?: number): Promise<number | undefined>;
|
|
738
|
-
protected handleSkippedRequest(options: Parameters<SkippedRequestCallback>[0]): Promise<void>;
|
|
739
|
-
private logOncePerRun;
|
|
740
583
|
/**
|
|
741
584
|
* Adds requests to the queue in batches. By default, it will resolve after the initial batch is added, and continue
|
|
742
585
|
* adding the rest in background. You can configure the batch size via `batchSize` option and the sleep time in between
|
|
743
586
|
* the batches via `waitBetweenBatchesMillis`. If you want to wait for all batches to be added to the queue, you can use
|
|
744
587
|
* the `waitForAllRequestsToBeAdded` promise you get in the response object.
|
|
745
588
|
*
|
|
589
|
+
* Optionally, the requests can be filtered using `include`/`exclude` glob or regexp patterns and an
|
|
590
|
+
* enqueue `strategy` (both AND-ed together, same as {@link CrawlingContext.enqueueLinks|`enqueueLinks`}),
|
|
591
|
+
* relative to `baseUrl`. Unlike `enqueueLinks`, there is no implicit "current page" to anchor the strategy
|
|
592
|
+
* to, so `strategy` defaults to {@link EnqueueStrategy.All|`all`} here.
|
|
593
|
+
*
|
|
746
594
|
* This is an alias for calling `addRequestsBatched()` on the implicit `RequestQueue` for this crawler instance.
|
|
747
595
|
*
|
|
748
596
|
* @param requests The requests to add
|
|
@@ -769,84 +617,41 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
769
617
|
/**
|
|
770
618
|
* Initializes the crawler.
|
|
771
619
|
*/
|
|
772
|
-
protected
|
|
620
|
+
protected init(): Promise<void>;
|
|
773
621
|
/**
|
|
774
622
|
* The navigation timeout (pre-navigation hooks, navigation, and post-navigation hooks) in milliseconds, used
|
|
775
623
|
* to size the internal request timeout. `BasicCrawler` has no navigation phase, so this is 0; the HTTP and
|
|
776
624
|
* browser crawlers override it with their `navigationTimeoutSecs`.
|
|
777
625
|
*/
|
|
778
626
|
protected getNavigationTimeoutMillis(): number;
|
|
779
|
-
/**
|
|
780
|
-
* Races the request against the internal timeout (see {@link raceWithTimeout}), sized to outlast the phases
|
|
781
|
-
* that have their own timeout - the navigation, its hooks, and the request handler - so a legitimately slow
|
|
782
|
-
* request, a per-route override, or a low `CRAWLEE_INTERNAL_TIMEOUT` is not cut short mid-phase. It takes
|
|
783
|
-
* whichever is larger: the configured internal timeout, or this request's combined phase budget.
|
|
784
|
-
*/
|
|
785
|
-
private withRequestTimeout;
|
|
786
|
-
/**
|
|
787
|
-
* The request handler timeout for a request with the given route label. A router route may override the
|
|
788
|
-
* crawler's own `requestHandlerTimeoutSecs`; anything else falls back to `fallbackMillis`.
|
|
789
|
-
*
|
|
790
|
-
* @param label The request's route label, or `undefined` for the default route / no specific request.
|
|
791
|
-
* @param fallbackMillis Timeout to use when no route overrides it.
|
|
792
|
-
*/
|
|
793
|
-
private resolveRequestHandlerTimeoutMillis;
|
|
794
|
-
/**
|
|
795
|
-
* The timeout the router route with the given label asked for, or `undefined` when it did not override one
|
|
796
|
-
* (or the request handler is not a router at all).
|
|
797
|
-
*/
|
|
798
|
-
private getRouteTimeoutMillis;
|
|
799
627
|
protected runRequestHandler(crawlingContext: ExtendedContext): Promise<void>;
|
|
800
628
|
/**
|
|
801
|
-
*
|
|
629
|
+
* Runs `callback` inside a {@link StorageTransaction}, unless transactional storage is disabled.
|
|
630
|
+
* Deliberately does **not** commit on return - the pipeline hands failures to `handleRequestFailure`, so a
|
|
631
|
+
* normal return says nothing about success. `handleRequest` commits on success.
|
|
802
632
|
*/
|
|
803
|
-
|
|
804
|
-
private isAllowedBasedOnRobotsTxtFile;
|
|
805
|
-
protected getRobotsTxtFileForUrl(url: string): Promise<RobotsTxtFile | undefined>;
|
|
806
|
-
private pauseOnMigration;
|
|
633
|
+
private runInStorageTransaction;
|
|
807
634
|
/**
|
|
808
|
-
*
|
|
635
|
+
* Handles blocked request
|
|
809
636
|
*/
|
|
810
|
-
|
|
637
|
+
protected throwOnBlockedRequest(statusCode: number): void;
|
|
811
638
|
/**
|
|
812
|
-
*
|
|
813
|
-
*
|
|
814
|
-
*
|
|
639
|
+
* Records an HTTP 429 against the URL's domain so the request manager can hold the retry back.
|
|
640
|
+
*
|
|
641
|
+
* @param retryAfterHeader The raw `Retry-After` response header, if the server sent one.
|
|
642
|
+
* @returns `true` if the manager took responsibility for the delay, in which case the caller should throw
|
|
643
|
+
* {@link RequestThrottledError} rather than treating the response as a blocked session.
|
|
815
644
|
*/
|
|
816
|
-
|
|
817
|
-
/**
|
|
645
|
+
protected recordDomainRateLimit(url: string, retryAfterHeader?: string | null): boolean;
|
|
646
|
+
/** @internal */
|
|
647
|
+
protected getRobotsTxtFileForUrl(url: string): Promise<RobotsTxtFile | undefined>;
|
|
648
|
+
/** Runs the request handler and marks the request as handled. Failures are left to `handleRequestFailure`. */
|
|
818
649
|
private handleRequest;
|
|
819
|
-
/**
|
|
820
|
-
* Wrapper around the crawling context's `enqueueLinks` method:
|
|
821
|
-
* - Injects `crawlDepth` to each request being added based on the crawling context request.
|
|
822
|
-
* - Provides defaults for the `enqueueLinks` options based on the crawler configuration.
|
|
823
|
-
* - These options can be overridden by the user.
|
|
824
|
-
* @internal
|
|
825
|
-
*/
|
|
826
|
-
protected enqueueLinksWithCrawlDepth(options: SetRequired<EnqueueLinksOptions, 'urls'>, request: Request<Dictionary>, requestManager: IRequestManager): Promise<BatchAddRequestsResult>;
|
|
827
650
|
/**
|
|
828
651
|
* Generator function that yields requests injected with the given crawl depth.
|
|
829
652
|
* @internal
|
|
830
653
|
*/
|
|
831
654
|
protected addCrawlDepthRequestGenerator(requests: RequestsLike, newRequestDepth: number): AsyncGenerator<Source, void, undefined>;
|
|
832
|
-
/**
|
|
833
|
-
* Run async callback with given timeout and retry. Returns the result of the callback.
|
|
834
|
-
* @ignore
|
|
835
|
-
*/
|
|
836
|
-
private timeoutAndRetry;
|
|
837
|
-
/**
|
|
838
|
-
* Returns true if either RequestList or RequestQueue have a request ready for processing.
|
|
839
|
-
*/
|
|
840
|
-
private isTaskReadyFunction;
|
|
841
|
-
/**
|
|
842
|
-
* Returns true if both RequestList and RequestQueue have all requests finished.
|
|
843
|
-
*/
|
|
844
|
-
private defaultIsFinishedFunction;
|
|
845
|
-
/**
|
|
846
|
-
* Unwraps errors thrown by the context pipeline to get the actual user error.
|
|
847
|
-
* RequestHandlerError and ContextPipelineInitializationError wrap the actual error.
|
|
848
|
-
*/
|
|
849
|
-
private unwrapError;
|
|
850
655
|
/**
|
|
851
656
|
* Handles errors thrown by user provided requestHandler()
|
|
852
657
|
*
|
|
@@ -859,40 +664,31 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
859
664
|
* @param error The error received
|
|
860
665
|
* @returns The message to be logged
|
|
861
666
|
*/
|
|
862
|
-
protected
|
|
863
|
-
private canRequestBeRetried;
|
|
667
|
+
protected getMessageFromError(error: Error, forceStack?: boolean): string;
|
|
864
668
|
/**
|
|
865
|
-
*
|
|
669
|
+
* Ends the run in progress immediately, without waiting for the requests already in flight.
|
|
866
670
|
*
|
|
867
|
-
* This
|
|
671
|
+
* This runs at the end of every {@link BasicCrawler.run|`run()`}, so what it releases is per-run only, and
|
|
672
|
+
* a repeated `run()` has to find everything it needs either intact or re-establishable. What outlives a run is
|
|
673
|
+
* released by {@link BasicCrawler.destroy|`destroy()`} instead.
|
|
868
674
|
*
|
|
869
675
|
* To stop the crawler gracefully (waiting for all running requests to finish), use {@link BasicCrawler.stop|`crawler.stop()`} instead.
|
|
870
676
|
*/
|
|
871
677
|
teardown(): Promise<void>;
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
678
|
+
/**
|
|
679
|
+
* Releases what the crawler owns beyond a single run — in the browser crawlers, the browser pool. A finished
|
|
680
|
+
* `run()` has already released everything a run owns, so this is only needed before dropping a crawler you
|
|
681
|
+
* could otherwise have run again.
|
|
682
|
+
*/
|
|
683
|
+
destroy(): Promise<void>;
|
|
684
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
685
|
+
protected getCookieHeaderFromRequest(request: Request): string;
|
|
879
686
|
}
|
|
880
|
-
export interface CrawlerAddRequestsOptions extends AddRequestsBatchedOptions {
|
|
687
|
+
export interface CrawlerAddRequestsOptions extends AddRequestsBatchedOptions, EnqueueUrlsOptions {
|
|
881
688
|
}
|
|
882
689
|
export interface CrawlerAddRequestsResult extends AddRequestsBatchedResult {
|
|
883
690
|
}
|
|
884
691
|
export interface CrawlerRunOptions extends CrawlerAddRequestsOptions {
|
|
885
|
-
/**
|
|
886
|
-
* Controls whether the request queue is purged between repeated `run()` calls on the same crawler instance.
|
|
887
|
-
* Purging clears all requests and resets internal counters, allowing the same URLs to be processed again.
|
|
888
|
-
*
|
|
889
|
-
* - **`undefined`** (default) — only the crawler's own (auto-created) queue is purged.
|
|
890
|
-
* A user-supplied `requestQueue` is left untouched.
|
|
891
|
-
* - **`true`** — the queue is always purged, even if it was supplied by the user.
|
|
892
|
-
* - **`false`** — nothing is purged. Only genuinely new requests will be processed;
|
|
893
|
-
* note that even a failed request is considered handled.
|
|
894
|
-
*/
|
|
895
|
-
purgeRequestQueue?: boolean;
|
|
896
692
|
}
|
|
897
693
|
/**
|
|
898
694
|
* Creates new {@link Router} instance that works based on request labels.
|