@crawlee/jsdom 4.0.0-beta.122 → 4.0.0-beta.124

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.
@@ -1,8 +1,7 @@
1
- import type { BasicCrawlingContext, CrawlingContext, EnqueueLinksOptions, ErrorHandler, GetUserDataFromRequest, HttpCrawlerOptions, InternalHttpCrawlingContext, InternalHttpHook, IRequestManager, RequestHandler, RouterHandler, RouterRoutes, RouteSchemas, RoutesFromSchemas, SkippedRequestCallback } from '@crawlee/http';
1
+ import type { AddRequestsBatchedResult, CrawlingContext, EnqueueLinksOptions, ErrorHandler, ExtractLinksOptions, GetUserDataFromRequest, HttpCrawlerOptions, InternalHttpCrawlingContext, InternalHttpHook, RequestHandler, RouterHandler, RouterRoutes, RouteSchemas, RoutesFromSchemas } from '@crawlee/http';
2
2
  import { HttpCrawler } from '@crawlee/http';
3
- import type { BatchAddRequestsResult, Dictionary } from '@crawlee/types';
3
+ import type { Dictionary } from '@crawlee/types';
4
4
  import { type CheerioRoot } from '@crawlee/utils/internal';
5
- import { type RobotsTxtFile } from '@crawlee/utils';
6
5
  import type { DOMWindow } from 'jsdom';
7
6
  import { VirtualConsole } from 'jsdom';
8
7
  import { z } from 'zod';
@@ -56,9 +55,13 @@ JSONData extends Dictionary = any> extends InternalHttpCrawlingContext<UserData,
56
55
  */
57
56
  parseWithCheerio(selector?: string, timeoutMs?: number): Promise<CheerioRoot>;
58
57
  /**
59
- * Helper function for extracting URLs from the parsed HTML and adding them to the request queue.
58
+ * Extracts URLs from the parsed DOM, without adding them to the request queue.
60
59
  */
61
- enqueueLinks(options?: EnqueueLinksOptions): Promise<BatchAddRequestsResult>;
60
+ extractLinks(options?: ExtractLinksOptions): Promise<string[]>;
61
+ /**
62
+ * Helper function for extracting URLs from the parsed DOM and adding them to the request queue.
63
+ */
64
+ enqueueLinks(options?: EnqueueLinksOptions): Promise<AddRequestsBatchedResult>;
62
65
  }
63
66
  export type JSDOMRequestHandler<UserData extends Dictionary = any, // with default to Dictionary we cant use a typed router in untyped crawler
64
67
  JSONData extends Dictionary = any> = RequestHandler<JSDOMCrawlingContext<UserData, JSONData>>;
@@ -185,7 +188,8 @@ export declare class JSDOMCrawler<ContextExtension = Dictionary<never>, Extended
185
188
  readonly body: string;
186
189
  readonly document: Document;
187
190
  } & {
188
- enqueueLinks: (enqueueOptions?: EnqueueLinksOptions) => Promise<BatchAddRequestsResult>;
191
+ extractLinks: (options?: ExtractLinksOptions) => Promise<string[]>;
192
+ enqueueLinks: (options?: EnqueueLinksOptions) => Promise<AddRequestsBatchedResult>;
189
193
  waitForSelector(selector: string, timeoutMs?: number): Promise<void>;
190
194
  // @ts-ignore optional peer dependency or compatibility with es2022
191
195
  parseWithCheerio(selector?: string, _timeoutMs?: number): Promise<import("cheerio").CheerioAPI>;
@@ -209,24 +213,6 @@ export declare class JSDOMCrawler<ContextExtension = Dictionary<never>, Extended
209
213
  private parseContent;
210
214
  private addHelpers;
211
215
  }
212
- interface EnqueueLinksInternalOptions {
213
- options?: EnqueueLinksOptions;
214
- window: DOMWindow | null;
215
- requestManager: IRequestManager;
216
- robotsTxtFile?: RobotsTxtFile;
217
- onSkippedRequest?: SkippedRequestCallback;
218
- originalRequestUrl: string;
219
- finalRequestUrl?: string;
220
- }
221
- interface BoundEnqueueLinksInternalOptions {
222
- enqueueLinks: BasicCrawlingContext['enqueueLinks'];
223
- options?: EnqueueLinksOptions;
224
- window: DOMWindow | null;
225
- originalRequestUrl: string;
226
- finalRequestUrl?: string;
227
- }
228
- /** @internal */
229
- export declare function domCrawlerEnqueueLinks(options: EnqueueLinksInternalOptions | BoundEnqueueLinksInternalOptions): Promise<unknown>;
230
216
  /**
231
217
  * Creates new {@link Router} instance that works based on request labels.
232
218
  * This instance can then serve as a `requestHandler` of your {@link JSDOMCrawler}.
@@ -254,4 +240,3 @@ export declare function domCrawlerEnqueueLinks(options: EnqueueLinksInternalOpti
254
240
  export declare function createJSDOMRouter<Context extends JSDOMCrawlingContext = JSDOMCrawlingContext, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>>(routes?: RouterRoutes<Context, Routes>): RouterHandler<Context, Routes>;
255
241
  export declare function createJSDOMRouter<Context extends JSDOMCrawlingContext = JSDOMCrawlingContext, UserData extends Dictionary = GetUserDataFromRequest<Context['request']>>(routes?: RouterRoutes<Context, Record<string, UserData>>): RouterHandler<Context, Record<string, UserData>>;
256
242
  export declare function createJSDOMRouter<Context extends JSDOMCrawlingContext = JSDOMCrawlingContext, const Schemas extends RouteSchemas = RouteSchemas>(schemas: Schemas): RouterHandler<Context, RoutesFromSchemas<Schemas>>;
257
- export {};
@@ -1,4 +1,4 @@
1
- import { enqueueLinks, HttpCrawler, NavigationSkippedError, parseArgument, resolveBaseUrlForEnqueueLinksFiltering, Router, tryAbsoluteURL, } from '@crawlee/http';
1
+ import { EnqueueStrategy, HttpCrawler, NavigationSkippedError, parseArgument, resolveBaseUrlForEnqueueLinksFiltering, Router, tryAbsoluteURL, } from '@crawlee/http';
2
2
  import { sleep } from '@crawlee/utils';
3
3
  import { JSDOM, ResourceLoader, VirtualConsole } from 'jsdom';
4
4
  import { z } from 'zod';
@@ -214,20 +214,28 @@ export class JSDOMCrawler extends HttpCrawler {
214
214
  }
215
215
  }
216
216
  async addHelpers(crawlingContext) {
217
+ const addRequests = crawlingContext.addRequests;
218
+ const extractLinks = async (options) => {
219
+ if (!crawlingContext.window) {
220
+ throw new Error('Cannot extract links because the JSDOM is not available.');
221
+ }
222
+ return extractUrlsFromWindow(crawlingContext.window, options?.selector ?? 'a', options?.baseUrl ?? crawlingContext.request.loadedUrl ?? crawlingContext.request.url);
223
+ };
217
224
  return {
218
- enqueueLinks: async (enqueueOptions) => {
219
- return (await domCrawlerEnqueueLinks({
220
- options: {
221
- ...enqueueOptions,
222
- limit: await this.calculateEnqueuedRequestLimit(enqueueOptions?.limit),
223
- },
224
- window: crawlingContext.window,
225
- requestManager: await this.getRequestManager(),
226
- robotsTxtFile: await this.getRobotsTxtFileForUrl(crawlingContext.request.url),
227
- onSkippedRequest: this.handleSkippedRequest,
228
- originalRequestUrl: crawlingContext.request.url,
225
+ extractLinks,
226
+ enqueueLinks: async (options = {}) => {
227
+ const baseUrl = resolveBaseUrlForEnqueueLinksFiltering({
228
+ enqueueStrategy: options.strategy,
229
229
  finalRequestUrl: crawlingContext.request.loadedUrl,
230
- })); // TODO make this type safe, see https://github.com/apify/crawlee/issues/4024
230
+ originalRequestUrl: crawlingContext.request.url,
231
+ userProvidedBaseUrl: options.baseUrl,
232
+ });
233
+ const urls = await extractLinks(options);
234
+ return addRequests(urls, {
235
+ ...options,
236
+ baseUrl,
237
+ strategy: options.strategy ?? EnqueueStrategy.SameHostname,
238
+ });
231
239
  },
232
240
  async waitForSelector(selector, timeoutMs = 5_000) {
233
241
  const cheerio = await import('cheerio');
@@ -252,39 +260,6 @@ export class JSDOMCrawler extends HttpCrawler {
252
260
  };
253
261
  }
254
262
  }
255
- /** @internal */
256
- function containsEnqueueLinks(options) {
257
- return !!options.enqueueLinks;
258
- }
259
- /** @internal */
260
- export async function domCrawlerEnqueueLinks(options) {
261
- const { options: enqueueLinksOptions, window, originalRequestUrl, finalRequestUrl } = options;
262
- if (!window) {
263
- throw new Error('Cannot enqueue links because the JSDOM is not available.');
264
- }
265
- const baseUrl = resolveBaseUrlForEnqueueLinksFiltering({
266
- enqueueStrategy: enqueueLinksOptions?.strategy,
267
- finalRequestUrl,
268
- originalRequestUrl,
269
- userProvidedBaseUrl: enqueueLinksOptions?.baseUrl,
270
- });
271
- const urls = extractUrlsFromWindow(window, enqueueLinksOptions?.selector ?? 'a', enqueueLinksOptions?.baseUrl ?? finalRequestUrl ?? originalRequestUrl);
272
- if (containsEnqueueLinks(options)) {
273
- return options.enqueueLinks({
274
- urls,
275
- baseUrl,
276
- ...enqueueLinksOptions,
277
- });
278
- }
279
- return enqueueLinks({
280
- requestManager: options.requestManager,
281
- robotsTxtFile: options.robotsTxtFile,
282
- onSkippedRequest: options.onSkippedRequest,
283
- urls,
284
- baseUrl,
285
- ...enqueueLinksOptions,
286
- });
287
- }
288
263
  /**
289
264
  * Extracts URLs from a given Window object.
290
265
  * @ignore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/jsdom",
3
- "version": "4.0.0-beta.122",
3
+ "version": "4.0.0-beta.124",
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,9 +49,9 @@
49
49
  "dependencies": {
50
50
  "@apify/timeout": "^0.4.4",
51
51
  "@apify/utilities": "^2.7.10",
52
- "@crawlee/http": "4.0.0-beta.122",
53
- "@crawlee/types": "4.0.0-beta.122",
54
- "@crawlee/utils": "4.0.0-beta.122",
52
+ "@crawlee/http": "4.0.0-beta.124",
53
+ "@crawlee/types": "4.0.0-beta.124",
54
+ "@crawlee/utils": "4.0.0-beta.124",
55
55
  "@types/jsdom": "^21.1.7",
56
56
  "cheerio": "^1.0.0",
57
57
  "jsdom": "^26.1.0",
@@ -65,5 +65,5 @@
65
65
  }
66
66
  }
67
67
  },
68
- "gitHead": "2c3e87fefdb9e1fca4c144f03167d8524cfdc2e5"
68
+ "gitHead": "0694ee1b94c755b98141671baa93cc363f2bf8e3"
69
69
  }