@crawlee/basic 4.0.0-beta.11 → 4.0.0-beta.111
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 +17 -13
- package/index.d.ts +1 -1
- package/index.js +0 -1
- package/internals/basic-crawler.d.ts +497 -219
- package/internals/basic-crawler.js +1130 -600
- package/internals/request-timeout.d.ts +48 -0
- package/internals/request-timeout.js +73 -0
- package/internals/send-request.d.ts +3 -6
- package/internals/send-request.js +21 -26
- package/package.json +12 -10
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/internals/basic-crawler.d.ts.map +0 -1
- package/internals/basic-crawler.js.map +0 -1
- package/internals/send-request.d.ts.map +0 -1
- package/internals/send-request.js.map +0 -1
- package/tsconfig.build.tsbuildinfo +0 -1
|
@@ -1,25 +1,34 @@
|
|
|
1
|
-
import type { AddRequestsBatchedOptions, AddRequestsBatchedResult,
|
|
2
|
-
import {
|
|
3
|
-
import type { Awaitable, Dictionary, SetStatusMessageOptions } from '@crawlee/types';
|
|
1
|
+
import type { AddRequestsBatchedOptions, AddRequestsBatchedResult, ConcurrencySystemOptions, Configuration, CrawleeLogger, CrawlingContext, DatasetExportOptions, EnqueueLinksOptions, EventManager, FinalStatistics, GetUserDataFromRequest, IConcurrencySystem, IProxyConfiguration, IRequestLoader, IRequestManager, IStatistics, Request, RequestsLike, RouterHandler, RouterRoutes, SkippedRequestCallback, Source, StatisticState, StorageIdentifier, StorageWritePolicy, TaskLoopPredicates, TypedRequestsLike } from '@crawlee/core';
|
|
2
|
+
import { ConcurrencySystem, ContextPipeline, Dataset, RequestQueue } from '@crawlee/core';
|
|
3
|
+
import type { Awaitable, BaseHttpClient, BatchAddRequestsResult, Dictionary, ISession, ISessionPool, ProxyInfo, SetStatusMessageOptions, StorageBackend } from '@crawlee/types';
|
|
4
4
|
import { RobotsTxtFile } from '@crawlee/utils';
|
|
5
|
-
import type
|
|
6
|
-
import type {
|
|
5
|
+
import { type BasePredicate } from 'ow';
|
|
6
|
+
import type { ReadonlyDeep, SetRequired } from 'type-fest';
|
|
7
7
|
import { TimeoutError } from '@apify/timeout';
|
|
8
8
|
export interface BasicCrawlingContext<UserData extends Dictionary = Dictionary> extends CrawlingContext<UserData> {
|
|
9
9
|
}
|
|
10
|
+
export { navigationDeadlineKey, remainingNavigationWindowMillis } from './request-timeout.js';
|
|
10
11
|
export type RequestHandler<Context extends CrawlingContext = CrawlingContext> = (inputs: Context) => Awaitable<void>;
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* An error handler receives the crawling context and the error that was thrown while processing the request.
|
|
14
|
+
*
|
|
15
|
+
* Unlike the {@link RequestHandler}, an error handler may run before the context pipeline has finished
|
|
16
|
+
* building the full context (e.g. when navigation or session setup fails). Therefore only `BaseContext` is
|
|
17
|
+
* guaranteed to be present, while the extra properties added by the pipeline and `extendContext` (the
|
|
18
|
+
* difference between `BaseContext` and `ExtendedContext`) are only available as a `Partial`.
|
|
19
|
+
*/
|
|
20
|
+
export type ErrorHandler<BaseContext extends CrawlingContext = CrawlingContext, ExtendedContext extends BaseContext = BaseContext> = (inputs: BaseContext & Partial<ExtendedContext>, error: Error) => Awaitable<void>;
|
|
21
|
+
export interface StatusMessageCallbackParams<Context extends CrawlingContext = BasicCrawlingContext, Crawler extends BasicCrawler<any, any, any, any> = BasicCrawler<Context>> {
|
|
13
22
|
state: StatisticState;
|
|
14
23
|
crawler: Crawler;
|
|
15
24
|
previousState: StatisticState;
|
|
16
25
|
message: string;
|
|
17
26
|
}
|
|
18
|
-
export type StatusMessageCallback<Context extends CrawlingContext = BasicCrawlingContext, Crawler extends BasicCrawler<any> = BasicCrawler<Context>> = (params: StatusMessageCallbackParams<Context, Crawler>) => Awaitable<void>;
|
|
27
|
+
export type StatusMessageCallback<Context extends CrawlingContext = BasicCrawlingContext, Crawler extends BasicCrawler<any, any, any, any> = BasicCrawler<Context>> = (params: StatusMessageCallbackParams<Context, Crawler>) => Awaitable<void>;
|
|
19
28
|
export type RequireContextPipeline<DefaultContextType extends CrawlingContext, FinalContextType extends DefaultContextType> = DefaultContextType extends FinalContextType ? {} : {
|
|
20
29
|
contextPipelineBuilder: () => ContextPipeline<CrawlingContext, FinalContextType>;
|
|
21
30
|
};
|
|
22
|
-
export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingContext, ContextExtension =
|
|
31
|
+
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']>>> {
|
|
23
32
|
/**
|
|
24
33
|
* User-provided function that performs the logic of the crawler. It is called for each URL to crawl.
|
|
25
34
|
*
|
|
@@ -37,9 +46,15 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
37
46
|
* The exceptions are logged to the request using the
|
|
38
47
|
* {@link Request.pushErrorMessage|`Request.pushErrorMessage()`} function.
|
|
39
48
|
*/
|
|
40
|
-
requestHandler?: RequestHandler<ExtendedContext>;
|
|
49
|
+
requestHandler?: RouterHandler<ExtendedContext, Routes> | RequestHandler<ExtendedContext>;
|
|
41
50
|
/**
|
|
42
|
-
* Allows the user to extend the crawling context
|
|
51
|
+
* Allows the user to extend the crawling context with custom functionality (helpers, references, etc.).
|
|
52
|
+
*
|
|
53
|
+
* `extendContext` runs *before* navigation, so the returned members are visible to the
|
|
54
|
+
* `preNavigationHooks`, `postNavigationHooks`, and the `requestHandler` alike. As a consequence,
|
|
55
|
+
* the `context` passed to `extendContext` is the pre-navigation {@link CrawlingContext} and does
|
|
56
|
+
* **not** include navigation-dependent members (e.g. `page`, `response`, `$`, `body`). If you need
|
|
57
|
+
* those, use a `postNavigationHook` or the `requestHandler` instead.
|
|
43
58
|
*
|
|
44
59
|
* **Example usage:**
|
|
45
60
|
*
|
|
@@ -59,7 +74,7 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
59
74
|
* });
|
|
60
75
|
* ```
|
|
61
76
|
*/
|
|
62
|
-
extendContext?: (context:
|
|
77
|
+
extendContext?: (context: CrawlingContext) => Awaitable<ContextExtension>;
|
|
63
78
|
/**
|
|
64
79
|
* *Intended for BasicCrawler subclasses*. Prepares a context pipeline that transforms the initial crawling context into the shape given by the `Context` type parameter.
|
|
65
80
|
*
|
|
@@ -68,18 +83,27 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
68
83
|
contextPipelineBuilder?: () => ContextPipeline<CrawlingContext, Context>;
|
|
69
84
|
/**
|
|
70
85
|
* Static list of URLs to be processed.
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
86
|
+
*
|
|
87
|
+
* @deprecated Use the `requestManager` option instead. To combine a read-only loader (such as a `RequestList`)
|
|
88
|
+
* with a writable queue, build a tandem with {@link IRequestLoader.toTandem|`requestList.toTandem(requestQueue)`}
|
|
89
|
+
* and pass the result as `requestManager`. When both `requestList` and `requestQueue` are provided, they are
|
|
90
|
+
* combined into a tandem automatically.
|
|
74
91
|
*/
|
|
75
|
-
requestList?:
|
|
92
|
+
requestList?: IRequestLoader;
|
|
76
93
|
/**
|
|
77
94
|
* Dynamic queue of URLs to be processed. This is useful for recursive crawling of websites.
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* it
|
|
95
|
+
*
|
|
96
|
+
* @deprecated Use the `requestManager` option instead. A `RequestQueue` is itself a request manager, so you can
|
|
97
|
+
* pass it directly as `requestManager`.
|
|
98
|
+
*/
|
|
99
|
+
requestQueue?: RequestQueue;
|
|
100
|
+
/**
|
|
101
|
+
* Manager of requests that should be processed by the crawler. Mutually exclusive with the deprecated
|
|
102
|
+
* `requestQueue` and `requestList` options.
|
|
103
|
+
*
|
|
104
|
+
* If not provided, the crawler will open the default {@link RequestQueue} when it is first needed.
|
|
81
105
|
*/
|
|
82
|
-
|
|
106
|
+
requestManager?: IRequestManager;
|
|
83
107
|
/**
|
|
84
108
|
* Timeout in which the function passed as {@link BasicCrawlerOptions.requestHandler|`requestHandler`} needs to finish, in seconds.
|
|
85
109
|
* @default 60
|
|
@@ -106,11 +130,8 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
106
130
|
failedRequestHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
|
|
107
131
|
/**
|
|
108
132
|
* Specifies the maximum number of retries allowed for a request if its processing fails.
|
|
109
|
-
* This includes retries due to navigation errors or errors thrown from user-supplied
|
|
110
|
-
* (`requestHandler`, `preNavigationHooks`, `postNavigationHooks`).
|
|
111
|
-
*
|
|
112
|
-
* This limit does not apply to retries triggered by session rotation
|
|
113
|
-
* (see {@link BasicCrawlerOptions.maxSessionRotations|`maxSessionRotations`}).
|
|
133
|
+
* This includes retries due to navigation errors, session/proxy errors, or errors thrown from user-supplied
|
|
134
|
+
* functions (`requestHandler`, `preNavigationHooks`, `postNavigationHooks`).
|
|
114
135
|
* @default 3
|
|
115
136
|
*/
|
|
116
137
|
maxRequestRetries?: number;
|
|
@@ -119,14 +140,6 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
119
140
|
* @default 0
|
|
120
141
|
*/
|
|
121
142
|
sameDomainDelaySecs?: number;
|
|
122
|
-
/**
|
|
123
|
-
* Maximum number of session rotations per request.
|
|
124
|
-
* The crawler will automatically rotate the session in case of a proxy error or if it gets blocked by the website.
|
|
125
|
-
*
|
|
126
|
-
* The session rotations are not counted towards the {@link BasicCrawlerOptions.maxRequestRetries|`maxRequestRetries`} limit.
|
|
127
|
-
* @default 10
|
|
128
|
-
*/
|
|
129
|
-
maxSessionRotations?: number;
|
|
130
143
|
/**
|
|
131
144
|
* Maximum number of pages that the crawler will open. The crawl will stop when this limit is reached.
|
|
132
145
|
* This value should always be set in order to prevent infinite loops in misconfigured crawlers.
|
|
@@ -134,29 +147,56 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
134
147
|
*/
|
|
135
148
|
maxRequestsPerCrawl?: number;
|
|
136
149
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* and
|
|
140
|
-
* are provided by the crawler and cannot be overridden.
|
|
141
|
-
* However, we can provide a custom implementation of {@link AutoscaledPoolOptions.isFinishedFunction|`isFinishedFunction`}.
|
|
150
|
+
* Maximum depth of the crawl. If not set, the crawl will continue until all requests are processed.
|
|
151
|
+
* Setting this to `0` will only process the initial requests, skipping all links enqueued by `crawlingContext.enqueueLinks` and `crawlingContext.addRequests`.
|
|
152
|
+
* Passing `1` will process the initial requests and all links enqueued by `crawlingContext.enqueueLinks` and `crawlingContext.addRequests` in the handler for initial requests.
|
|
142
153
|
*/
|
|
143
|
-
|
|
154
|
+
maxCrawlDepth?: number;
|
|
155
|
+
/**
|
|
156
|
+
* Lets you override the predicates that steer the crawler's task loop: `isTaskReadyFunction` (may another request
|
|
157
|
+
* start?) and `isFinishedFunction` (is the crawl over?). The task itself — fetching a request and running it
|
|
158
|
+
* through the pipeline — is owned by the crawler and cannot be overridden.
|
|
159
|
+
*
|
|
160
|
+
* Concurrency is configured elsewhere — through the `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute`
|
|
161
|
+
* shortcuts, or a {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} for finer control.
|
|
162
|
+
*/
|
|
163
|
+
taskLoopOptions?: TaskLoopPredicates;
|
|
164
|
+
/**
|
|
165
|
+
* A pre-configured concurrency governor — the component that decides whether there is free compute for one more
|
|
166
|
+
* task. Typically a {@link ConcurrencySystem}, though any {@link IConcurrencySystem} is accepted. All
|
|
167
|
+
* scaling configuration (min/max/desired concurrency, scaling ratios, `maxTasksPerMinute`, snapshotter tuning)
|
|
168
|
+
* lives on the instance itself.
|
|
169
|
+
*
|
|
170
|
+
* Inject the *same* instance into several concurrent crawlers to cap their **combined** concurrency against a
|
|
171
|
+
* single budget. Each crawler still builds and drives its own {@link AutoscaledPool}; only the load/scaling
|
|
172
|
+
* accounting is shared.
|
|
173
|
+
*
|
|
174
|
+
* Mutually exclusive with the `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute` shortcuts, which configure
|
|
175
|
+
* the default system this one replaces — combining the two throws.
|
|
176
|
+
*
|
|
177
|
+
* You own a supplied system's lifecycle: `start()` it before `run()` (which throws otherwise) and `stop()` it once
|
|
178
|
+
* every crawler borrowing it has finished. The crawler does neither on your behalf.
|
|
179
|
+
*/
|
|
180
|
+
concurrencySystem?: IConcurrencySystem;
|
|
144
181
|
/**
|
|
145
182
|
* Sets the minimum concurrency (parallelism) for the crawl. Shortcut for the
|
|
146
|
-
*
|
|
183
|
+
* {@link ConcurrencySystemOptions.minConcurrency|`minConcurrency`} option of the crawler's default
|
|
184
|
+
* {@link ConcurrencySystem}.
|
|
147
185
|
* > *WARNING:* If we set this value too high with respect to the available system memory and CPU, our crawler will run extremely slow or crash.
|
|
148
186
|
* If not sure, it's better to keep the default value and the concurrency will scale up automatically.
|
|
149
187
|
*/
|
|
150
188
|
minConcurrency?: number;
|
|
151
189
|
/**
|
|
152
190
|
* Sets the maximum concurrency (parallelism) for the crawl. Shortcut for the
|
|
153
|
-
*
|
|
191
|
+
* {@link ConcurrencySystemOptions.maxConcurrency|`maxConcurrency`} option of the crawler's default
|
|
192
|
+
* {@link ConcurrencySystem}.
|
|
154
193
|
*/
|
|
155
194
|
maxConcurrency?: number;
|
|
156
195
|
/**
|
|
157
196
|
* The maximum number of requests per minute the crawler should run.
|
|
158
197
|
* By default, this is set to `Infinity`, but we can pass any positive, non-zero integer.
|
|
159
|
-
* Shortcut for the
|
|
198
|
+
* Shortcut for the {@link ConcurrencySystemOptions.maxTasksPerMinute|`maxTasksPerMinute`} option of the
|
|
199
|
+
* crawler's default {@link ConcurrencySystem}.
|
|
160
200
|
*/
|
|
161
201
|
maxRequestsPerMinute?: number;
|
|
162
202
|
/**
|
|
@@ -166,14 +206,14 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
166
206
|
*/
|
|
167
207
|
keepAlive?: boolean;
|
|
168
208
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
*
|
|
209
|
+
* An existing session pool instance to use. When provided, the crawler will use this pool directly instead of
|
|
210
|
+
* creating a new one, enabling session sharing across multiple crawlers. The crawler will not tear down a shared
|
|
211
|
+
* pool — the caller is responsible for its lifecycle.
|
|
212
|
+
*
|
|
213
|
+
* Accepts the built-in {@link SessionPool} or any object implementing the {@link ISessionPool} interface,
|
|
214
|
+
* so custom session-management strategies can be plugged in.
|
|
175
215
|
*/
|
|
176
|
-
|
|
216
|
+
sessionPool?: ISessionPool;
|
|
177
217
|
/**
|
|
178
218
|
* Defines the length of the interval for calling the `setStatusMessage` in seconds.
|
|
179
219
|
*/
|
|
@@ -195,6 +235,11 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
195
235
|
* ```
|
|
196
236
|
*/
|
|
197
237
|
statusMessageCallback?: StatusMessageCallback;
|
|
238
|
+
/**
|
|
239
|
+
* HTTP status codes that indicate the session should be retired.
|
|
240
|
+
* @default [401, 403, 429]
|
|
241
|
+
*/
|
|
242
|
+
blockedStatusCodes?: number[];
|
|
198
243
|
/**
|
|
199
244
|
* If set to `true`, the crawler will automatically try to bypass any detected bot protection.
|
|
200
245
|
*
|
|
@@ -206,45 +251,94 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
206
251
|
/**
|
|
207
252
|
* If set to `true`, the crawler will automatically try to fetch the robots.txt file for each domain,
|
|
208
253
|
* and skip those that are not allowed. This also prevents disallowed URLs to be added via `enqueueLinks`.
|
|
254
|
+
*
|
|
255
|
+
* If an object is provided, it may contain a `userAgent` property to specify which user-agent
|
|
256
|
+
* should be used when checking the robots.txt file. If not provided, the default user-agent `*` will be used.
|
|
209
257
|
*/
|
|
210
|
-
respectRobotsTxtFile?: boolean
|
|
258
|
+
respectRobotsTxtFile?: boolean | {
|
|
259
|
+
userAgent?: string;
|
|
260
|
+
};
|
|
211
261
|
/**
|
|
212
262
|
* When a request is skipped for some reason, you can use this callback to act on it.
|
|
213
|
-
* This is currently fired
|
|
263
|
+
* This is currently fired for requests skipped
|
|
264
|
+
* 1. based on robots.txt file,
|
|
265
|
+
* 2. because they don't match enqueueLinks filters,
|
|
266
|
+
* 3. because they are redirected to a URL that doesn't match the enqueueLinks strategy,
|
|
267
|
+
* 4. or because the {@link BasicCrawlerOptions.maxRequestsPerCrawl|`maxRequestsPerCrawl`} limit has been reached
|
|
214
268
|
*/
|
|
215
269
|
onSkippedRequest?: SkippedRequestCallback;
|
|
216
|
-
/** @internal */
|
|
217
|
-
log?: Log;
|
|
218
|
-
/**
|
|
219
|
-
* Enables experimental features of Crawlee, which can alter the behavior of the crawler.
|
|
220
|
-
* WARNING: these options are not guaranteed to be stable and may change or be removed at any time.
|
|
221
|
-
*/
|
|
222
|
-
experiments?: CrawlerExperiments;
|
|
223
270
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
271
|
+
* A preconfigured statistics instance. When provided, the crawler records into it instead of building its own and
|
|
272
|
+
* will not `reset()` it between `run()` calls. Accepts the built-in {@link Statistics} (subclass it to track
|
|
273
|
+
* extra fields) or any object implementing {@link IStatistics}.
|
|
226
274
|
*/
|
|
227
|
-
|
|
275
|
+
statistics?: IStatistics;
|
|
228
276
|
/**
|
|
229
277
|
* HTTP client implementation for the `sendRequest` context helper and for plain HTTP crawling.
|
|
230
|
-
* Defaults to
|
|
278
|
+
* Defaults to {@link ImpitHttpClient} when `@crawlee/impit-client` is installed, otherwise {@link FetchHttpClient}.
|
|
231
279
|
*/
|
|
232
280
|
httpClient?: BaseHttpClient;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* A set of options that you can toggle to enable experimental features in Crawlee.
|
|
236
|
-
*
|
|
237
|
-
* NOTE: These options will not respect semantic versioning and may be removed or changed at any time. Use at your own risk.
|
|
238
|
-
* If you do use these and encounter issues, please report them to us.
|
|
239
|
-
*/
|
|
240
|
-
export interface CrawlerExperiments {
|
|
241
281
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
|
|
245
|
-
|
|
282
|
+
* If set, the crawler will be configured for all connections to use
|
|
283
|
+
* the Proxy URLs provided and rotated according to the configuration.
|
|
284
|
+
*/
|
|
285
|
+
proxyConfiguration?: IProxyConfiguration;
|
|
286
|
+
/**
|
|
287
|
+
* Custom configuration to use for this crawler.
|
|
288
|
+
* If provided, the crawler will use its own ServiceLocator instance instead of the global one.
|
|
289
|
+
*/
|
|
290
|
+
configuration?: Configuration;
|
|
291
|
+
/**
|
|
292
|
+
* Custom storage backend to use for this crawler.
|
|
293
|
+
* If provided, the crawler will use its own ServiceLocator instance instead of the global one.
|
|
294
|
+
*/
|
|
295
|
+
storageBackend?: StorageBackend;
|
|
296
|
+
/**
|
|
297
|
+
* Custom event manager to use for this crawler.
|
|
298
|
+
* If provided, the crawler will use its own ServiceLocator instance instead of the global one.
|
|
299
|
+
*/
|
|
300
|
+
eventManager?: EventManager;
|
|
301
|
+
/**
|
|
302
|
+
* Custom logger to use for this crawler.
|
|
303
|
+
* If provided, the crawler will use its own ServiceLocator instance instead of the global one.
|
|
246
304
|
*/
|
|
247
|
-
|
|
305
|
+
logger?: CrawleeLogger;
|
|
306
|
+
/**
|
|
307
|
+
* A unique identifier for the crawler instance. This ID is used to isolate the state returned by
|
|
308
|
+
* {@link BasicCrawler.useState|`crawler.useState()`} from other crawler instances.
|
|
309
|
+
*
|
|
310
|
+
* When multiple crawler instances use `useState()` without an explicit `id`, they will share the same
|
|
311
|
+
* state object for backward compatibility. A warning will be logged in this case.
|
|
312
|
+
*
|
|
313
|
+
* To ensure each crawler has its own isolated state that also persists across script restarts
|
|
314
|
+
* (e.g., during Apify migrations), provide a stable, unique ID for each crawler instance.
|
|
315
|
+
*
|
|
316
|
+
*/
|
|
317
|
+
id?: string;
|
|
318
|
+
/**
|
|
319
|
+
* Makes the storage writes performed while handling a request atomic with respect to the request
|
|
320
|
+
* succeeding: they are recorded in a {@link StorageTransaction} spanning the whole request
|
|
321
|
+
* lifecycle and only applied when the request handler succeeds, so a thrown handler leaves no partial
|
|
322
|
+
* writes behind and a retry does not double-write. Reads within the handler see its own writes.
|
|
323
|
+
*
|
|
324
|
+
* `false` disables the mechanism entirely; an object overrides the per-storage-type
|
|
325
|
+
* {@link StorageWritePolicy} (e.g. `{ requestQueue: 'deferred' }` for all-or-nothing enqueues).
|
|
326
|
+
* {@link withDirectStorageAccess} is the per-call-site escape hatch; `useState()` is deliberately
|
|
327
|
+
* *not* transactional.
|
|
328
|
+
*
|
|
329
|
+
* @default true
|
|
330
|
+
*/
|
|
331
|
+
transactionalStorage?: boolean | Partial<StorageWritePolicy>;
|
|
332
|
+
/**
|
|
333
|
+
* An array of HTTP response [Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) to be excluded from error consideration.
|
|
334
|
+
* By default, status codes >= 500 trigger errors.
|
|
335
|
+
*/
|
|
336
|
+
ignoreHttpErrorStatusCodes?: number[];
|
|
337
|
+
/**
|
|
338
|
+
* An array of additional HTTP response [Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) to be treated as errors.
|
|
339
|
+
* By default, status codes >= 500 trigger errors.
|
|
340
|
+
*/
|
|
341
|
+
additionalHttpErrorStatusCodes?: number[];
|
|
248
342
|
}
|
|
249
343
|
/**
|
|
250
344
|
* Provides a simple framework for parallel crawling of web pages.
|
|
@@ -258,25 +352,31 @@ export interface CrawlerExperiments {
|
|
|
258
352
|
*
|
|
259
353
|
* `BasicCrawler` invokes the user-provided {@link BasicCrawlerOptions.requestHandler|`requestHandler`}
|
|
260
354
|
* for each {@link Request} object, which represents a single URL to crawl.
|
|
261
|
-
* The {@link Request} objects are fed from the {@link
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
355
|
+
* The {@link Request} objects are fed from the {@link IRequestManager|request manager} provided via the
|
|
356
|
+
* {@link BasicCrawlerOptions.requestManager|`requestManager`} constructor option (a {@link RequestQueue} is
|
|
357
|
+
* itself a request manager). If no `requestManager` is provided, the crawler opens the default {@link RequestQueue}
|
|
358
|
+
* either when the {@link BasicCrawler.addRequests|`crawler.addRequests()`} function is called, or if the `requests`
|
|
359
|
+
* parameter (representing the initial requests) of the {@link BasicCrawler.run|`crawler.run()`} function is provided.
|
|
266
360
|
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
361
|
+
* To read requests from a read-only source such as a {@link RequestList} or {@link SitemapRequestLoader} while
|
|
362
|
+
* still being able to enqueue new ones, combine the loader with a queue into a {@link RequestManagerTandem} using
|
|
363
|
+
* {@link IRequestLoader.toTandem|`requestLoader.toTandem()`} and pass the result as `requestManager`. The tandem
|
|
364
|
+
* first processes URLs from the loader and automatically enqueues them into the queue, ensuring a single URL is not
|
|
365
|
+
* crawled multiple times.
|
|
366
|
+
*
|
|
367
|
+
* > The legacy {@link BasicCrawlerOptions.requestList|`requestList`} and
|
|
368
|
+
* > {@link BasicCrawlerOptions.requestQueue|`requestQueue`} options are deprecated. They are still accepted and
|
|
369
|
+
* > folded into a single `requestManager` (combined into a tandem when both are given), but new code should use
|
|
370
|
+
* > `requestManager` directly.
|
|
270
371
|
*
|
|
271
372
|
* The crawler finishes if there are no more {@link Request} objects to crawl.
|
|
272
373
|
*
|
|
273
|
-
* New requests are only dispatched when there is enough free CPU and memory available,
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
* {@link
|
|
279
|
-
* underlying {@link AutoscaledPool} constructor are available directly in the `BasicCrawler` constructor.
|
|
374
|
+
* New requests are only dispatched when there is enough free CPU and memory available, as judged by the crawler's
|
|
375
|
+
* {@link ConcurrencySystem}.
|
|
376
|
+
* Concurrency is tuned via the {@link BasicCrawlerOptions.minConcurrency|`minConcurrency`},
|
|
377
|
+
* {@link BasicCrawlerOptions.maxConcurrency|`maxConcurrency`} and
|
|
378
|
+
* {@link BasicCrawlerOptions.maxRequestsPerMinute|`maxRequestsPerMinute`} shortcuts, or, for finer control, by
|
|
379
|
+
* injecting a pre-configured {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`}.
|
|
280
380
|
*
|
|
281
381
|
* **Example usage:**
|
|
282
382
|
*
|
|
@@ -310,135 +410,214 @@ export interface CrawlerExperiments {
|
|
|
310
410
|
* ```
|
|
311
411
|
* @category Crawlers
|
|
312
412
|
*/
|
|
313
|
-
|
|
314
|
-
|
|
413
|
+
/**
|
|
414
|
+
* Identifies a crawler instance for storage aliasing, `useState()` and status-message events.
|
|
415
|
+
*/
|
|
416
|
+
interface CrawlerIdentity {
|
|
417
|
+
/**
|
|
418
|
+
* 0-based instantiation order across all crawlers in the process.
|
|
419
|
+
* Note that the value can be subject to race conditions between different script invocations.
|
|
420
|
+
*/
|
|
421
|
+
readonly instanceIndex: number;
|
|
422
|
+
/** The user-supplied `id` option, or a fallback derived from `instanceIndex`. */
|
|
423
|
+
readonly id: string;
|
|
424
|
+
/** Whether `id` came from the user (as opposed to being derived from `instanceIndex`). */
|
|
425
|
+
readonly hasExplicitId: boolean;
|
|
426
|
+
}
|
|
427
|
+
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']>>> {
|
|
428
|
+
#private;
|
|
315
429
|
protected static readonly CRAWLEE_STATE_KEY = "CRAWLEE_STATE";
|
|
316
430
|
/**
|
|
317
|
-
*
|
|
431
|
+
* Tracks the number of crawler instances created. The first crawler uses the default
|
|
432
|
+
* request queue; subsequent ones get their own queue via a unique alias so they don't
|
|
433
|
+
* collide.
|
|
318
434
|
*/
|
|
319
|
-
|
|
435
|
+
private static instanceCount;
|
|
320
436
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
437
|
+
* The statistics instance collecting the crawler's run statistics - either the injected `statistics` option or a
|
|
438
|
+
* crawler-built default. Typed as {@link IStatistics} so custom implementations can be plugged in.
|
|
323
439
|
*/
|
|
324
|
-
|
|
440
|
+
get stats(): IStatistics;
|
|
325
441
|
/**
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
442
|
+
* The main request-handling component of the crawler. It manages the requests that the crawler processes,
|
|
443
|
+
* combining any provided request loader and/or queue. It's initialized during the crawler startup or lazily
|
|
444
|
+
* via {@link BasicCrawler.getRequestManager|`getRequestManager()`}.
|
|
329
445
|
*/
|
|
330
|
-
|
|
446
|
+
protected requestManager?: IRequestManager;
|
|
331
447
|
/**
|
|
332
|
-
* A reference to the underlying
|
|
333
|
-
*
|
|
448
|
+
* A reference to the underlying session pool that manages the crawler's {@link Session|sessions}. Typed as
|
|
449
|
+
* {@link ISessionPool} so custom implementations can be plugged in via the `sessionPool` constructor option.
|
|
334
450
|
*/
|
|
335
|
-
sessionPool
|
|
451
|
+
get sessionPool(): ISessionPool;
|
|
336
452
|
/**
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
453
|
+
* The concurrency governor this run is booking its requests against — either the
|
|
454
|
+
* {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} that was injected, or the default the
|
|
455
|
+
* crawler built for itself. Read it for telemetry: `desiredConcurrency`, `currentConcurrency`, `isRunning`.
|
|
456
|
+
*
|
|
457
|
+
* > *NOTE:* `undefined` until {@link BasicCrawler.run|`crawler.run()`} has resolved it. A crawler-owned default
|
|
458
|
+
* is also rebuilt for every run, so the instance is not stable across runs.
|
|
459
|
+
*
|
|
460
|
+
* {@link IConcurrencySystem} is deliberately read-only. Tuning concurrency *while a crawl is running* means
|
|
461
|
+
* owning the instance: build a {@link ConcurrencySystem} yourself and inject it, then set
|
|
462
|
+
* `minConcurrency`/`maxConcurrency`/`desiredConcurrency` on your own reference.
|
|
463
|
+
*/
|
|
464
|
+
get concurrencySystem(): IConcurrencySystem | undefined;
|
|
465
|
+
/**
|
|
466
|
+
* A reference to the underlying {@link IProxyConfiguration} instance that manages the crawler's proxies.
|
|
467
|
+
* Only available if used by the crawler.
|
|
342
468
|
*/
|
|
343
|
-
|
|
469
|
+
readonly proxyConfiguration?: IProxyConfiguration;
|
|
344
470
|
/**
|
|
345
471
|
* Default {@link Router} instance that will be used if we don't specify any {@link BasicCrawlerOptions.requestHandler|`requestHandler`}.
|
|
346
472
|
* See {@link Router.addHandler|`router.addHandler()`} and {@link Router.addDefaultHandler|`router.addDefaultHandler()`}.
|
|
347
473
|
*/
|
|
348
|
-
readonly router: RouterHandler<Context>;
|
|
349
|
-
|
|
350
|
-
|
|
474
|
+
readonly router: RouterHandler<Context, Routes>;
|
|
475
|
+
/**
|
|
476
|
+
* The basic part of the context pipeline. Unlike the subclass pipeline, this
|
|
477
|
+
* part has no major side effects (e.g. launching a browser). It also makes typing more explicit, as subclass
|
|
478
|
+
* pipelines expect the basic crawler fields to already be present in the context at runtime.
|
|
479
|
+
*
|
|
480
|
+
* Context built with this pipeline can be passed into multiple crawler pipelines at once.
|
|
481
|
+
* This is used e.g. in the {@link AdaptivePlaywrightCrawler|`AdaptivePlaywrightCrawler`}.
|
|
482
|
+
*/
|
|
483
|
+
get basicContextPipeline(): ContextPipeline<{
|
|
484
|
+
request: Request;
|
|
485
|
+
}, CrawlingContext>;
|
|
351
486
|
get contextPipeline(): ContextPipeline<CrawlingContext, ExtendedContext>;
|
|
352
487
|
running: boolean;
|
|
353
488
|
hasFinishedBefore: boolean;
|
|
354
|
-
|
|
355
|
-
protected requestHandler: RequestHandler<ExtendedContext>;
|
|
356
|
-
protected errorHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
|
|
357
|
-
protected failedRequestHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
|
|
358
|
-
|
|
359
|
-
protected internalTimeoutMillis: number;
|
|
360
|
-
protected maxRequestRetries: number;
|
|
361
|
-
protected
|
|
362
|
-
protected
|
|
363
|
-
|
|
364
|
-
protected
|
|
365
|
-
protected
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
protected
|
|
374
|
-
protected
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
private readonly robotsTxtFileCache;
|
|
378
|
-
private _experimentWarnings;
|
|
489
|
+
get log(): CrawleeLogger;
|
|
490
|
+
protected readonly requestHandler: RequestHandler<ExtendedContext>;
|
|
491
|
+
protected readonly errorHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
|
|
492
|
+
protected readonly failedRequestHandler?: ErrorHandler<CrawlingContext, ExtendedContext>;
|
|
493
|
+
private requestHandlerTimeoutMillis;
|
|
494
|
+
protected readonly internalTimeoutMillis: number;
|
|
495
|
+
protected readonly maxRequestRetries: number;
|
|
496
|
+
protected readonly maxCrawlDepth?: number;
|
|
497
|
+
protected readonly maxRequestsPerCrawl?: number;
|
|
498
|
+
private get handledRequestsCount();
|
|
499
|
+
protected blockedStatusCodes: Set<number>;
|
|
500
|
+
protected readonly additionalHttpErrorStatusCodes: Set<number>;
|
|
501
|
+
/**
|
|
502
|
+
* The resolved options for the crawler's own task loop — the crawler-owned `runTaskFunction`, the (possibly
|
|
503
|
+
* user-overridden) ready/finished predicates and cadence/logging. Concurrency configuration lives on the
|
|
504
|
+
* {@link ConcurrencySystem} instead, and the loop's `consumer` identity is the crawler's own, so neither is
|
|
505
|
+
* settable here.
|
|
506
|
+
*/
|
|
507
|
+
private taskLoopOptions;
|
|
508
|
+
protected readonly httpClient: BaseHttpClient;
|
|
509
|
+
protected readonly retryOnBlocked: boolean;
|
|
510
|
+
protected readonly onSkippedRequest?: SkippedRequestCallback;
|
|
511
|
+
protected readonly identity: CrawlerIdentity;
|
|
379
512
|
protected static optionsShape: {
|
|
380
513
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
381
|
-
contextPipelineBuilder: import("ow").ObjectPredicate<object> &
|
|
514
|
+
contextPipelineBuilder: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
515
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
516
|
+
extendContext: import("ow").Predicate<Function> & BasePredicate<Function | undefined>;
|
|
382
517
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
383
|
-
|
|
518
|
+
requestList: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
384
519
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
385
|
-
|
|
520
|
+
requestQueue: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
386
521
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
387
|
-
|
|
522
|
+
requestHandler: import("ow").Predicate<Function> & BasePredicate<Function | undefined>;
|
|
388
523
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
389
|
-
|
|
524
|
+
requestHandlerTimeoutSecs: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
390
525
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
391
|
-
|
|
526
|
+
errorHandler: import("ow").Predicate<Function> & BasePredicate<Function | undefined>;
|
|
392
527
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
393
|
-
|
|
528
|
+
failedRequestHandler: import("ow").Predicate<Function> & BasePredicate<Function | undefined>;
|
|
394
529
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
395
|
-
|
|
530
|
+
maxRequestRetries: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
396
531
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
397
|
-
|
|
532
|
+
sameDomainDelaySecs: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
398
533
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
399
|
-
|
|
534
|
+
maxRequestsPerCrawl: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
400
535
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
401
|
-
|
|
536
|
+
maxCrawlDepth: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
402
537
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
403
|
-
|
|
538
|
+
taskLoopOptions: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
404
539
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
405
|
-
|
|
540
|
+
concurrencySystem: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
406
541
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
407
|
-
|
|
542
|
+
sessionPool: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
408
543
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
409
|
-
|
|
544
|
+
proxyConfiguration: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
410
545
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
411
|
-
statusMessageLoggingInterval: import("ow").NumberPredicate &
|
|
546
|
+
statusMessageLoggingInterval: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
412
547
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
413
|
-
statusMessageCallback: import("ow").Predicate<Function> &
|
|
548
|
+
statusMessageCallback: import("ow").Predicate<Function> & BasePredicate<Function | undefined>;
|
|
414
549
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
415
|
-
|
|
550
|
+
additionalHttpErrorStatusCodes: import("ow").ArrayPredicate<number>;
|
|
416
551
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
417
|
-
|
|
552
|
+
ignoreHttpErrorStatusCodes: import("ow").ArrayPredicate<number>;
|
|
418
553
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
419
|
-
|
|
554
|
+
blockedStatusCodes: import("ow").ArrayPredicate<number>;
|
|
420
555
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
421
|
-
|
|
556
|
+
retryOnBlocked: import("ow").BooleanPredicate & BasePredicate<boolean | undefined>;
|
|
422
557
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
423
|
-
|
|
558
|
+
respectRobotsTxtFile: import("ow").AnyPredicate<boolean | object>;
|
|
559
|
+
transactionalStorage: BasePredicate<boolean | Partial<StorageWritePolicy> | undefined>;
|
|
424
560
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
425
|
-
|
|
561
|
+
onSkippedRequest: import("ow").Predicate<Function> & BasePredicate<Function | undefined>;
|
|
426
562
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
427
|
-
|
|
563
|
+
httpClient: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
428
564
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
429
|
-
|
|
565
|
+
configuration: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
430
566
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
431
|
-
|
|
567
|
+
storageBackend: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
432
568
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
433
|
-
|
|
569
|
+
eventManager: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
434
570
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
435
|
-
|
|
571
|
+
logger: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
572
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
573
|
+
minConcurrency: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
574
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
575
|
+
maxConcurrency: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
576
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
577
|
+
maxRequestsPerMinute: import("ow").NumberPredicate & BasePredicate<number | undefined>;
|
|
578
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
579
|
+
keepAlive: import("ow").BooleanPredicate & BasePredicate<boolean | undefined>;
|
|
580
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
581
|
+
statistics: import("ow").ObjectPredicate<object> & BasePredicate<object | undefined>;
|
|
582
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
583
|
+
id: import("ow").StringPredicate & BasePredicate<string | undefined>;
|
|
436
584
|
};
|
|
437
585
|
/**
|
|
438
586
|
* All `BasicCrawler` parameters are passed via an options object.
|
|
439
587
|
*/
|
|
440
|
-
constructor(options?: BasicCrawlerOptions<Context, ContextExtension, ExtendedContext> & RequireContextPipeline<CrawlingContext, Context
|
|
441
|
-
|
|
588
|
+
constructor(options?: BasicCrawlerOptions<Context, ContextExtension, ExtendedContext, Routes> & RequireContextPipeline<CrawlingContext, Context>);
|
|
589
|
+
/**
|
|
590
|
+
* Builds the crawler-owned default {@link ConcurrencySystem} from the resolved
|
|
591
|
+
* `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute` shortcuts. Not called when a
|
|
592
|
+
* {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} was injected.
|
|
593
|
+
*
|
|
594
|
+
* Subclasses may override this to tune the default system (e.g. {@link HttpCrawler} raises the starting
|
|
595
|
+
* concurrency and relaxes the event loop signal) while still honouring the user's shortcuts.
|
|
596
|
+
*/
|
|
597
|
+
protected createDefaultConcurrencySystem(options: ConcurrencySystemOptions): ConcurrencySystem;
|
|
598
|
+
/**
|
|
599
|
+
* Determines if the given HTTP status code is an error status code given
|
|
600
|
+
* the default behaviour and user-set preferences.
|
|
601
|
+
* @param status
|
|
602
|
+
* @returns `true` if the status code is considered an error, `false` otherwise
|
|
603
|
+
*/
|
|
604
|
+
protected isErrorStatusCode(status: number): boolean;
|
|
605
|
+
/**
|
|
606
|
+
* Builds the basic context pipeline that transforms `{ request }` into a full `CrawlingContext`.
|
|
607
|
+
* This handles base context creation, session resolution, and context helpers.
|
|
608
|
+
*/
|
|
609
|
+
private buildBasicContextPipeline;
|
|
610
|
+
private checkRobotsTxt;
|
|
611
|
+
/**
|
|
612
|
+
* Builds the subclass-specific context pipeline that transforms a `CrawlingContext` into the crawler's target context type.
|
|
613
|
+
* Subclasses should override this to add their own pipeline stages.
|
|
614
|
+
*/
|
|
615
|
+
protected buildContextPipeline(): ContextPipeline<CrawlingContext, CrawlingContext>;
|
|
616
|
+
private createBaseContext;
|
|
617
|
+
private resolveRequest;
|
|
618
|
+
private resolveSession;
|
|
619
|
+
private createContextHelpers;
|
|
620
|
+
private buildFinalContextPipeline;
|
|
442
621
|
/**
|
|
443
622
|
* Checks if the given error is a proxy error by comparing its message to a list of known proxy error messages.
|
|
444
623
|
* Used for retrying requests that failed due to proxy errors.
|
|
@@ -447,13 +626,20 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
447
626
|
*/
|
|
448
627
|
protected isProxyError(error: Error): boolean;
|
|
449
628
|
/**
|
|
629
|
+
* Sets the status message for the current crawler run.
|
|
630
|
+
*
|
|
450
631
|
* This method is periodically called by the crawler, every `statusMessageLoggingInterval` seconds.
|
|
632
|
+
*
|
|
633
|
+
* The message is logged and broadcast via the {@link EventType.STATUS_MESSAGE|`statusMessage`}
|
|
634
|
+
* event. Integrations such as the Apify SDK subscribe to that event and forward the message to
|
|
635
|
+
* their status-reporting backend (e.g. the Apify platform).
|
|
451
636
|
*/
|
|
452
|
-
setStatusMessage(message: string, options?: SetStatusMessageOptions):
|
|
637
|
+
setStatusMessage(message: string, options?: SetStatusMessageOptions): void;
|
|
453
638
|
private getPeriodicLogger;
|
|
454
639
|
/**
|
|
455
|
-
* Runs the crawler. Returns a promise that resolves once
|
|
456
|
-
*
|
|
640
|
+
* Runs the crawler. Returns a promise that resolves once every request has been processed and the crawler's
|
|
641
|
+
* finished-check ({@link BasicCrawlerOptions.taskLoopOptions|`taskLoopOptions.isFinishedFunction`}, or the
|
|
642
|
+
* default "the request manager is empty") reports that the crawl is over.
|
|
457
643
|
*
|
|
458
644
|
* We can use the `requests` parameter to enqueue the initial requests — it is a shortcut for
|
|
459
645
|
* running {@link BasicCrawler.addRequests|`crawler.addRequests()`} before {@link BasicCrawler.run|`crawler.run()`}.
|
|
@@ -461,15 +647,66 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
461
647
|
* @param [requests] The requests to add.
|
|
462
648
|
* @param [options] Options for the request queue.
|
|
463
649
|
*/
|
|
464
|
-
run(requests?:
|
|
650
|
+
run(requests?: TypedRequestsLike<Routes>, options?: CrawlerRunOptions): Promise<FinalStatistics>;
|
|
465
651
|
/**
|
|
466
652
|
* Gracefully stops the current run of the crawler.
|
|
467
653
|
*
|
|
468
654
|
* All the tasks active at the time of calling this method will be allowed to finish.
|
|
655
|
+
*
|
|
656
|
+
* To stop the crawler immediately, use {@link BasicCrawler.teardown|`crawler.teardown()`} instead.
|
|
657
|
+
*/
|
|
658
|
+
stop(reason?: string): void;
|
|
659
|
+
/**
|
|
660
|
+
* Stops dispatching new requests, letting the in-progress ones finish. Resolves once they have settled, or rejects
|
|
661
|
+
* after `timeoutSecs` if they take too long. Unlike {@link BasicCrawler.stop|`stop()`}, this does not end the
|
|
662
|
+
* run — {@link BasicCrawler.run|`run()`} stays pending until {@link BasicCrawler.resume|`resume()`}.
|
|
663
|
+
*
|
|
664
|
+
* > *NOTE:* The {@link BasicCrawler.concurrencySystem|concurrency system} keeps monitoring and autoscaling
|
|
665
|
+
* throughout, since a shared one may still be serving other crawlers.
|
|
666
|
+
*/
|
|
667
|
+
pause(timeoutSecs?: number): Promise<void>;
|
|
668
|
+
/**
|
|
669
|
+
* Resumes a run suspended with {@link BasicCrawler.pause|`pause()`}, letting the crawler dispatch requests
|
|
670
|
+
* again. A no-op on a crawler that is not paused.
|
|
469
671
|
*/
|
|
470
|
-
|
|
471
|
-
|
|
672
|
+
resume(): void;
|
|
673
|
+
/**
|
|
674
|
+
* Returns the crawler's {@link IRequestManager|request manager}, opening the default {@link RequestQueue}
|
|
675
|
+
* if none has been configured or opened yet.
|
|
676
|
+
*/
|
|
677
|
+
getRequestManager(): Promise<IRequestManager>;
|
|
678
|
+
/**
|
|
679
|
+
* @deprecated Use {@link BasicCrawler.getRequestManager|`getRequestManager()`} instead. This returns the
|
|
680
|
+
* crawler's request manager, which is no longer guaranteed to be a {@link RequestQueue}.
|
|
681
|
+
*/
|
|
682
|
+
getRequestQueue(): Promise<IRequestManager>;
|
|
683
|
+
/**
|
|
684
|
+
* Opens the default {@link RequestQueue}, applies the crawler's timeouts to it and records it as the
|
|
685
|
+
* crawler-owned queue (so it gets purged between repeated `run()` calls).
|
|
686
|
+
* @private
|
|
687
|
+
*/
|
|
688
|
+
private openOwnedRequestQueue;
|
|
689
|
+
/**
|
|
690
|
+
* Tells a request manager how long we expect to hold a fetched request, so that one backed by a
|
|
691
|
+
* locking storage backend keeps it reserved for slightly longer than the request handler timeout
|
|
692
|
+
* (with some padding for overhead), but never for less than a minute. This prevents a long-running
|
|
693
|
+
* request from being handed out a second time while it is still being processed — and it works
|
|
694
|
+
* regardless of whether the manager is a plain {@link RequestQueue} or a `RequestManagerTandem`.
|
|
695
|
+
*/
|
|
696
|
+
private applyRequestManagerTimeouts;
|
|
697
|
+
/**
|
|
698
|
+
* Validates a request source's `userData` against the {@link RouteSchemas|Standard Schema} registered
|
|
699
|
+
* for its label on the crawler's schema-router (if any), throwing a {@link RequestValidationError} on
|
|
700
|
+
* mismatch. A no-op when the user's request handler is not a schema-router, or no schema is registered for
|
|
701
|
+
* the request's label. Applied by the crawler on the add paths it owns — `crawler.addRequests`,
|
|
702
|
+
* `crawler.run`, `context.addRequests` and `context.enqueueLinks`.
|
|
703
|
+
*/
|
|
704
|
+
private validateRequestUserData;
|
|
472
705
|
useState<State extends Dictionary = Dictionary>(defaultValue?: State): Promise<State>;
|
|
706
|
+
protected getPendingRequestCountApproximation(): Promise<number>;
|
|
707
|
+
protected calculateEnqueuedRequestLimit(explicitLimit?: number): Promise<number | undefined>;
|
|
708
|
+
protected handleSkippedRequest(options: Parameters<SkippedRequestCallback>[0]): Promise<void>;
|
|
709
|
+
private logOncePerRun;
|
|
473
710
|
/**
|
|
474
711
|
* Adds requests to the queue in batches. By default, it will resolve after the initial batch is added, and continue
|
|
475
712
|
* adding the rest in background. You can configure the batch size via `batchSize` option and the sleep time in between
|
|
@@ -481,15 +718,15 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
481
718
|
* @param requests The requests to add
|
|
482
719
|
* @param options Options for the request queue
|
|
483
720
|
*/
|
|
484
|
-
addRequests(requests: ReadonlyDeep<
|
|
721
|
+
addRequests(requests: ReadonlyDeep<TypedRequestsLike<Routes>>, options?: CrawlerAddRequestsOptions): Promise<CrawlerAddRequestsResult>;
|
|
485
722
|
/**
|
|
486
723
|
* Pushes data to the specified {@link Dataset}, or the default crawler {@link Dataset} by calling {@link Dataset.pushData}.
|
|
487
724
|
*/
|
|
488
|
-
pushData(data: Parameters<Dataset['pushData']>[0],
|
|
725
|
+
pushData(data: Parameters<Dataset['pushData']>[0], datasetIdentifier?: string | StorageIdentifier): Promise<void>;
|
|
489
726
|
/**
|
|
490
727
|
* Retrieves the specified {@link Dataset}, or the default crawler {@link Dataset}.
|
|
491
728
|
*/
|
|
492
|
-
getDataset(
|
|
729
|
+
getDataset(identifier?: string | StorageIdentifier): Promise<Dataset>;
|
|
493
730
|
/**
|
|
494
731
|
* Retrieves data from the default crawler {@link Dataset} by calling {@link Dataset.getData}.
|
|
495
732
|
*/
|
|
@@ -499,45 +736,88 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
499
736
|
* Supported formats are currently 'json' and 'csv', and will be inferred from the `path` automatically.
|
|
500
737
|
*/
|
|
501
738
|
exportData<Data>(path: string, format?: 'json' | 'csv', options?: DatasetExportOptions): Promise<Data[]>;
|
|
502
|
-
|
|
503
|
-
|
|
739
|
+
/**
|
|
740
|
+
* Initializes the crawler.
|
|
741
|
+
*/
|
|
742
|
+
protected init(): Promise<void>;
|
|
743
|
+
/**
|
|
744
|
+
* The navigation timeout (pre-navigation hooks, navigation, and post-navigation hooks) in milliseconds, used
|
|
745
|
+
* to size the internal request timeout. `BasicCrawler` has no navigation phase, so this is 0; the HTTP and
|
|
746
|
+
* browser crawlers override it with their `navigationTimeoutSecs`.
|
|
747
|
+
*/
|
|
748
|
+
protected getNavigationTimeoutMillis(): number;
|
|
749
|
+
/**
|
|
750
|
+
* Races the request against the internal timeout (see {@link raceWithTimeout}), sized to outlast the phases
|
|
751
|
+
* that have their own timeout - the navigation, its hooks, and the request handler - so a legitimately slow
|
|
752
|
+
* request, a per-route override, or a low `CRAWLEE_INTERNAL_TIMEOUT` is not cut short mid-phase. It takes
|
|
753
|
+
* whichever is larger: the configured internal timeout, or this request's combined phase budget.
|
|
754
|
+
*/
|
|
755
|
+
private withRequestTimeout;
|
|
756
|
+
/**
|
|
757
|
+
* The request handler timeout for a request with the given route label. A router route may override the
|
|
758
|
+
* crawler's own `requestHandlerTimeoutSecs`; anything else falls back to `fallbackMillis`.
|
|
759
|
+
*
|
|
760
|
+
* @param label The request's route label, or `undefined` for the default route / no specific request.
|
|
761
|
+
* @param fallbackMillis Timeout to use when no route overrides it.
|
|
762
|
+
*/
|
|
763
|
+
private resolveRequestHandlerTimeoutMillis;
|
|
764
|
+
/**
|
|
765
|
+
* The timeout the router route with the given label asked for, or `undefined` when it did not override one
|
|
766
|
+
* (or the request handler is not a router at all).
|
|
767
|
+
*/
|
|
768
|
+
private getRouteTimeoutMillis;
|
|
769
|
+
protected runRequestHandler(crawlingContext: ExtendedContext): Promise<void>;
|
|
770
|
+
/**
|
|
771
|
+
* Runs `callback` inside a {@link StorageTransaction}, unless transactional storage is disabled.
|
|
772
|
+
* Deliberately does **not** commit on return - `handleRequest` swallows request handler failures, so
|
|
773
|
+
* a normal return says nothing about success. `handleRequest` owns the outcome.
|
|
774
|
+
*/
|
|
775
|
+
private runInStorageTransaction;
|
|
504
776
|
/**
|
|
505
777
|
* Handles blocked request
|
|
506
778
|
*/
|
|
507
|
-
protected
|
|
779
|
+
protected throwOnBlockedRequest(statusCode: number): void;
|
|
508
780
|
private isAllowedBasedOnRobotsTxtFile;
|
|
509
781
|
protected getRobotsTxtFileForUrl(url: string): Promise<RobotsTxtFile | undefined>;
|
|
510
|
-
|
|
782
|
+
private pauseOnMigration;
|
|
511
783
|
/**
|
|
512
|
-
* Fetches request
|
|
513
|
-
* and RequestQueue is present then enqueues it to the queue first.
|
|
784
|
+
* Fetches the next request to process from the underlying request provider.
|
|
514
785
|
*/
|
|
515
|
-
|
|
786
|
+
private fetchNextRequest;
|
|
516
787
|
/**
|
|
517
788
|
* Delays processing of the request based on the `sameDomainDelaySecs` option,
|
|
518
789
|
* adding it back to the queue after the timeout passes. Returns `true` if the request
|
|
519
790
|
* should be ignored and will be reclaimed to the queue once ready.
|
|
520
791
|
*/
|
|
521
|
-
|
|
792
|
+
private delayRequest;
|
|
793
|
+
/** Handles a single request - runs the request handler with retries, error handling, and lifecycle management. */
|
|
794
|
+
private handleRequest;
|
|
795
|
+
/**
|
|
796
|
+
* Wrapper around the crawling context's `enqueueLinks` method:
|
|
797
|
+
* - Injects `crawlDepth` to each request being added based on the crawling context request.
|
|
798
|
+
* - Provides defaults for the `enqueueLinks` options based on the crawler configuration.
|
|
799
|
+
* - These options can be overridden by the user.
|
|
800
|
+
* @internal
|
|
801
|
+
*/
|
|
802
|
+
protected enqueueLinksWithCrawlDepth(options: SetRequired<EnqueueLinksOptions, 'urls'>, request: Request<Dictionary>, requestManager: IRequestManager): Promise<BatchAddRequestsResult>;
|
|
522
803
|
/**
|
|
523
|
-
*
|
|
524
|
-
*
|
|
804
|
+
* Generator function that yields requests injected with the given crawl depth.
|
|
805
|
+
* @internal
|
|
525
806
|
*/
|
|
526
|
-
protected
|
|
807
|
+
protected addCrawlDepthRequestGenerator(requests: RequestsLike, newRequestDepth: number): AsyncGenerator<Source, void, undefined>;
|
|
527
808
|
/**
|
|
528
|
-
* Run async callback with given timeout and retry.
|
|
809
|
+
* Run async callback with given timeout and retry. Returns the result of the callback.
|
|
529
810
|
* @ignore
|
|
530
811
|
*/
|
|
531
|
-
|
|
812
|
+
private timeoutAndRetry;
|
|
532
813
|
/**
|
|
533
814
|
* Returns true if either RequestList or RequestQueue have a request ready for processing.
|
|
534
815
|
*/
|
|
535
|
-
|
|
816
|
+
private isTaskReadyFunction;
|
|
536
817
|
/**
|
|
537
818
|
* Returns true if both RequestList and RequestQueue have all requests finished.
|
|
538
819
|
*/
|
|
539
|
-
|
|
540
|
-
private _rotateSession;
|
|
820
|
+
private defaultIsFinishedFunction;
|
|
541
821
|
/**
|
|
542
822
|
* Unwraps errors thrown by the context pipeline to get the actual user error.
|
|
543
823
|
* RequestHandlerError and ContextPipelineInitializationError wrap the actual error.
|
|
@@ -545,39 +825,32 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
545
825
|
private unwrapError;
|
|
546
826
|
/**
|
|
547
827
|
* Handles errors thrown by user provided requestHandler()
|
|
828
|
+
*
|
|
829
|
+
* @param request The request object, passed separately to circumvent potential dynamic logic in crawlingContext.request
|
|
548
830
|
*/
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
protected _handleFailedRequestHandler(crawlingContext: CrawlingContext, error: Error): Promise<void>;
|
|
831
|
+
private requestFunctionErrorHandler;
|
|
832
|
+
private handleFailedRequestHandler;
|
|
552
833
|
/**
|
|
553
834
|
* Resolves the most verbose error message from a thrown error
|
|
554
835
|
* @param error The error received
|
|
555
836
|
* @returns The message to be logged
|
|
556
837
|
*/
|
|
557
|
-
protected
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* Updates handledRequestsCount from possibly stored counts,
|
|
561
|
-
* usually after worker migration. Since one of the stores
|
|
562
|
-
* needs to have priority when both are present,
|
|
563
|
-
* it is the request queue, because generally, the request
|
|
564
|
-
* list will first be dumped into the queue and then left
|
|
565
|
-
* empty.
|
|
566
|
-
*/
|
|
567
|
-
protected _loadHandledRequestCount(): Promise<void>;
|
|
568
|
-
protected _executeHooks<HookLike extends (...args: any[]) => Awaitable<void>>(hooks: HookLike[], ...args: Parameters<HookLike>): Promise<void>;
|
|
838
|
+
protected getMessageFromError(error: Error, forceStack?: boolean): string | TimeoutError | undefined;
|
|
839
|
+
private canRequestBeRetried;
|
|
569
840
|
/**
|
|
570
|
-
*
|
|
571
|
-
*
|
|
841
|
+
* Stops the crawler immediately.
|
|
842
|
+
*
|
|
843
|
+
* This method doesn't wait for currently active requests to finish.
|
|
844
|
+
*
|
|
845
|
+
* To stop the crawler gracefully (waiting for all running requests to finish), use {@link BasicCrawler.stop|`crawler.stop()`} instead.
|
|
572
846
|
*/
|
|
573
847
|
teardown(): Promise<void>;
|
|
574
|
-
protected
|
|
575
|
-
private
|
|
576
|
-
protected requestMatchesEnqueueStrategy(request: Request): boolean;
|
|
848
|
+
protected getCookieHeaderFromRequest(request: Request): string;
|
|
849
|
+
private requestMatchesEnqueueStrategy;
|
|
577
850
|
}
|
|
578
851
|
export interface CreateContextOptions {
|
|
579
852
|
request: Request;
|
|
580
|
-
session
|
|
853
|
+
session: ISession;
|
|
581
854
|
proxyInfo?: ProxyInfo;
|
|
582
855
|
}
|
|
583
856
|
export interface CrawlerAddRequestsOptions extends AddRequestsBatchedOptions {
|
|
@@ -586,9 +859,14 @@ export interface CrawlerAddRequestsResult extends AddRequestsBatchedResult {
|
|
|
586
859
|
}
|
|
587
860
|
export interface CrawlerRunOptions extends CrawlerAddRequestsOptions {
|
|
588
861
|
/**
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
862
|
+
* Controls whether the request queue is purged between repeated `run()` calls on the same crawler instance.
|
|
863
|
+
* Purging clears all requests and resets internal counters, allowing the same URLs to be processed again.
|
|
864
|
+
*
|
|
865
|
+
* - **`undefined`** (default) — only the crawler's own (auto-created) queue is purged.
|
|
866
|
+
* A user-supplied `requestQueue` is left untouched.
|
|
867
|
+
* - **`true`** — the queue is always purged, even if it was supplied by the user.
|
|
868
|
+
* - **`false`** — nothing is purged. Only genuinely new requests will be processed;
|
|
869
|
+
* note that even a failed request is considered handled.
|
|
592
870
|
*/
|
|
593
871
|
purgeRequestQueue?: boolean;
|
|
594
872
|
}
|
|
@@ -616,5 +894,5 @@ export interface CrawlerRunOptions extends CrawlerAddRequestsOptions {
|
|
|
616
894
|
* await crawler.run();
|
|
617
895
|
* ```
|
|
618
896
|
*/
|
|
619
|
-
export declare function createBasicRouter<Context extends BasicCrawlingContext = BasicCrawlingContext,
|
|
620
|
-
|
|
897
|
+
export declare function createBasicRouter<Context extends BasicCrawlingContext = BasicCrawlingContext, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>>(routes?: RouterRoutes<Context, Routes>): RouterHandler<Context, Routes>;
|
|
898
|
+
export declare function createBasicRouter<Context extends BasicCrawlingContext = BasicCrawlingContext, UserData extends Dictionary = GetUserDataFromRequest<Context['request']>>(routes?: RouterRoutes<Context, Record<string, UserData>>): RouterHandler<Context, Record<string, UserData>>;
|