@crawlee/browser 3.0.0-beta.9 → 3.0.1-beta.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 +75 -133
- package/index.mjs +7 -0
- package/internals/browser-crawler.d.ts +111 -135
- package/internals/browser-crawler.d.ts.map +1 -1
- package/internals/browser-crawler.js +39 -28
- package/internals/browser-crawler.js.map +1 -1
- package/internals/browser-launcher.d.ts +10 -8
- package/internals/browser-launcher.d.ts.map +1 -1
- package/internals/browser-launcher.js +13 -10
- package/internals/browser-launcher.js.map +1 -1
- package/package.json +17 -14
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1,171 +1,143 @@
|
|
|
1
|
-
import { EnqueueLinksOptions,
|
|
2
|
-
import {
|
|
3
|
-
import { Awaitable, Dictionary } from '@crawlee/
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
1
|
+
import type { EnqueueLinksOptions, CrawlingContext, ProxyConfiguration, RequestQueue } from '@crawlee/core';
|
|
2
|
+
import { Configuration } from '@crawlee/core';
|
|
3
|
+
import type { BasicCrawlerOptions, Awaitable, Dictionary } from '@crawlee/basic';
|
|
4
|
+
import { BasicCrawler } from '@crawlee/basic';
|
|
5
|
+
import type { BrowserController, BrowserPlugin, BrowserPoolHooks, BrowserPoolOptions, CommonPage, InferBrowserPluginArray, LaunchContext } from '@crawlee/browser-pool';
|
|
6
|
+
import { BrowserPool } from '@crawlee/browser-pool';
|
|
7
|
+
import type { GotOptionsInit, Response as GotResponse } from 'got-scraping';
|
|
8
|
+
import type { BatchAddRequestsResult } from '@crawlee/types';
|
|
9
|
+
import type { BrowserLaunchContext } from './browser-launcher';
|
|
10
|
+
export interface BrowserCrawlingContext<Page extends CommonPage = CommonPage, Response = Dictionary, ProvidedController = BrowserController, UserData extends Dictionary = Dictionary> extends CrawlingContext<UserData> {
|
|
8
11
|
browserController: ProvidedController;
|
|
9
12
|
page: Page;
|
|
10
13
|
response?: Response;
|
|
11
14
|
crawler: BrowserCrawler;
|
|
12
15
|
enqueueLinks: (options?: BrowserCrawlerEnqueueLinksOptions) => Promise<BatchAddRequestsResult>;
|
|
16
|
+
sendRequest: (overrideOptions?: Partial<GotOptionsInit>) => Promise<GotResponse<string>>;
|
|
13
17
|
}
|
|
14
|
-
export interface BrowserCrawlerHandleFailedRequestInput extends CrawlerHandleFailedRequestInput {
|
|
15
|
-
crawler: BrowserCrawler;
|
|
16
|
-
}
|
|
17
|
-
export declare type BrowserCrawlerHandleFailedRequest = (inputs: BrowserCrawlerHandleFailedRequestInput) => Awaitable<void>;
|
|
18
18
|
export declare type BrowserCrawlerHandleRequest<Context extends BrowserCrawlingContext = BrowserCrawlingContext> = (inputs: Context) => Awaitable<void>;
|
|
19
|
+
export declare type BrowserCrawlerHandleFailedRequest<Context extends BrowserCrawlingContext = BrowserCrawlingContext> = (inputs: Context, error: Error) => Awaitable<void>;
|
|
19
20
|
export declare type BrowserCrawlerEnqueueLinksOptions = Omit<EnqueueLinksOptions, 'requestQueue' | 'urls'>;
|
|
20
21
|
export declare type BrowserHook<Context = BrowserCrawlingContext, GoToOptions extends Record<PropertyKey, any> | undefined = Dictionary> = (crawlingContext: Context, gotoOptions: GoToOptions) => Awaitable<void>;
|
|
21
|
-
export interface BrowserCrawlerOptions<Context extends BrowserCrawlingContext = BrowserCrawlingContext, InternalBrowserPoolOptions extends BrowserPoolOptions = BrowserPoolOptions, __BrowserPlugins extends BrowserPlugin[] = InferBrowserPluginArray<InternalBrowserPoolOptions['browserPlugins']>, __BrowserControllerReturn extends BrowserController = ReturnType<__BrowserPlugins[number]['createController']>, __LaunchContextReturn extends LaunchContext = ReturnType<__BrowserPlugins[number]['createLaunchContext']>> extends Omit<BasicCrawlerOptions, 'requestHandler' | 'handleRequestFunction' | 'failedRequestHandler' | 'handleFailedRequestFunction'> {
|
|
22
|
+
export interface BrowserCrawlerOptions<Context extends BrowserCrawlingContext = BrowserCrawlingContext, InternalBrowserPoolOptions extends BrowserPoolOptions = BrowserPoolOptions, __BrowserPlugins extends BrowserPlugin[] = InferBrowserPluginArray<InternalBrowserPoolOptions['browserPlugins']>, __BrowserControllerReturn extends BrowserController = ReturnType<__BrowserPlugins[number]['createController']>, __LaunchContextReturn extends LaunchContext = ReturnType<__BrowserPlugins[number]['createLaunchContext']>> extends Omit<BasicCrawlerOptions, 'requestHandler' | 'handleRequestFunction' | 'failedRequestHandler' | 'handleFailedRequestFunction' | 'errorHandler'> {
|
|
22
23
|
launchContext?: BrowserLaunchContext<any, any>;
|
|
23
24
|
/**
|
|
24
25
|
* Function that is called to process each request.
|
|
25
|
-
* It is passed an object with the following fields:
|
|
26
26
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
27
|
+
* The function receives the {@link BrowserCrawlingContext}
|
|
28
|
+
* (actual context will be enhanced with the crawler specific properties) as an argument, where:
|
|
29
|
+
* - {@link BrowserCrawlingContext.request|`request`} is an instance of the {@link Request} object
|
|
30
|
+
* with details about the URL to open, HTTP method etc;
|
|
31
|
+
* - {@link BrowserCrawlingContext.page|`page`} is an instance of the
|
|
32
|
+
* Puppeteer [Page](https://pptr.dev/api/puppeteer.page) or
|
|
33
|
+
* Playwright [Page](https://playwright.dev/docs/api/class-page);
|
|
34
|
+
* - {@link BrowserCrawlingContext.browserController|`browserController`} is an instance of the {@link BrowserController};
|
|
35
|
+
* - {@link BrowserCrawlingContext.response|`response`} is an instance of the
|
|
36
|
+
* Puppeteer [Response](https://pptr.dev/api/puppeteer.httpresponse) or
|
|
37
|
+
* Playwright [Response](https://playwright.dev/docs/api/class-response),
|
|
38
|
+
* which is the main resource response as returned by the respective `page.goto()` function.
|
|
38
39
|
*
|
|
39
|
-
* `request` is an instance of the {@link Request} object with details about the URL to open, HTTP method etc.
|
|
40
|
-
* `page` is an instance of the `Puppeteer`
|
|
41
|
-
* [`Page`](https://pptr.dev/#?product=Puppeteer&show=api-class-page) or `Playwright`
|
|
42
|
-
* [`Page`](https://playwright.dev/docs/api/class-page)
|
|
43
|
-
* `browserPool` is an instance of the
|
|
44
|
-
* [`BrowserPool`](https://github.com/apify/browser-pool#BrowserPool),
|
|
45
|
-
* `browserController` is an instance of the
|
|
46
|
-
* [`BrowserController`](https://github.com/apify/browser-pool#browsercontroller),
|
|
47
|
-
* `response` is an instance of the `Puppeteer`
|
|
48
|
-
* [`Response`](https://pptr.dev/#?product=Puppeteer&show=api-class-response) or `Playwright`
|
|
49
|
-
* [`Response`](https://playwright.dev/docs/api/class-response),
|
|
50
|
-
* which is the main resource response as returned by `page.goto(request.url)`.
|
|
51
40
|
* The function must return a promise, which is then awaited by the crawler.
|
|
52
41
|
*
|
|
53
42
|
* If the function throws an exception, the crawler will try to re-crawl the
|
|
54
|
-
* request later, up to
|
|
43
|
+
* request later, up to the {@link BrowserCrawlerOptions.maxRequestRetries|`maxRequestRetries`} times.
|
|
55
44
|
* If all the retries fail, the crawler calls the function
|
|
56
|
-
* provided to the `
|
|
57
|
-
* To make this work,
|
|
58
|
-
* let
|
|
45
|
+
* provided to the {@link BrowserCrawlerOptions.failedRequestHandler|`failedRequestHandler`} parameter.
|
|
46
|
+
* To make this work, we should **always**
|
|
47
|
+
* let our function throw exceptions rather than catch them.
|
|
59
48
|
* The exceptions are logged to the request using the
|
|
60
|
-
* {@link Request.pushErrorMessage} function.
|
|
49
|
+
* {@link Request.pushErrorMessage|`Request.pushErrorMessage()`} function.
|
|
61
50
|
*/
|
|
62
|
-
requestHandler
|
|
51
|
+
requestHandler?: BrowserCrawlerHandleRequest<Context>;
|
|
63
52
|
/**
|
|
64
53
|
* Function that is called to process each request.
|
|
65
|
-
* It is passed an object with the following fields:
|
|
66
54
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
55
|
+
* The function receives the {@link BrowserCrawlingContext}
|
|
56
|
+
* (actual context will be enhanced with the crawler specific properties) as an argument, where:
|
|
57
|
+
* - {@link BrowserCrawlingContext.request|`request`} is an instance of the {@link Request} object
|
|
58
|
+
* with details about the URL to open, HTTP method etc;
|
|
59
|
+
* - {@link BrowserCrawlingContext.page|`page`} is an instance of the
|
|
60
|
+
* Puppeteer [Page](https://pptr.dev/api/puppeteer.page) or
|
|
61
|
+
* Playwright [Page](https://playwright.dev/docs/api/class-page);
|
|
62
|
+
* - {@link BrowserCrawlingContext.browserController|`browserController`} is an instance of the {@link BrowserController};
|
|
63
|
+
* - {@link BrowserCrawlingContext.response|`response`} is an instance of the
|
|
64
|
+
* Puppeteer [Response](https://pptr.dev/api/puppeteer.httpresponse) or
|
|
65
|
+
* Playwright [Response](https://playwright.dev/docs/api/class-response),
|
|
66
|
+
* which is the main resource response as returned by the respective `page.goto()` function.
|
|
78
67
|
*
|
|
79
|
-
* `request` is an instance of the {@link Request} object with details about the URL to open, HTTP method etc.
|
|
80
|
-
* `page` is an instance of the `Puppeteer`
|
|
81
|
-
* [`Page`](https://pptr.dev/#?product=Puppeteer&show=api-class-page) or `Playwright`
|
|
82
|
-
* [`Page`](https://playwright.dev/docs/api/class-page)
|
|
83
|
-
* `browserPool` is an instance of the
|
|
84
|
-
* [`BrowserPool`](https://github.com/apify/browser-pool#BrowserPool),
|
|
85
|
-
* `browserController` is an instance of the
|
|
86
|
-
* [`BrowserController`](https://github.com/apify/browser-pool#browsercontroller),
|
|
87
|
-
* `response` is an instance of the `Puppeteer`
|
|
88
|
-
* [`Response`](https://pptr.dev/#?product=Puppeteer&show=api-class-response) or `Playwright`
|
|
89
|
-
* [`Response`](https://playwright.dev/docs/api/class-response),
|
|
90
|
-
* which is the main resource response as returned by `page.goto(request.url)`.
|
|
91
68
|
* The function must return a promise, which is then awaited by the crawler.
|
|
92
69
|
*
|
|
93
70
|
* If the function throws an exception, the crawler will try to re-crawl the
|
|
94
|
-
* request later, up to
|
|
71
|
+
* request later, up to the {@link BrowserCrawlerOptions.maxRequestRetries|`maxRequestRetries`} times.
|
|
95
72
|
* If all the retries fail, the crawler calls the function
|
|
96
|
-
* provided to the `
|
|
97
|
-
* To make this work,
|
|
98
|
-
* let
|
|
73
|
+
* provided to the {@link BrowserCrawlerOptions.failedRequestHandler|`failedRequestHandler`} parameter.
|
|
74
|
+
* To make this work, we should **always**
|
|
75
|
+
* let our function throw exceptions rather than catch them.
|
|
99
76
|
* The exceptions are logged to the request using the
|
|
100
|
-
* {@link Request.pushErrorMessage} function.
|
|
77
|
+
* {@link Request.pushErrorMessage|`Request.pushErrorMessage()`} function.
|
|
101
78
|
*
|
|
102
79
|
* @deprecated `handlePageFunction` has been renamed to `requestHandler` and will be removed in a future version.
|
|
80
|
+
* @ignore
|
|
103
81
|
*/
|
|
104
82
|
handlePageFunction?: BrowserCrawlerHandleRequest<Context>;
|
|
105
83
|
/**
|
|
106
|
-
*
|
|
84
|
+
* User-provided function that allows modifying the request object before it gets retried by the crawler.
|
|
85
|
+
* It's executed before each retry for the requests that failed less than {@link BrowserCrawlerOptions.maxRequestRetries|`maxRequestRetries`} times.
|
|
107
86
|
*
|
|
108
|
-
* The function receives the
|
|
109
|
-
*
|
|
110
|
-
* {
|
|
111
|
-
*
|
|
112
|
-
* response: Response,
|
|
113
|
-
* page: Page,
|
|
114
|
-
* browserPool: BrowserPool,
|
|
115
|
-
* autoscaledPool: AutoscaledPool,
|
|
116
|
-
* session: Session,
|
|
117
|
-
* browserController: BrowserController,
|
|
118
|
-
* proxyInfo: ProxyInfo,
|
|
119
|
-
* }
|
|
120
|
-
* ```
|
|
121
|
-
* Where the {@link Request} instance corresponds to the failed request, and the `Error` instance
|
|
87
|
+
* The function receives the {@link BrowserCrawlingContext}
|
|
88
|
+
* (actual context will be enhanced with the crawler specific properties) as the first argument,
|
|
89
|
+
* where the {@link BrowserCrawlingContext.request|`request`} corresponds to the request to be retried.
|
|
90
|
+
* Second argument is the `Error` instance that
|
|
122
91
|
* represents the last error thrown during processing of the request.
|
|
92
|
+
*/
|
|
93
|
+
errorHandler?: BrowserCrawlerHandleFailedRequest<Context>;
|
|
94
|
+
/**
|
|
95
|
+
* A function to handle requests that failed more than `option.maxRequestRetries` times.
|
|
123
96
|
*
|
|
97
|
+
* The function receives the {@link BrowserCrawlingContext}
|
|
98
|
+
* (actual context will be enhanced with the crawler specific properties) as the first argument,
|
|
99
|
+
* where the {@link BrowserCrawlingContext.request|`request`} corresponds to the failed request.
|
|
100
|
+
* Second argument is the `Error` instance that
|
|
101
|
+
* represents the last error thrown during processing of the request.
|
|
124
102
|
*/
|
|
125
|
-
failedRequestHandler?: BrowserCrawlerHandleFailedRequest
|
|
103
|
+
failedRequestHandler?: BrowserCrawlerHandleFailedRequest<Context>;
|
|
126
104
|
/**
|
|
127
105
|
* A function to handle requests that failed more than `option.maxRequestRetries` times.
|
|
128
106
|
*
|
|
129
|
-
* The function receives the
|
|
130
|
-
*
|
|
131
|
-
* {
|
|
132
|
-
*
|
|
133
|
-
* response: Response,
|
|
134
|
-
* page: Page,
|
|
135
|
-
* browserPool: BrowserPool,
|
|
136
|
-
* autoscaledPool: AutoscaledPool,
|
|
137
|
-
* session: Session,
|
|
138
|
-
* browserController: BrowserController,
|
|
139
|
-
* proxyInfo: ProxyInfo,
|
|
140
|
-
* }
|
|
141
|
-
* ```
|
|
142
|
-
* Where the {@link Request} instance corresponds to the failed request, and the `Error` instance
|
|
107
|
+
* The function receives the {@link BrowserCrawlingContext}
|
|
108
|
+
* (actual context will be enhanced with the crawler specific properties) as the first argument,
|
|
109
|
+
* where the {@link BrowserCrawlingContext.request|`request`} corresponds to the failed request.
|
|
110
|
+
* Second argument is the `Error` instance that
|
|
143
111
|
* represents the last error thrown during processing of the request.
|
|
144
112
|
*
|
|
145
113
|
* @deprecated `handleFailedRequestFunction` has been renamed to `failedRequestHandler` and will be removed in a future version.
|
|
114
|
+
* @ignore
|
|
146
115
|
*/
|
|
147
|
-
handleFailedRequestFunction?: BrowserCrawlerHandleFailedRequest
|
|
116
|
+
handleFailedRequestFunction?: BrowserCrawlerHandleFailedRequest<Context>;
|
|
148
117
|
/**
|
|
149
|
-
* Custom options passed to the underlying
|
|
150
|
-
*
|
|
118
|
+
* Custom options passed to the underlying {@link BrowserPool} constructor.
|
|
119
|
+
* We can tweak those to fine-tune browser management.
|
|
151
120
|
*/
|
|
152
121
|
browserPoolOptions?: Partial<BrowserPoolOptions> & Partial<BrowserPoolHooks<__BrowserControllerReturn, __LaunchContextReturn>>;
|
|
153
122
|
/**
|
|
154
123
|
* If set, the crawler will be configured for all connections to use
|
|
155
|
-
*
|
|
156
|
-
* For more information, see the [documentation](https://docs.apify.com/proxy).
|
|
124
|
+
* the Proxy URLs provided and rotated according to the configuration.
|
|
157
125
|
*/
|
|
158
126
|
proxyConfiguration?: ProxyConfiguration;
|
|
159
127
|
/**
|
|
160
128
|
* Async functions that are sequentially evaluated before the navigation. Good for setting additional cookies
|
|
161
129
|
* or browser properties before navigation. The function accepts two parameters, `crawlingContext` and `gotoOptions`,
|
|
162
130
|
* which are passed to the `page.goto()` function the crawler calls to navigate.
|
|
163
|
-
*
|
|
164
|
-
*
|
|
131
|
+
*
|
|
132
|
+
* **Example:**
|
|
133
|
+
*
|
|
134
|
+
* ```js
|
|
165
135
|
* preNavigationHooks: [
|
|
166
136
|
* async (crawlingContext, gotoOptions) => {
|
|
167
137
|
* const { page } = crawlingContext;
|
|
168
138
|
* await page.evaluate((attr) => { window.foo = attr; }, 'bar');
|
|
139
|
+
* gotoOptions.timeout = 60_000;
|
|
140
|
+
* gotoOptions.waitUntil = 'domcontentloaded';
|
|
169
141
|
* },
|
|
170
142
|
* ]
|
|
171
143
|
* ```
|
|
@@ -174,13 +146,15 @@ export interface BrowserCrawlerOptions<Context extends BrowserCrawlingContext =
|
|
|
174
146
|
/**
|
|
175
147
|
* Async functions that are sequentially evaluated after the navigation. Good for checking if the navigation was successful.
|
|
176
148
|
* The function accepts `crawlingContext` as the only parameter.
|
|
177
|
-
*
|
|
178
|
-
*
|
|
149
|
+
*
|
|
150
|
+
* **Example:**
|
|
151
|
+
*
|
|
152
|
+
* ```js
|
|
179
153
|
* postNavigationHooks: [
|
|
180
154
|
* async (crawlingContext) => {
|
|
181
155
|
* const { page } = crawlingContext;
|
|
182
156
|
* if (hasCaptcha(page)) {
|
|
183
|
-
* await solveCaptcha
|
|
157
|
+
* await solveCaptcha(page);
|
|
184
158
|
* }
|
|
185
159
|
* },
|
|
186
160
|
* ]
|
|
@@ -192,7 +166,7 @@ export interface BrowserCrawlerOptions<Context extends BrowserCrawlingContext =
|
|
|
192
166
|
*/
|
|
193
167
|
navigationTimeoutSecs?: number;
|
|
194
168
|
/**
|
|
195
|
-
*
|
|
169
|
+
* Defines whether the cookies should be persisted for sessions.
|
|
196
170
|
* This can only be used when `useSessionPool` is set to `true`.
|
|
197
171
|
*/
|
|
198
172
|
persistCookiesPerSession?: boolean;
|
|
@@ -204,46 +178,47 @@ export interface BrowserCrawlerOptions<Context extends BrowserCrawlingContext =
|
|
|
204
178
|
* The URLs to crawl are fed either from a static list of URLs
|
|
205
179
|
* or from a dynamic queue of URLs enabling recursive crawling of websites.
|
|
206
180
|
*
|
|
207
|
-
* Since `BrowserCrawler` uses headless or even
|
|
181
|
+
* Since `BrowserCrawler` uses headless (or even headful) browsers to download web pages and extract data,
|
|
208
182
|
* it is useful for crawling of websites that require to execute JavaScript.
|
|
209
|
-
* If the target website doesn't need JavaScript, consider using {@link CheerioCrawler},
|
|
183
|
+
* If the target website doesn't need JavaScript, we should consider using the {@link CheerioCrawler},
|
|
210
184
|
* which downloads the pages using raw HTTP requests and is about 10x faster.
|
|
211
185
|
*
|
|
212
|
-
* The source URLs are represented
|
|
213
|
-
*
|
|
214
|
-
*
|
|
186
|
+
* The source URLs are represented by the {@link Request} objects that are fed from the {@link RequestList} or {@link RequestQueue} instances
|
|
187
|
+
* provided by the {@link BrowserCrawlerOptions.requestList|`requestList`} or {@link BrowserCrawlerOptions.requestQueue|`requestQueue`}
|
|
188
|
+
* constructor options, respectively. If neither `requestList` nor `requestQueue` options are provided,
|
|
189
|
+
* the crawler will open the default request queue either when the {@link BrowserCrawler.addRequests|`crawler.addRequests()`} function is called,
|
|
190
|
+
* or if `requests` parameter (representing the initial requests) of the {@link BrowserCrawler.run|`crawler.run()`} function is provided.
|
|
215
191
|
*
|
|
216
|
-
* If both {@link BrowserCrawlerOptions.requestList} and {@link BrowserCrawlerOptions.requestQueue} are used,
|
|
192
|
+
* If both {@link BrowserCrawlerOptions.requestList|`requestList`} and {@link BrowserCrawlerOptions.requestQueue|`requestQueue`} options are used,
|
|
217
193
|
* the instance first processes URLs from the {@link RequestList} and automatically enqueues all of them
|
|
218
|
-
* to {@link RequestQueue} before it starts their processing. This ensures that a single URL is not crawled multiple times.
|
|
194
|
+
* to the {@link RequestQueue} before it starts their processing. This ensures that a single URL is not crawled multiple times.
|
|
219
195
|
*
|
|
220
196
|
* The crawler finishes when there are no more {@link Request} objects to crawl.
|
|
221
197
|
*
|
|
222
198
|
* `BrowserCrawler` opens a new browser page (i.e. tab or window) for each {@link Request} object to crawl
|
|
223
|
-
* and then calls the function provided by user as the {@link BrowserCrawlerOptions.
|
|
199
|
+
* and then calls the function provided by user as the {@link BrowserCrawlerOptions.requestHandler|`requestHandler`} option.
|
|
224
200
|
*
|
|
225
201
|
* New pages are only opened when there is enough free CPU and memory available,
|
|
226
202
|
* using the functionality provided by the {@link AutoscaledPool} class.
|
|
227
|
-
* All {@link AutoscaledPool} configuration options can be passed to the {@link BrowserCrawlerOptions.autoscaledPoolOptions}
|
|
228
|
-
* parameter of the `BrowserCrawler` constructor.
|
|
229
|
-
* {@link AutoscaledPoolOptions}
|
|
203
|
+
* All {@link AutoscaledPool} configuration options can be passed to the {@link BrowserCrawlerOptions.autoscaledPoolOptions|`autoscaledPoolOptions`}
|
|
204
|
+
* parameter of the `BrowserCrawler` constructor.
|
|
205
|
+
* For user convenience, the {@link AutoscaledPoolOptions.minConcurrency|`minConcurrency`} and
|
|
206
|
+
* {@link AutoscaledPoolOptions.maxConcurrency|`maxConcurrency`} options of the
|
|
207
|
+
* underlying {@link AutoscaledPool} constructor are available directly in the `BrowserCrawler` constructor.
|
|
208
|
+
*
|
|
209
|
+
* > *NOTE:* the pool of browser instances is internally managed by the {@link BrowserPool} class.
|
|
230
210
|
*
|
|
231
|
-
* Note that the pool of browser instances is internally managed by the [BrowserPool](https://github.com/apify/browser-pool) class.
|
|
232
|
-
* ```js
|
|
233
|
-
* await crawler.run();
|
|
234
|
-
* ```
|
|
235
211
|
* @category Crawlers
|
|
236
212
|
*/
|
|
237
213
|
export declare abstract class BrowserCrawler<InternalBrowserPoolOptions extends BrowserPoolOptions = BrowserPoolOptions, LaunchOptions = Dictionary, Context extends BrowserCrawlingContext = BrowserCrawlingContext, GoToOptions extends Record<PropertyKey, any> = Dictionary> extends BasicCrawler<Context> {
|
|
214
|
+
readonly config: Configuration;
|
|
238
215
|
/**
|
|
239
216
|
* A reference to the underlying {@link ProxyConfiguration} class that manages the crawler's proxies.
|
|
240
217
|
* Only available if used by the crawler.
|
|
241
218
|
*/
|
|
242
219
|
proxyConfiguration?: ProxyConfiguration;
|
|
243
220
|
/**
|
|
244
|
-
* A reference to the underlying
|
|
245
|
-
* For more information about it, see the [`browser-pool` module](https://github.com/apify/browser-pool).
|
|
246
|
-
* @todo the type is almost unusable with so many generic arguments, what should go there? we need inference
|
|
221
|
+
* A reference to the underlying {@link BrowserPool} class that manages the crawler's browsers.
|
|
247
222
|
*/
|
|
248
223
|
browserPool: BrowserPool<InternalBrowserPoolOptions>;
|
|
249
224
|
launchContext?: BrowserLaunchContext<LaunchOptions, unknown>;
|
|
@@ -269,6 +244,7 @@ export declare abstract class BrowserCrawler<InternalBrowserPoolOptions extends
|
|
|
269
244
|
handleRequestFunction: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
|
|
270
245
|
requestHandlerTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
271
246
|
handleRequestTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
247
|
+
errorHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
|
|
272
248
|
failedRequestHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
|
|
273
249
|
handleFailedRequestFunction: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
|
|
274
250
|
maxRequestRetries: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
@@ -276,14 +252,15 @@ export declare abstract class BrowserCrawler<InternalBrowserPoolOptions extends
|
|
|
276
252
|
autoscaledPoolOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
277
253
|
minConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
278
254
|
maxConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
255
|
+
maxRequestsPerMinute: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
279
256
|
log: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
280
257
|
};
|
|
281
258
|
/**
|
|
282
259
|
* All `BrowserCrawler` parameters are passed via an options object.
|
|
283
260
|
*/
|
|
284
|
-
protected constructor(options
|
|
261
|
+
protected constructor(options?: BrowserCrawlerOptions<Context>, config?: Configuration);
|
|
285
262
|
/**
|
|
286
|
-
* Wrapper around
|
|
263
|
+
* Wrapper around requestHandler that opens and closes pages etc.
|
|
287
264
|
*/
|
|
288
265
|
protected _runRequestHandler(crawlingContext: Context): Promise<void>;
|
|
289
266
|
protected _enhanceCrawlingContextWithPageInfo(crawlingContext: Context, page: CommonPage, useIncognitoPages?: boolean): void;
|
|
@@ -292,17 +269,16 @@ export declare abstract class BrowserCrawler<InternalBrowserPoolOptions extends
|
|
|
292
269
|
/**
|
|
293
270
|
* Marks session bad in case of navigation timeout.
|
|
294
271
|
*/
|
|
295
|
-
protected _handleNavigationTimeout(crawlingContext: Context, error: Error): void
|
|
272
|
+
protected _handleNavigationTimeout(crawlingContext: Context, error: Error): Promise<void>;
|
|
296
273
|
protected abstract _navigationHandler(crawlingContext: Context, gotoOptions: GoToOptions): Promise<Context['response'] | null | undefined>;
|
|
297
274
|
/**
|
|
298
275
|
* Should be overridden in case of different automation library that does not support this response API.
|
|
299
|
-
* @todo: This can be also done as a postNavigation hook except the loadedUrl marking.
|
|
300
276
|
*/
|
|
301
277
|
protected _responseHandler(crawlingContext: Context): Promise<void>;
|
|
302
278
|
protected _extendLaunchContext(_pageId: string, launchContext: LaunchContext): Promise<void>;
|
|
303
279
|
protected _maybeAddSessionRetiredListener(_pageId: string, browserController: Context['browserController']): void;
|
|
304
280
|
/**
|
|
305
|
-
* Function for cleaning up after all
|
|
281
|
+
* Function for cleaning up after all requests are processed.
|
|
306
282
|
* @ignore
|
|
307
283
|
*/
|
|
308
284
|
teardown(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-crawler.d.ts","sourceRoot":"","sources":["../../src/internals/browser-crawler.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"browser-crawler.d.ts","sourceRoot":"","sources":["../../src/internals/browser-crawler.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,41 +15,43 @@ const tough_cookie_1 = require("tough-cookie");
|
|
|
15
15
|
* The URLs to crawl are fed either from a static list of URLs
|
|
16
16
|
* or from a dynamic queue of URLs enabling recursive crawling of websites.
|
|
17
17
|
*
|
|
18
|
-
* Since `BrowserCrawler` uses headless or even
|
|
18
|
+
* Since `BrowserCrawler` uses headless (or even headful) browsers to download web pages and extract data,
|
|
19
19
|
* it is useful for crawling of websites that require to execute JavaScript.
|
|
20
|
-
* If the target website doesn't need JavaScript, consider using {@link CheerioCrawler},
|
|
20
|
+
* If the target website doesn't need JavaScript, we should consider using the {@link CheerioCrawler},
|
|
21
21
|
* which downloads the pages using raw HTTP requests and is about 10x faster.
|
|
22
22
|
*
|
|
23
|
-
* The source URLs are represented
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* The source URLs are represented by the {@link Request} objects that are fed from the {@link RequestList} or {@link RequestQueue} instances
|
|
24
|
+
* provided by the {@link BrowserCrawlerOptions.requestList|`requestList`} or {@link BrowserCrawlerOptions.requestQueue|`requestQueue`}
|
|
25
|
+
* constructor options, respectively. If neither `requestList` nor `requestQueue` options are provided,
|
|
26
|
+
* the crawler will open the default request queue either when the {@link BrowserCrawler.addRequests|`crawler.addRequests()`} function is called,
|
|
27
|
+
* or if `requests` parameter (representing the initial requests) of the {@link BrowserCrawler.run|`crawler.run()`} function is provided.
|
|
26
28
|
*
|
|
27
|
-
* If both {@link BrowserCrawlerOptions.requestList} and {@link BrowserCrawlerOptions.requestQueue} are used,
|
|
29
|
+
* If both {@link BrowserCrawlerOptions.requestList|`requestList`} and {@link BrowserCrawlerOptions.requestQueue|`requestQueue`} options are used,
|
|
28
30
|
* the instance first processes URLs from the {@link RequestList} and automatically enqueues all of them
|
|
29
|
-
* to {@link RequestQueue} before it starts their processing. This ensures that a single URL is not crawled multiple times.
|
|
31
|
+
* to the {@link RequestQueue} before it starts their processing. This ensures that a single URL is not crawled multiple times.
|
|
30
32
|
*
|
|
31
33
|
* The crawler finishes when there are no more {@link Request} objects to crawl.
|
|
32
34
|
*
|
|
33
35
|
* `BrowserCrawler` opens a new browser page (i.e. tab or window) for each {@link Request} object to crawl
|
|
34
|
-
* and then calls the function provided by user as the {@link BrowserCrawlerOptions.
|
|
36
|
+
* and then calls the function provided by user as the {@link BrowserCrawlerOptions.requestHandler|`requestHandler`} option.
|
|
35
37
|
*
|
|
36
38
|
* New pages are only opened when there is enough free CPU and memory available,
|
|
37
39
|
* using the functionality provided by the {@link AutoscaledPool} class.
|
|
38
|
-
* All {@link AutoscaledPool} configuration options can be passed to the {@link BrowserCrawlerOptions.autoscaledPoolOptions}
|
|
39
|
-
* parameter of the `BrowserCrawler` constructor.
|
|
40
|
-
* {@link AutoscaledPoolOptions}
|
|
40
|
+
* All {@link AutoscaledPool} configuration options can be passed to the {@link BrowserCrawlerOptions.autoscaledPoolOptions|`autoscaledPoolOptions`}
|
|
41
|
+
* parameter of the `BrowserCrawler` constructor.
|
|
42
|
+
* For user convenience, the {@link AutoscaledPoolOptions.minConcurrency|`minConcurrency`} and
|
|
43
|
+
* {@link AutoscaledPoolOptions.maxConcurrency|`maxConcurrency`} options of the
|
|
44
|
+
* underlying {@link AutoscaledPool} constructor are available directly in the `BrowserCrawler` constructor.
|
|
45
|
+
*
|
|
46
|
+
* > *NOTE:* the pool of browser instances is internally managed by the {@link BrowserPool} class.
|
|
41
47
|
*
|
|
42
|
-
* Note that the pool of browser instances is internally managed by the [BrowserPool](https://github.com/apify/browser-pool) class.
|
|
43
|
-
* ```js
|
|
44
|
-
* await crawler.run();
|
|
45
|
-
* ```
|
|
46
48
|
* @category Crawlers
|
|
47
49
|
*/
|
|
48
50
|
class BrowserCrawler extends basic_1.BasicCrawler {
|
|
49
51
|
/**
|
|
50
52
|
* All `BrowserCrawler` parameters are passed via an options object.
|
|
51
53
|
*/
|
|
52
|
-
constructor(options) {
|
|
54
|
+
constructor(options = {}, config = core_1.Configuration.getGlobalConfig()) {
|
|
53
55
|
(0, ow_1.default)(options, 'BrowserCrawlerOptions', ow_1.default.object.exactShape(BrowserCrawler.optionsShape));
|
|
54
56
|
const { navigationTimeoutSecs = 60, requestHandlerTimeoutSecs = 60, persistCookiesPerSession, proxyConfiguration, launchContext, browserPoolOptions, preNavigationHooks = [], postNavigationHooks = [],
|
|
55
57
|
// Ignored
|
|
@@ -58,6 +60,12 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
58
60
|
...basicCrawlerOptions,
|
|
59
61
|
requestHandler: (...args) => this._runRequestHandler(...args),
|
|
60
62
|
requestHandlerTimeoutSecs: navigationTimeoutSecs + requestHandlerTimeoutSecs + basic_1.BASIC_CRAWLER_TIMEOUT_BUFFER_SECS,
|
|
63
|
+
}, config);
|
|
64
|
+
Object.defineProperty(this, "config", {
|
|
65
|
+
enumerable: true,
|
|
66
|
+
configurable: true,
|
|
67
|
+
writable: true,
|
|
68
|
+
value: config
|
|
61
69
|
});
|
|
62
70
|
/**
|
|
63
71
|
* A reference to the underlying {@link ProxyConfiguration} class that manages the crawler's proxies.
|
|
@@ -70,9 +78,7 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
70
78
|
value: void 0
|
|
71
79
|
});
|
|
72
80
|
/**
|
|
73
|
-
* A reference to the underlying
|
|
74
|
-
* For more information about it, see the [`browser-pool` module](https://github.com/apify/browser-pool).
|
|
75
|
-
* @todo the type is almost unusable with so many generic arguments, what should go there? we need inference
|
|
81
|
+
* A reference to the underlying {@link BrowserPool} class that manages the crawler's browsers.
|
|
76
82
|
*/
|
|
77
83
|
Object.defineProperty(this, "browserPool", {
|
|
78
84
|
enumerable: true,
|
|
@@ -122,7 +128,11 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
122
128
|
propertyKey: 'userProvidedRequestHandler',
|
|
123
129
|
newProperty: userProvidedRequestHandler,
|
|
124
130
|
oldProperty: handlePageFunction,
|
|
131
|
+
allowUndefined: true, // fallback to the default router
|
|
125
132
|
});
|
|
133
|
+
if (!this.userProvidedRequestHandler) {
|
|
134
|
+
this.userProvidedRequestHandler = this.router;
|
|
135
|
+
}
|
|
126
136
|
this._handlePropertyNameChange({
|
|
127
137
|
newName: 'failedRequestHandler',
|
|
128
138
|
oldName: 'handleFailedRequestFunction',
|
|
@@ -147,8 +157,9 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
147
157
|
this.persistCookiesPerSession = false;
|
|
148
158
|
}
|
|
149
159
|
if (launchContext?.userAgent) {
|
|
160
|
+
if (browserPoolOptions.useFingerprints)
|
|
161
|
+
this.log.info('Custom user agent provided, disabling automatic browser fingerprint injection!');
|
|
150
162
|
browserPoolOptions.useFingerprints = false;
|
|
151
|
-
this.log.info('Disabling automatic fingerprint injection because custom user agent has been provided.');
|
|
152
163
|
}
|
|
153
164
|
const { preLaunchHooks = [], postLaunchHooks = [], ...rest } = browserPoolOptions;
|
|
154
165
|
this.browserPool = new browser_pool_1.BrowserPool({
|
|
@@ -164,7 +175,7 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
164
175
|
});
|
|
165
176
|
}
|
|
166
177
|
/**
|
|
167
|
-
* Wrapper around
|
|
178
|
+
* Wrapper around requestHandler that opens and closes pages etc.
|
|
168
179
|
*/
|
|
169
180
|
async _runRequestHandler(crawlingContext) {
|
|
170
181
|
const newPageOptions = {
|
|
@@ -205,7 +216,7 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
205
216
|
if (this.persistCookiesPerSession) {
|
|
206
217
|
const cookies = await crawlingContext.browserController.getCookies(page);
|
|
207
218
|
(0, timeout_1.tryCancel)();
|
|
208
|
-
session?.
|
|
219
|
+
session?.setCookies(cookies, request.loadedUrl);
|
|
209
220
|
}
|
|
210
221
|
}
|
|
211
222
|
await (0, timeout_1.addTimeoutToPromise)(() => Promise.resolve(this.userProvidedRequestHandler(crawlingContext)), this.requestHandlerTimeoutMillis, `requestHandler timed out after ${this.requestHandlerTimeoutMillis / 1000} seconds.`);
|
|
@@ -214,7 +225,7 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
214
225
|
session.markGood();
|
|
215
226
|
}
|
|
216
227
|
finally {
|
|
217
|
-
page.close().catch((error) => this.log.debug('Error while closing page', { error }));
|
|
228
|
+
await page.close().catch((error) => this.log.debug('Error while closing page', { error }));
|
|
218
229
|
}
|
|
219
230
|
}
|
|
220
231
|
_enhanceCrawlingContextWithPageInfo(crawlingContext, page, useIncognitoPages) {
|
|
@@ -252,14 +263,14 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
252
263
|
crawlingContext.response = await this._navigationHandler(crawlingContext, gotoOptions) ?? undefined;
|
|
253
264
|
}
|
|
254
265
|
catch (error) {
|
|
255
|
-
this._handleNavigationTimeout(crawlingContext, error);
|
|
266
|
+
await this._handleNavigationTimeout(crawlingContext, error);
|
|
256
267
|
throw error;
|
|
257
268
|
}
|
|
258
269
|
(0, timeout_1.tryCancel)();
|
|
259
270
|
await this._executeHooks(this.postNavigationHooks, crawlingContext, gotoOptions);
|
|
260
271
|
}
|
|
261
272
|
async _applyCookies({ session, request, page, browserController }, preHooksCookies, postHooksCookies) {
|
|
262
|
-
const sessionCookie = session?.
|
|
273
|
+
const sessionCookie = session?.getCookies(request.url) ?? [];
|
|
263
274
|
const parsedPreHooksCookies = preHooksCookies.split(/ *; */).map((c) => tough_cookie_1.Cookie.parse(c)?.toJSON());
|
|
264
275
|
const parsedPostHooksCookies = postHooksCookies.split(/ *; */).map((c) => tough_cookie_1.Cookie.parse(c)?.toJSON());
|
|
265
276
|
await browserController.setCookies(page, [
|
|
@@ -271,15 +282,15 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
271
282
|
/**
|
|
272
283
|
* Marks session bad in case of navigation timeout.
|
|
273
284
|
*/
|
|
274
|
-
_handleNavigationTimeout(crawlingContext, error) {
|
|
285
|
+
async _handleNavigationTimeout(crawlingContext, error) {
|
|
275
286
|
const { session } = crawlingContext;
|
|
276
287
|
if (error && error.constructor.name === 'TimeoutError') {
|
|
277
288
|
(0, core_1.handleRequestTimeout)({ session, errorMessage: error.message });
|
|
278
289
|
}
|
|
290
|
+
await crawlingContext.page.close();
|
|
279
291
|
}
|
|
280
292
|
/**
|
|
281
293
|
* Should be overridden in case of different automation library that does not support this response API.
|
|
282
|
-
* @todo: This can be also done as a postNavigation hook except the loadedUrl marking.
|
|
283
294
|
*/
|
|
284
295
|
async _responseHandler(crawlingContext) {
|
|
285
296
|
const { response, session, request, page } = crawlingContext;
|
|
@@ -328,7 +339,7 @@ class BrowserCrawler extends basic_1.BasicCrawler {
|
|
|
328
339
|
}
|
|
329
340
|
}
|
|
330
341
|
/**
|
|
331
|
-
* Function for cleaning up after all
|
|
342
|
+
* Function for cleaning up after all requests are processed.
|
|
332
343
|
* @ignore
|
|
333
344
|
*/
|
|
334
345
|
async teardown() {
|