@crawlee/playwright 4.0.0-beta.89 → 4.0.0-beta.90

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/index.d.ts CHANGED
@@ -6,4 +6,4 @@ export { RenderingTypePredictor } from './internals/utils/rendering-type-predict
6
6
  export * as playwrightUtils from './internals/utils/playwright-utils.js';
7
7
  export * as playwrightClickElements from './internals/enqueue-links/click-elements.js';
8
8
  export type { DirectNavigationOptions as PlaywrightDirectNavigationOptions } from './internals/utils/playwright-utils.js';
9
- export type { RenderingType } from './internals/utils/rendering-type-prediction.js';
9
+ export type { IRenderingTypePredictor, RenderingType } from './internals/utils/rendering-type-prediction.js';
@@ -10,7 +10,7 @@ import type { AnyNode } from 'domhandler';
10
10
  // @ts-ignore optional peer dependency or compatibility with es2022
11
11
  import type { Page } from 'playwright';
12
12
  import type { PlaywrightCrawlingContext, PlaywrightGotoOptions } from './playwright-crawler.js';
13
- import { RenderingTypePredictor } from './utils/rendering-type-prediction.js';
13
+ import { type IRenderingTypePredictor } from './utils/rendering-type-prediction.js';
14
14
  interface AdaptivePlaywrightCrawlerStatisticState extends StatisticState {
15
15
  httpOnlyRequestHandlerRuns?: number;
16
16
  browserRequestHandlerRuns?: number;
@@ -137,9 +137,11 @@ export interface AdaptivePlaywrightCrawlerOptions<ContextExtension = Dictionary<
137
137
  */
138
138
  resultComparator?: (resultA: RequestHandlerResult, resultB: RequestHandlerResult) => boolean | 'equal' | 'different' | 'inconclusive';
139
139
  /**
140
- * A custom rendering type predictor
140
+ * A custom rendering type predictor. A predictor passed here is borrowed - the crawler never drives its
141
+ * lifecycle, so set it up yourself (the built-in {@link RenderingTypePredictor} needs `initialize()`).
142
+ * Omit the option and the crawler builds its own from `renderingTypeDetectionRatio` - and initializes it.
141
143
  */
142
- renderingTypePredictor?: Pick<RenderingTypePredictor, 'predict' | 'storeResult' | 'initialize'>;
144
+ renderingTypePredictor?: IRenderingTypePredictor;
143
145
  /**
144
146
  * Prevent direct access to storage in request handlers (only allow using context helpers).
145
147
  * Defaults to `true`
@@ -2,11 +2,11 @@ import { isDeepStrictEqual } from 'node:util';
2
2
  import { BasicCrawler } from '@crawlee/basic';
3
3
  import { extractUrlsFromPage } from '@crawlee/browser';
4
4
  import { CheerioCrawler } from '@crawlee/cheerio';
5
- import { RequestHandlerError, RequestHandlerResult, resolveBaseUrlForEnqueueLinksFiltering, Router, serviceLocator, Statistics, withCheckedStorageAccess, } from '@crawlee/core';
5
+ import { OwnedOrInjected, RequestHandlerError, RequestHandlerResult, resolveBaseUrlForEnqueueLinksFiltering, Router, serviceLocator, Statistics, withCheckedStorageAccess, } from '@crawlee/core';
6
6
  import { extractUrlsFromCheerio } from '@crawlee/utils';
7
7
  import { addTimeoutToPromise } from '@apify/timeout';
8
8
  import { PlaywrightCrawler } from './playwright-crawler.js';
9
- import { RenderingTypePredictor } from './utils/rendering-type-prediction.js';
9
+ import { RenderingTypePredictor, } from './utils/rendering-type-prediction.js';
10
10
  class AdaptivePlaywrightCrawlerStatistics extends Statistics {
11
11
  state = null; // this needs to be assigned for a valid override, but the initialization is done by a reset() call from the parent constructor
12
12
  constructor(options = {}) {
@@ -103,8 +103,9 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
103
103
  contextPipelineBuilder: contextPipelineBuilder ?? (() => this.buildContextPipeline()),
104
104
  });
105
105
  this.individualRequestHandlerTimeoutMillis = requestHandlerTimeoutSecs * 1000;
106
- this.renderingTypePredictor =
107
- renderingTypePredictor ?? new RenderingTypePredictor({ detectionRatio: renderingTypeDetectionRatio });
106
+ // `renderingTypeDetectionRatio` only configures the default predictor - an injected one brings its own
107
+ // detection ratio (and its own state), so the option is ignored in that case.
108
+ this.renderingTypePredictor = OwnedOrInjected.resolve(renderingTypePredictor, () => new RenderingTypePredictor({ detectionRatio: renderingTypeDetectionRatio }));
108
109
  this.resultChecker = resultChecker ?? (() => true);
109
110
  this.shouldPropagateError = shouldPropagateError ?? (() => false);
110
111
  if (resultComparator !== undefined) {
@@ -162,7 +163,9 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
162
163
  this.preventDirectStorageAccess = preventDirectStorageAccess;
163
164
  }
164
165
  async _init() {
165
- await this.renderingTypePredictor.initialize();
166
+ // Only the predictor we built ourselves is ours to initialize - an injected one is borrowed, so its
167
+ // lifecycle (including restoring persisted state) stays with whoever created it.
168
+ await this.renderingTypePredictor.ifOwned((predictor) => predictor.initialize());
166
169
  return await super._init();
167
170
  }
168
171
  buildContextPipeline() {
@@ -302,7 +305,7 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
302
305
  }
303
306
  }
304
307
  async runRequestHandler(crawlingContext) {
305
- const renderingTypePrediction = this.renderingTypePredictor.predict(crawlingContext.request);
308
+ const renderingTypePrediction = this.renderingTypePredictor.value.predict(crawlingContext.request);
306
309
  const shouldDetectRenderingType = Math.random() < renderingTypePrediction.detectionProbabilityRecommendation;
307
310
  if (!shouldDetectRenderingType) {
308
311
  crawlingContext.log.debug(`Predicted rendering type ${renderingTypePrediction.renderingType} for ${crawlingContext.request.url}`);
@@ -382,7 +385,7 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
382
385
  })();
383
386
  crawlingContext.log.debug(`Detected rendering type ${detectionResult} for ${crawlingContext.request.url}`);
384
387
  if (detectionResult !== undefined) {
385
- this.renderingTypePredictor.storeResult(crawlingContext.request, detectionResult);
388
+ this.renderingTypePredictor.value.storeResult(crawlingContext.request, detectionResult);
386
389
  }
387
390
  }
388
391
  }
@@ -5,12 +5,27 @@ export interface RenderingTypePredictorOptions {
5
5
  detectionRatio: number;
6
6
  persistenceOptions?: Partial<RecoverableStatePersistenceOptions>;
7
7
  }
8
+ /**
9
+ * Minimal contract that any object passed to {@link AdaptivePlaywrightCrawler} as its
10
+ * `renderingTypePredictor` option must satisfy.
11
+ *
12
+ * @experimental
13
+ */
14
+ export interface IRenderingTypePredictor {
15
+ /** Predict the rendering type for a request, and how likely the crawler should be to verify it. */
16
+ predict(request: Request): {
17
+ renderingType: RenderingType;
18
+ detectionProbabilityRecommendation: number;
19
+ };
20
+ /** Report a detected rendering type, so that future predictions can take it into account. */
21
+ storeResult(requests: Request | Request[], renderingType: RenderingType): void;
22
+ }
8
23
  /**
9
24
  * Stores rendering type information for previously crawled URLs and predicts the rendering type for URLs that have yet to be crawled and recommends when rendering type detection should be performed.
10
25
  *
11
26
  * @experimental
12
27
  */
13
- export declare class RenderingTypePredictor {
28
+ export declare class RenderingTypePredictor implements IRenderingTypePredictor {
14
29
  private detectionRatio;
15
30
  private state;
16
31
  constructor({ detectionRatio, persistenceOptions }: RenderingTypePredictorOptions);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/playwright",
3
- "version": "4.0.0-beta.89",
3
+ "version": "4.0.0-beta.90",
4
4
  "description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
5
5
  "engines": {
6
6
  "node": ">=22.0.0"
@@ -49,13 +49,13 @@
49
49
  "dependencies": {
50
50
  "@apify/datastructures": "^2.0.3",
51
51
  "@apify/timeout": "^0.3.2",
52
- "@crawlee/basic": "4.0.0-beta.89",
53
- "@crawlee/browser": "4.0.0-beta.89",
54
- "@crawlee/browser-pool": "4.0.0-beta.89",
55
- "@crawlee/cheerio": "4.0.0-beta.89",
56
- "@crawlee/core": "4.0.0-beta.89",
57
- "@crawlee/types": "4.0.0-beta.89",
58
- "@crawlee/utils": "4.0.0-beta.89",
52
+ "@crawlee/basic": "4.0.0-beta.90",
53
+ "@crawlee/browser": "4.0.0-beta.90",
54
+ "@crawlee/browser-pool": "4.0.0-beta.90",
55
+ "@crawlee/cheerio": "4.0.0-beta.90",
56
+ "@crawlee/core": "4.0.0-beta.90",
57
+ "@crawlee/types": "4.0.0-beta.90",
58
+ "@crawlee/utils": "4.0.0-beta.90",
59
59
  "cheerio": "^1.0.0",
60
60
  "idcac-playwright": "^0.1.3",
61
61
  "jquery": "^3.7.1",
@@ -85,5 +85,5 @@
85
85
  }
86
86
  }
87
87
  },
88
- "gitHead": "9279941162eb4be0a9113f768b5bd79d27e66eba"
88
+ "gitHead": "7afdd44c5b6850b4775cfc08ffbbdd1791ae6402"
89
89
  }