@crawlee/puppeteer 3.0.0-alpha.1 → 3.0.0-alpha.4

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.
Files changed (35) hide show
  1. package/index.d.ts +12 -0
  2. package/index.d.ts.map +1 -0
  3. package/index.js +12 -0
  4. package/index.js.map +1 -0
  5. package/index.mjs +76 -0
  6. package/internals/enqueue-links/click-elements.d.ts +188 -0
  7. package/internals/enqueue-links/click-elements.d.ts.map +1 -0
  8. package/internals/enqueue-links/click-elements.js +336 -0
  9. package/internals/enqueue-links/click-elements.js.map +1 -0
  10. package/internals/puppeteer-crawler.d.ts +149 -0
  11. package/internals/puppeteer-crawler.d.ts.map +1 -0
  12. package/internals/puppeteer-crawler.js +117 -0
  13. package/internals/puppeteer-crawler.js.map +1 -0
  14. package/internals/puppeteer-launcher.d.ts +134 -0
  15. package/internals/puppeteer-launcher.d.ts.map +1 -0
  16. package/internals/puppeteer-launcher.js +146 -0
  17. package/internals/puppeteer-launcher.js.map +1 -0
  18. package/internals/stealth/hiding_tricks.d.ts +10 -0
  19. package/internals/stealth/hiding_tricks.d.ts.map +1 -0
  20. package/internals/stealth/hiding_tricks.js +334 -0
  21. package/internals/stealth/hiding_tricks.js.map +1 -0
  22. package/internals/stealth/index.d.ts +40 -0
  23. package/internals/stealth/index.d.ts.map +1 -0
  24. package/internals/stealth/index.js +108 -0
  25. package/internals/stealth/index.js.map +1 -0
  26. package/internals/utils/puppeteer_request_interception.d.ts +60 -0
  27. package/internals/utils/puppeteer_request_interception.d.ts.map +1 -0
  28. package/internals/utils/puppeteer_request_interception.js +225 -0
  29. package/internals/utils/puppeteer_request_interception.js.map +1 -0
  30. package/internals/utils/puppeteer_utils.d.ts +298 -0
  31. package/internals/utils/puppeteer_utils.d.ts.map +1 -0
  32. package/internals/utils/puppeteer_utils.js +468 -0
  33. package/internals/utils/puppeteer_utils.js.map +1 -0
  34. package/package.json +2 -5
  35. package/tsconfig.build.tsbuildinfo +1 -0
package/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export * from '@crawlee/browser';
2
+ export * from './internals/puppeteer-crawler';
3
+ export * from './internals/puppeteer-launcher';
4
+ export * as puppeteerStealth from './internals/stealth';
5
+ export type { StealthOptions } from './internals/stealth';
6
+ export * as puppeteerRequestInterception from './internals/utils/puppeteer_request_interception';
7
+ export type { InterceptHandler } from './internals/utils/puppeteer_request_interception';
8
+ export * as puppeteerUtils from './internals/utils/puppeteer_utils';
9
+ export type { BlockRequestsOptions, CompiledScriptFunction, CompiledScriptParams, DirectNavigationOptions as PuppeteerDirectNavigationOptions, InfiniteScrollOptions, InjectFileOptions, SaveSnapshotOptions, } from './internals/utils/puppeteer_utils';
10
+ export * as puppeteerClickElements from './internals/enqueue-links/click-elements';
11
+ export type { EnqueueLinksByClickingElementsOptions } from './internals/enqueue-links/click-elements';
12
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAE/C,OAAO,KAAK,gBAAgB,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,4BAA4B,MAAM,kDAAkD,CAAC;AACjG,YAAY,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AAEzF,OAAO,KAAK,cAAc,MAAM,mCAAmC,CAAC;AACpE,YAAY,EACR,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,IAAI,gCAAgC,EAC3D,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACtB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,KAAK,sBAAsB,MAAM,0CAA0C,CAAC;AACnF,YAAY,EAAE,qCAAqC,EAAE,MAAM,0CAA0C,CAAC"}
package/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.puppeteerClickElements = exports.puppeteerUtils = exports.puppeteerRequestInterception = exports.puppeteerStealth = void 0;
4
+ const tslib_1 = require("tslib");
5
+ tslib_1.__exportStar(require("@crawlee/browser"), exports);
6
+ tslib_1.__exportStar(require("./internals/puppeteer-crawler"), exports);
7
+ tslib_1.__exportStar(require("./internals/puppeteer-launcher"), exports);
8
+ exports.puppeteerStealth = tslib_1.__importStar(require("./internals/stealth"));
9
+ exports.puppeteerRequestInterception = tslib_1.__importStar(require("./internals/utils/puppeteer_request_interception"));
10
+ exports.puppeteerUtils = tslib_1.__importStar(require("./internals/utils/puppeteer_utils"));
11
+ exports.puppeteerClickElements = tslib_1.__importStar(require("./internals/enqueue-links/click-elements"));
12
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,2DAAiC;AACjC,wEAA8C;AAC9C,yEAA+C;AAE/C,gFAAwD;AAGxD,yHAAiG;AAGjG,4FAAoE;AAWpE,2GAAmF"}
package/index.mjs ADDED
@@ -0,0 +1,76 @@
1
+ import mod from "./index.js";
2
+
3
+ export default mod;
4
+ export const API_PROCESSED_REQUESTS_DELAY_MILLIS = mod.API_PROCESSED_REQUESTS_DELAY_MILLIS;
5
+ export const AutoscaledPool = mod.AutoscaledPool;
6
+ export const BASIC_CRAWLER_TIMEOUT_BUFFER_SECS = mod.BASIC_CRAWLER_TIMEOUT_BUFFER_SECS;
7
+ export const BasicCrawler = mod.BasicCrawler;
8
+ export const BrowserCrawler = mod.BrowserCrawler;
9
+ export const BrowserLauncher = mod.BrowserLauncher;
10
+ export const Configuration = mod.Configuration;
11
+ export const CookieParseError = mod.CookieParseError;
12
+ export const CrawlerExtension = mod.CrawlerExtension;
13
+ export const DATASET_ITERATORS_DEFAULT_LIMIT = mod.DATASET_ITERATORS_DEFAULT_LIMIT;
14
+ export const Dataset = mod.Dataset;
15
+ export const EVENT_SESSION_RETIRED = mod.EVENT_SESSION_RETIRED;
16
+ export const EnqueueStrategy = mod.EnqueueStrategy;
17
+ export const EventManager = mod.EventManager;
18
+ export const EventType = mod.EventType;
19
+ export const KeyValueStore = mod.KeyValueStore;
20
+ export const LocalEventManager = mod.LocalEventManager;
21
+ export const Log = mod.Log;
22
+ export const LogLevel = mod.LogLevel;
23
+ export const Logger = mod.Logger;
24
+ export const LoggerJson = mod.LoggerJson;
25
+ export const LoggerText = mod.LoggerText;
26
+ export const MAX_QUERIES_FOR_CONSISTENCY = mod.MAX_QUERIES_FOR_CONSISTENCY;
27
+ export const ProxyConfiguration = mod.ProxyConfiguration;
28
+ export const PuppeteerCrawler = mod.PuppeteerCrawler;
29
+ export const PuppeteerLauncher = mod.PuppeteerLauncher;
30
+ export const QUERY_HEAD_BUFFER = mod.QUERY_HEAD_BUFFER;
31
+ export const QUERY_HEAD_MIN_LENGTH = mod.QUERY_HEAD_MIN_LENGTH;
32
+ export const REQUESTS_PERSISTENCE_KEY = mod.REQUESTS_PERSISTENCE_KEY;
33
+ export const Request = mod.Request;
34
+ export const RequestList = mod.RequestList;
35
+ export const RequestQueue = mod.RequestQueue;
36
+ export const STATE_PERSISTENCE_KEY = mod.STATE_PERSISTENCE_KEY;
37
+ export const STATUS_CODES_BLOCKED = mod.STATUS_CODES_BLOCKED;
38
+ export const STORAGE_CONSISTENCY_DELAY_MILLIS = mod.STORAGE_CONSISTENCY_DELAY_MILLIS;
39
+ export const Session = mod.Session;
40
+ export const SessionPool = mod.SessionPool;
41
+ export const Snapshotter = mod.Snapshotter;
42
+ export const Statistics = mod.Statistics;
43
+ export const StorageManager = mod.StorageManager;
44
+ export const SystemStatus = mod.SystemStatus;
45
+ export const basicCrawlerEnqueueLinks = mod.basicCrawlerEnqueueLinks;
46
+ export const browserCrawlerEnqueueLinks = mod.browserCrawlerEnqueueLinks;
47
+ export const checkAndSerialize = mod.checkAndSerialize;
48
+ export const chunkBySize = mod.chunkBySize;
49
+ export const constructGlobObjectsFromGlobs = mod.constructGlobObjectsFromGlobs;
50
+ export const constructRegExpObjectsFromPseudoUrls = mod.constructRegExpObjectsFromPseudoUrls;
51
+ export const constructRegExpObjectsFromRegExps = mod.constructRegExpObjectsFromRegExps;
52
+ export const createDeserialize = mod.createDeserialize;
53
+ export const createRequestOptions = mod.createRequestOptions;
54
+ export const createRequests = mod.createRequests;
55
+ export const deserializeArray = mod.deserializeArray;
56
+ export const diffCookies = mod.diffCookies;
57
+ export const enqueueLinks = mod.enqueueLinks;
58
+ export const getCookiesFromResponse = mod.getCookiesFromResponse;
59
+ export const getRequestId = mod.getRequestId;
60
+ export const handleRequestTimeout = mod.handleRequestTimeout;
61
+ export const launchPuppeteer = mod.launchPuppeteer;
62
+ export const log = mod.log;
63
+ export const maybeStringify = mod.maybeStringify;
64
+ export const mergeCookies = mod.mergeCookies;
65
+ export const openDataset = mod.openDataset;
66
+ export const puppeteerClickElements = mod.puppeteerClickElements;
67
+ export const puppeteerRequestInterception = mod.puppeteerRequestInterception;
68
+ export const puppeteerStealth = mod.puppeteerStealth;
69
+ export const puppeteerUtils = mod.puppeteerUtils;
70
+ export const pushData = mod.pushData;
71
+ export const serializeArray = mod.serializeArray;
72
+ export const storage = mod.storage;
73
+ export const throwOnBlockedRequest = mod.throwOnBlockedRequest;
74
+ export const updateEnqueueLinksPatternCache = mod.updateEnqueueLinksPatternCache;
75
+ export const validateGlobPattern = mod.validateGlobPattern;
76
+ export const validators = mod.validators;
@@ -0,0 +1,188 @@
1
+ import { GlobInput, PseudoUrlInput, RegExpInput, RequestTransform, RequestQueue, storage } from '@crawlee/browser';
2
+ import { Dictionary } from '@crawlee/utils';
3
+ import { ClickOptions, Page, Target } from 'puppeteer';
4
+ export interface EnqueueLinksByClickingElementsOptions {
5
+ /**
6
+ * Puppeteer [`Page`](https://pptr.dev/#?product=Puppeteer&show=api-class-page) object.
7
+ */
8
+ page: Page;
9
+ /**
10
+ * A request queue to which the URLs will be enqueued.
11
+ */
12
+ requestQueue: RequestQueue;
13
+ /**
14
+ * A CSS selector matching elements to be clicked on. Unlike in {@link enqueueLinks}, there is no default
15
+ * value. This is to prevent suboptimal use of this function by using it too broadly.
16
+ */
17
+ selector: string;
18
+ /**
19
+ * Click options for use in Puppeteer's click handler.
20
+ */
21
+ clickOptions?: ClickOptions;
22
+ /**
23
+ * An array of glob pattern strings or plain objects
24
+ * containing glob pattern strings matching the URLs to be enqueued.
25
+ *
26
+ * The plain objects must include at least the `glob` property, which holds the glob pattern string.
27
+ * All remaining keys will be used as request options for the corresponding enqueued {@link Request} objects.
28
+ *
29
+ * The matching is always case-insensitive.
30
+ * If you need case-sensitive matching, use `regexps` property directly.
31
+ *
32
+ * If `globs` is an empty array or `undefined`, then the function
33
+ * enqueues all the intercepted navigation requests produced by the page
34
+ * after clicking on elements matching the provided CSS selector.
35
+ */
36
+ globs?: GlobInput[];
37
+ /**
38
+ * An array of regular expressions or plain objects
39
+ * containing regular expressions matching the URLs to be enqueued.
40
+ *
41
+ * The plain objects must include at least the `regexp` property, which holds the regular expression.
42
+ * All remaining keys will be used as request options for the corresponding enqueued {@link Request} objects.
43
+ *
44
+ * If `regexps` is an empty array or `undefined`, then the function
45
+ * enqueues all the intercepted navigation requests produced by the page
46
+ * after clicking on elements matching the provided CSS selector.
47
+ */
48
+ regexps?: RegExpInput[];
49
+ /**
50
+ * *NOTE:* In future versions of SDK the options will be removed.
51
+ * Please use `globs` or `regexps` instead.
52
+ *
53
+ * An array of {@link PseudoUrl} strings or plain objects
54
+ * containing {@link PseudoUrl} strings matching the URLs to be enqueued.
55
+ *
56
+ * The plain objects must include at least the `purl` property, which holds the pseudo-URL pattern string.
57
+ * All remaining keys will be used as request options for the corresponding enqueued {@link Request} objects.
58
+ *
59
+ * With a pseudo-URL string, the matching is always case-insensitive.
60
+ * If you need case-sensitive matching, use `regexps` property directly.
61
+ *
62
+ * If `pseudoUrls` is an empty array or `undefined`, then the function
63
+ * enqueues all the intercepted navigation requests produced by the page
64
+ * after clicking on elements matching the provided CSS selector.
65
+ *
66
+ * @deprecated prefer using `globs` or `regexps` instead
67
+ */
68
+ pseudoUrls?: PseudoUrlInput[];
69
+ /**
70
+ * Just before a new {@link Request} is constructed and enqueued to the {@link RequestQueue}, this function can be used
71
+ * to remove it or modify its contents such as `userData`, `payload` or, most importantly `uniqueKey`. This is useful
72
+ * when you need to enqueue multiple `Requests` to the queue that share the same URL, but differ in methods or payloads,
73
+ * or to dynamically update or create `userData`.
74
+ *
75
+ * For example: by adding `useExtendedUniqueKey: true` to the `request` object, `uniqueKey` will be computed from
76
+ * a combination of `url`, `method` and `payload` which enables crawling of websites that navigate using form submits
77
+ * (POST requests).
78
+ *
79
+ * **Example:**
80
+ * ```javascript
81
+ * {
82
+ * transformRequestFunction: (request) => {
83
+ * request.userData.foo = 'bar';
84
+ * request.useExtendedUniqueKey = true;
85
+ * return request;
86
+ * }
87
+ * }
88
+ * ```
89
+ */
90
+ transformRequestFunction?: RequestTransform;
91
+ /**
92
+ * Clicking in the page triggers various asynchronous operations that lead to new URLs being shown
93
+ * by the browser. It could be a simple JavaScript redirect or opening of a new tab in the browser.
94
+ * These events often happen only some time after the actual click. Requests typically take milliseconds
95
+ * while new tabs open in hundreds of milliseconds.
96
+ *
97
+ * To be able to capture all those events, the `enqueueLinksByClickingElements()` function repeatedly waits
98
+ * for the `waitForPageIdleSecs`. By repeatedly we mean that whenever a relevant event is triggered, the timer
99
+ * is restarted. As long as new events keep coming, the function will not return, unless
100
+ * the below `maxWaitForPageIdleSecs` timeout is reached.
101
+ *
102
+ * You may want to reduce this for example when you're sure that your clicks do not open new tabs,
103
+ * or increase when you're not getting all the expected URLs.
104
+ * @default 1
105
+ */
106
+ waitForPageIdleSecs?: number;
107
+ /**
108
+ * This is the maximum period for which the function will keep tracking events, even if more events keep coming.
109
+ * Its purpose is to prevent a deadlock in the page by periodic events, often unrelated to the clicking itself.
110
+ * See `waitForPageIdleSecs` above for an explanation.
111
+ * @default 5
112
+ */
113
+ maxWaitForPageIdleSecs?: number;
114
+ }
115
+ /**
116
+ * The function finds elements matching a specific CSS selector in a Puppeteer page,
117
+ * clicks all those elements using a mouse move and a left mouse button click and intercepts
118
+ * all the navigation requests that are subsequently produced by the page. The intercepted
119
+ * requests, including their methods, headers and payloads are then enqueued to a provided
120
+ * {@link RequestQueue}. This is useful to crawl JavaScript heavy pages where links are not available
121
+ * in `href` elements, but rather navigations are triggered in click handlers.
122
+ * If you're looking to find URLs in `href` attributes of the page, see {@link enqueueLinks}.
123
+ *
124
+ * Optionally, the function allows you to filter the target links' URLs using an array of {@link PseudoUrl} objects
125
+ * and override settings of the enqueued {@link Request} objects.
126
+ *
127
+ * **IMPORTANT**: To be able to do this, this function uses various mutations on the page,
128
+ * such as changing the Z-index of elements being clicked and their visibility. Therefore,
129
+ * it is recommended to only use this function as the last operation in the page.
130
+ *
131
+ * **USING HEADFUL BROWSER**: When using a headful browser, this function will only be able to click elements
132
+ * in the focused tab, effectively limiting concurrency to 1. In headless mode, full concurrency can be achieved.
133
+ *
134
+ * **PERFORMANCE**: Clicking elements with a mouse and intercepting requests is not a low level operation
135
+ * that takes nanoseconds. It's not very CPU intensive, but it takes time. We strongly recommend limiting
136
+ * the scope of the clicking as much as possible by using a specific selector that targets only the elements
137
+ * that you assume or know will produce a navigation. You can certainly click everything by using
138
+ * the `*` selector, but be prepared to wait minutes to get results on a large and complex page.
139
+ *
140
+ * **Example usage**
141
+ *
142
+ * ```javascript
143
+ * await Actor.utils.puppeteer.enqueueLinksByClickingElements({
144
+ * page,
145
+ * requestQueue,
146
+ * selector: 'a.product-detail',
147
+ * pseudoUrls: [
148
+ * 'https://www.example.com/handbags/[.*]'
149
+ * 'https://www.example.com/purses/[.*]'
150
+ * ],
151
+ * });
152
+ * ```
153
+ *
154
+ * @returns Promise that resolves to {@link BatchAddRequestsResult} object.
155
+ */
156
+ export declare function enqueueLinksByClickingElements(options: EnqueueLinksByClickingElementsOptions): Promise<storage.BatchAddRequestsResult>;
157
+ interface WaitForPageIdleOptions {
158
+ page: Page;
159
+ waitForPageIdleMillis?: number;
160
+ maxWaitForPageIdleMillis?: number;
161
+ }
162
+ interface ClickElementsAndInterceptNavigationRequestsOptions extends WaitForPageIdleOptions {
163
+ selector: string;
164
+ clickOptions?: ClickOptions;
165
+ }
166
+ /**
167
+ * Clicks all elements of given page matching given selector.
168
+ * Catches and intercepts all initiated navigation requests and opened pages.
169
+ * Returns a list of all target URLs.
170
+ * @ignore
171
+ */
172
+ export declare function clickElementsAndInterceptNavigationRequests(options: ClickElementsAndInterceptNavigationRequestsOptions): Promise<Dictionary[]>;
173
+ /**
174
+ * We're only interested in pages created by the page we're currently clicking in.
175
+ * There will generally be a lot of other targets being created in the browser.
176
+ */
177
+ export declare function isTargetRelevant(page: Page, target: Target): boolean;
178
+ /**
179
+ * Click all elements matching the given selector. To be able to do this using
180
+ * Puppeteer's `.click()` we need to make sure the elements are reachable by mouse,
181
+ * so we first move them to the top of the page's stacking context and then click.
182
+ * We do all in series to prevent elements from hiding one another. Therefore,
183
+ * for large element sets, this will take considerable amount of time.
184
+ * @ignore
185
+ */
186
+ export declare function clickElements(page: Page, selector: string, clickOptions?: ClickOptions): Promise<void>;
187
+ export {};
188
+ //# sourceMappingURL=click-elements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"click-elements.d.ts","sourceRoot":"","sources":["../../../src/internals/enqueue-links/click-elements.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,SAAS,EACT,cAAc,EACd,WAAW,EACX,gBAAgB,EAEhB,YAAY,EACZ,OAAO,EACV,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAGH,YAAY,EAGZ,IAAI,EAEJ,MAAM,EACT,MAAM,WAAW,CAAC;AAOnB,MAAM,WAAW,qCAAqC;IAClD;;OAEG;IACH,IAAI,EAAE,IAAI,CAAC;IAEX;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IAEpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IAExB;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAE9B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAE5C;;;;;;;;;;;;;;OAcG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,8BAA8B,CAAC,OAAO,EAAE,qCAAqC,GAAG,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAmE5I;AAED,UAAU,sBAAsB;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,UAAU,kDAAmD,SAAQ,sBAAsB;IACvF,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAsB,2CAA2C,CAAC,OAAO,EAAE,kDAAkD,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAiCpJ;AAoDD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGpE;AAiDD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB5G"}
@@ -0,0 +1,336 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clickElements = exports.isTargetRelevant = exports.clickElementsAndInterceptNavigationRequests = exports.enqueueLinksByClickingElements = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const browser_1 = require("@crawlee/browser");
6
+ const log_1 = tslib_1.__importDefault(require("@apify/log"));
7
+ const ow_1 = tslib_1.__importDefault(require("ow"));
8
+ const url_1 = require("url");
9
+ const puppeteer_request_interception_1 = require("../utils/puppeteer_request_interception");
10
+ const STARTING_Z_INDEX = 2147400000;
11
+ const log = log_1.default.child({ prefix: 'Puppeteer Click Elements' });
12
+ /**
13
+ * The function finds elements matching a specific CSS selector in a Puppeteer page,
14
+ * clicks all those elements using a mouse move and a left mouse button click and intercepts
15
+ * all the navigation requests that are subsequently produced by the page. The intercepted
16
+ * requests, including their methods, headers and payloads are then enqueued to a provided
17
+ * {@link RequestQueue}. This is useful to crawl JavaScript heavy pages where links are not available
18
+ * in `href` elements, but rather navigations are triggered in click handlers.
19
+ * If you're looking to find URLs in `href` attributes of the page, see {@link enqueueLinks}.
20
+ *
21
+ * Optionally, the function allows you to filter the target links' URLs using an array of {@link PseudoUrl} objects
22
+ * and override settings of the enqueued {@link Request} objects.
23
+ *
24
+ * **IMPORTANT**: To be able to do this, this function uses various mutations on the page,
25
+ * such as changing the Z-index of elements being clicked and their visibility. Therefore,
26
+ * it is recommended to only use this function as the last operation in the page.
27
+ *
28
+ * **USING HEADFUL BROWSER**: When using a headful browser, this function will only be able to click elements
29
+ * in the focused tab, effectively limiting concurrency to 1. In headless mode, full concurrency can be achieved.
30
+ *
31
+ * **PERFORMANCE**: Clicking elements with a mouse and intercepting requests is not a low level operation
32
+ * that takes nanoseconds. It's not very CPU intensive, but it takes time. We strongly recommend limiting
33
+ * the scope of the clicking as much as possible by using a specific selector that targets only the elements
34
+ * that you assume or know will produce a navigation. You can certainly click everything by using
35
+ * the `*` selector, but be prepared to wait minutes to get results on a large and complex page.
36
+ *
37
+ * **Example usage**
38
+ *
39
+ * ```javascript
40
+ * await Actor.utils.puppeteer.enqueueLinksByClickingElements({
41
+ * page,
42
+ * requestQueue,
43
+ * selector: 'a.product-detail',
44
+ * pseudoUrls: [
45
+ * 'https://www.example.com/handbags/[.*]'
46
+ * 'https://www.example.com/purses/[.*]'
47
+ * ],
48
+ * });
49
+ * ```
50
+ *
51
+ * @returns Promise that resolves to {@link BatchAddRequestsResult} object.
52
+ */
53
+ async function enqueueLinksByClickingElements(options) {
54
+ (0, ow_1.default)(options, ow_1.default.object.exactShape({
55
+ page: ow_1.default.object.hasKeys('goto', 'evaluate'),
56
+ requestQueue: ow_1.default.object.hasKeys('fetchNextRequest', 'addRequest'),
57
+ selector: ow_1.default.string,
58
+ clickOptions: ow_1.default.optional.object.hasKeys('clickCount', 'delay'),
59
+ pseudoUrls: ow_1.default.optional.array.ofType(ow_1.default.any(ow_1.default.string, ow_1.default.object.hasKeys('purl'))),
60
+ globs: ow_1.default.optional.array.ofType(ow_1.default.any(ow_1.default.string, ow_1.default.object.hasKeys('glob'))),
61
+ regexps: ow_1.default.optional.array.ofType(ow_1.default.any(ow_1.default.regExp, ow_1.default.object.hasKeys('regexp'))),
62
+ transformRequestFunction: ow_1.default.optional.function,
63
+ waitForPageIdleSecs: ow_1.default.optional.number,
64
+ maxWaitForPageIdleSecs: ow_1.default.optional.number,
65
+ }));
66
+ const { page, requestQueue, selector, clickOptions, pseudoUrls, globs, regexps, transformRequestFunction, waitForPageIdleSecs = 1, maxWaitForPageIdleSecs = 5, } = options;
67
+ const waitForPageIdleMillis = waitForPageIdleSecs * 1000;
68
+ const maxWaitForPageIdleMillis = maxWaitForPageIdleSecs * 1000;
69
+ const urlPatternObjects = [];
70
+ if (pseudoUrls?.length) {
71
+ log.deprecated('`pseudoUrls` option is deprecated, use `globs` or `regexps` instead');
72
+ urlPatternObjects.push(...(0, browser_1.constructRegExpObjectsFromPseudoUrls)(pseudoUrls));
73
+ }
74
+ if (globs?.length) {
75
+ urlPatternObjects.push(...(0, browser_1.constructGlobObjectsFromGlobs)(globs));
76
+ }
77
+ if (regexps?.length) {
78
+ urlPatternObjects.push(...(0, browser_1.constructRegExpObjectsFromRegExps)(regexps));
79
+ }
80
+ const interceptedRequests = await clickElementsAndInterceptNavigationRequests({
81
+ page,
82
+ selector,
83
+ waitForPageIdleMillis,
84
+ maxWaitForPageIdleMillis,
85
+ clickOptions,
86
+ });
87
+ let requestOptions = (0, browser_1.createRequestOptions)(interceptedRequests);
88
+ if (transformRequestFunction) {
89
+ requestOptions = requestOptions.map(transformRequestFunction).filter((r) => !!r);
90
+ }
91
+ const requests = (0, browser_1.createRequests)(requestOptions, urlPatternObjects);
92
+ return requestQueue.addRequests(requests);
93
+ }
94
+ exports.enqueueLinksByClickingElements = enqueueLinksByClickingElements;
95
+ /**
96
+ * Clicks all elements of given page matching given selector.
97
+ * Catches and intercepts all initiated navigation requests and opened pages.
98
+ * Returns a list of all target URLs.
99
+ * @ignore
100
+ */
101
+ async function clickElementsAndInterceptNavigationRequests(options) {
102
+ const { page, selector, waitForPageIdleMillis, maxWaitForPageIdleMillis, clickOptions, } = options;
103
+ const uniqueRequests = new Set();
104
+ const browser = page.browser();
105
+ const onInterceptedRequest = createInterceptRequestHandler(page, uniqueRequests);
106
+ const onTargetCreated = createTargetCreatedHandler(page, uniqueRequests);
107
+ const onFrameNavigated = createFrameNavigatedHandler(page, uniqueRequests);
108
+ await (0, puppeteer_request_interception_1.addInterceptRequestHandler)(page, onInterceptedRequest);
109
+ browser.on("targetcreated" /* TargetCreated */, onTargetCreated);
110
+ page.on("framenavigated" /* FrameNavigated */, onFrameNavigated);
111
+ await preventHistoryNavigation(page);
112
+ await clickElements(page, selector, clickOptions);
113
+ await waitForPageIdle({ page, waitForPageIdleMillis, maxWaitForPageIdleMillis });
114
+ await restoreHistoryNavigationAndSaveCapturedUrls(page, uniqueRequests);
115
+ browser.off("targetcreated" /* TargetCreated */, onTargetCreated);
116
+ page.off("framenavigated" /* FrameNavigated */, onFrameNavigated);
117
+ await (0, puppeteer_request_interception_1.removeInterceptRequestHandler)(page, onInterceptedRequest);
118
+ const serializedRequests = Array.from(uniqueRequests);
119
+ return serializedRequests.map((r) => JSON.parse(r));
120
+ }
121
+ exports.clickElementsAndInterceptNavigationRequests = clickElementsAndInterceptNavigationRequests;
122
+ /**
123
+ * @ignore
124
+ */
125
+ function createInterceptRequestHandler(page, requests) {
126
+ return async function onInterceptedRequest(req) {
127
+ if (!isTopFrameNavigationRequest(page, req))
128
+ return req.continue();
129
+ const url = req.url();
130
+ requests.add(JSON.stringify({
131
+ url,
132
+ headers: req.headers(),
133
+ method: req.method(),
134
+ payload: req.postData(),
135
+ }));
136
+ if (req.redirectChain().length) {
137
+ await req.respond({ body: '' }); // Prevents 301/302 redirect
138
+ }
139
+ else {
140
+ await req.abort('aborted'); // Prevents navigation by js
141
+ }
142
+ };
143
+ }
144
+ /**
145
+ * @ignore
146
+ */
147
+ function isTopFrameNavigationRequest(page, req) {
148
+ return req.isNavigationRequest()
149
+ && req.frame() === page.mainFrame();
150
+ }
151
+ /**
152
+ * @ignore
153
+ */
154
+ function createTargetCreatedHandler(page, requests) {
155
+ return async function onTargetCreated(target) {
156
+ if (!isTargetRelevant(page, target))
157
+ return;
158
+ const url = target.url();
159
+ requests.add(JSON.stringify({ url }));
160
+ // We want to close the page but don't care about
161
+ // possible errors like target closed.
162
+ try {
163
+ const createdPage = await target.page();
164
+ await createdPage.close();
165
+ }
166
+ catch (err) {
167
+ log.debug('enqueueLinksByClickingElements: Could not close spawned page.', { error: err.stack });
168
+ }
169
+ };
170
+ }
171
+ /**
172
+ * We're only interested in pages created by the page we're currently clicking in.
173
+ * There will generally be a lot of other targets being created in the browser.
174
+ */
175
+ function isTargetRelevant(page, target) {
176
+ return target.type() === 'page'
177
+ && page.target() === target.opener();
178
+ }
179
+ exports.isTargetRelevant = isTargetRelevant;
180
+ /**
181
+ * @ignore
182
+ */
183
+ function createFrameNavigatedHandler(page, requests) {
184
+ return function onFrameNavigated(frame) {
185
+ if (frame !== page.mainFrame())
186
+ return;
187
+ const url = frame.url();
188
+ requests.add(JSON.stringify({ url }));
189
+ };
190
+ }
191
+ /**
192
+ * @ignore
193
+ */
194
+ async function preventHistoryNavigation(page) {
195
+ /* istanbul ignore next */
196
+ return page.evaluate(() => {
197
+ window.__originalHistory__ = window.history; // eslint-disable-line no-underscore-dangle
198
+ delete window.history; // Simple override does not work.
199
+ window.history = {
200
+ stateHistory: [],
201
+ length: 0,
202
+ state: {},
203
+ go() { },
204
+ back() { },
205
+ forward() { },
206
+ pushState(...args) {
207
+ this.stateHistory.push(args);
208
+ },
209
+ replaceState(...args) {
210
+ this.stateHistory.push(args);
211
+ },
212
+ };
213
+ });
214
+ }
215
+ /**
216
+ * Click all elements matching the given selector. To be able to do this using
217
+ * Puppeteer's `.click()` we need to make sure the elements are reachable by mouse,
218
+ * so we first move them to the top of the page's stacking context and then click.
219
+ * We do all in series to prevent elements from hiding one another. Therefore,
220
+ * for large element sets, this will take considerable amount of time.
221
+ * @ignore
222
+ */
223
+ async function clickElements(page, selector, clickOptions) {
224
+ const elementHandles = await page.$$(selector);
225
+ log.debug(`enqueueLinksByClickingElements: There are ${elementHandles.length} elements to click.`);
226
+ let clickedElementsCount = 0;
227
+ let zIndex = STARTING_Z_INDEX;
228
+ let shouldLogWarning = true;
229
+ for (const handle of elementHandles) {
230
+ try {
231
+ await page.evaluate(updateElementCssToEnableMouseClick, handle, zIndex++);
232
+ await handle.click(clickOptions);
233
+ clickedElementsCount++;
234
+ }
235
+ catch (err) {
236
+ const e = err;
237
+ if (shouldLogWarning && e.stack.includes('is detached from document')) {
238
+ log.warning(`An element with selector ${selector} that you're trying to click has been removed from the page. `
239
+ + 'This was probably caused by an earlier click which triggered some JavaScript on the page that caused it to change. '
240
+ + 'If you\'re trying to enqueue pagination links, we suggest using the "next" button, if available and going one by one.');
241
+ shouldLogWarning = false;
242
+ }
243
+ log.debug('enqueueLinksByClickingElements: Click failed.', { stack: e.stack });
244
+ }
245
+ }
246
+ log.debug(`enqueueLinksByClickingElements: Successfully clicked ${clickedElementsCount} elements out of ${elementHandles.length}`);
247
+ }
248
+ exports.clickElements = clickElements;
249
+ /* istanbul ignore next */
250
+ /**
251
+ * This is an in browser function!
252
+ */
253
+ function updateElementCssToEnableMouseClick(el, zIndex) {
254
+ el.style.visibility = 'visible';
255
+ el.style.display = 'block';
256
+ el.style.position = 'fixed';
257
+ el.style.zIndex = String(zIndex);
258
+ el.style.left = '0';
259
+ el.style.top = '0';
260
+ const boundingRect = el.getBoundingClientRect();
261
+ if (!boundingRect.height)
262
+ el.style.height = '10px';
263
+ if (!boundingRect.width)
264
+ el.style.width = '10px';
265
+ }
266
+ /**
267
+ * This function tracks whether any requests, frame navigations or targets were emitted
268
+ * in the past idleIntervalMillis and whenever the interval registers no activity,
269
+ * the function returns.
270
+ *
271
+ * It will also return when a final timeout, represented by the timeoutMillis parameter
272
+ * is reached, to prevent blocking on pages with constant network activity.
273
+ *
274
+ * We need this to make sure we don't finish too soon when intercepting requests triggered
275
+ * by clicking in the page. They often get registered by the Node.js process only some
276
+ * milliseconds after clicking and we would lose those requests. This is especially prevalent
277
+ * when there's only a single element to click.
278
+ * @ignore
279
+ */
280
+ async function waitForPageIdle({ page, waitForPageIdleMillis, maxWaitForPageIdleMillis }) {
281
+ return new Promise((resolve) => {
282
+ let timeout;
283
+ let maxTimeout;
284
+ const context = page.browserContext();
285
+ function newTabTracker(target) {
286
+ if (isTargetRelevant(page, target))
287
+ activityHandler();
288
+ }
289
+ function activityHandler() {
290
+ clearTimeout(timeout);
291
+ timeout = setTimeout(() => {
292
+ clearTimeout(maxTimeout);
293
+ finish();
294
+ }, waitForPageIdleMillis);
295
+ }
296
+ function maxTimeoutHandler() {
297
+ log.debug(`enqueueLinksByClickingElements: Page still showed activity after ${maxWaitForPageIdleMillis}ms. `
298
+ + 'This is probably due to the website itself dispatching requests, but some links may also have been missed.');
299
+ finish();
300
+ }
301
+ function finish() {
302
+ page.off("request" /* Request */, activityHandler);
303
+ page.off("framenavigated" /* FrameNavigated */, activityHandler);
304
+ context.off("targetcreated" /* TargetCreated */, newTabTracker);
305
+ resolve();
306
+ }
307
+ maxTimeout = setTimeout(maxTimeoutHandler, maxWaitForPageIdleMillis);
308
+ activityHandler(); // We call this once manually in case there would be no requests at all.
309
+ page.on("request" /* Request */, activityHandler);
310
+ page.on("framenavigated" /* FrameNavigated */, activityHandler);
311
+ context.on("targetcreated" /* TargetCreated */, newTabTracker);
312
+ });
313
+ }
314
+ /**
315
+ * @ignore
316
+ */
317
+ async function restoreHistoryNavigationAndSaveCapturedUrls(page, requests) {
318
+ /* eslint-disable no-shadow */
319
+ /* istanbul ignore next */
320
+ const state = await page.evaluate(() => {
321
+ const { stateHistory } = window.history;
322
+ window.history = window.__originalHistory__; // eslint-disable-line no-underscore-dangle
323
+ return stateHistory;
324
+ });
325
+ state.forEach((args) => {
326
+ try {
327
+ const stateUrl = args[args.length - 1];
328
+ const url = new url_1.URL(stateUrl, page.url()).href;
329
+ requests.add(JSON.stringify({ url }));
330
+ }
331
+ catch (err) {
332
+ log.debug('enqueueLinksByClickingElements: Failed to ', { error: err.stack });
333
+ }
334
+ });
335
+ }
336
+ //# sourceMappingURL=click-elements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"click-elements.js","sourceRoot":"","sources":["../../../src/internals/enqueue-links/click-elements.ts"],"names":[],"mappings":"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"}