@isdk/web-fetcher 0.3.0 → 0.3.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.
Files changed (83) hide show
  1. package/README.action.cn.md +53 -312
  2. package/README.action.extract.cn.md +263 -0
  3. package/README.action.extract.md +263 -0
  4. package/README.action.md +53 -311
  5. package/README.cn.md +10 -2
  6. package/README.engine.cn.md +22 -1
  7. package/README.engine.md +22 -1
  8. package/README.md +8 -1
  9. package/dist/index.d.mts +147 -1
  10. package/dist/index.d.ts +147 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.mjs +1 -1
  13. package/docs/README.md +8 -1
  14. package/docs/_media/README.action.md +53 -311
  15. package/docs/_media/README.cn.md +10 -2
  16. package/docs/_media/README.engine.md +22 -1
  17. package/docs/classes/CheerioFetchEngine.md +236 -88
  18. package/docs/classes/ClickAction.md +23 -23
  19. package/docs/classes/EvaluateAction.md +23 -23
  20. package/docs/classes/ExtractAction.md +23 -23
  21. package/docs/classes/FetchAction.md +27 -23
  22. package/docs/classes/FetchEngine.md +218 -86
  23. package/docs/classes/FetchSession.md +13 -13
  24. package/docs/classes/FillAction.md +23 -23
  25. package/docs/classes/GetContentAction.md +23 -23
  26. package/docs/classes/GotoAction.md +23 -23
  27. package/docs/classes/KeyboardPressAction.md +533 -0
  28. package/docs/classes/KeyboardTypeAction.md +533 -0
  29. package/docs/classes/MouseClickAction.md +533 -0
  30. package/docs/classes/MouseMoveAction.md +533 -0
  31. package/docs/classes/PauseAction.md +23 -23
  32. package/docs/classes/PlaywrightFetchEngine.md +337 -87
  33. package/docs/classes/SubmitAction.md +23 -23
  34. package/docs/classes/TrimAction.md +23 -23
  35. package/docs/classes/WaitForAction.md +23 -23
  36. package/docs/classes/WebFetcher.md +5 -5
  37. package/docs/enumerations/FetchActionResultStatus.md +4 -4
  38. package/docs/functions/fetchWeb.md +2 -2
  39. package/docs/globals.md +8 -0
  40. package/docs/interfaces/BaseFetchActionProperties.md +12 -12
  41. package/docs/interfaces/BaseFetchCollectorActionProperties.md +16 -16
  42. package/docs/interfaces/BaseFetcherProperties.md +31 -27
  43. package/docs/interfaces/Cookie.md +14 -14
  44. package/docs/interfaces/DispatchedEngineAction.md +4 -4
  45. package/docs/interfaces/EvaluateActionOptions.md +3 -3
  46. package/docs/interfaces/ExtractActionProperties.md +12 -12
  47. package/docs/interfaces/FetchActionInContext.md +15 -15
  48. package/docs/interfaces/FetchActionProperties.md +13 -13
  49. package/docs/interfaces/FetchActionResult.md +6 -6
  50. package/docs/interfaces/FetchContext.md +41 -37
  51. package/docs/interfaces/FetchEngineContext.md +36 -32
  52. package/docs/interfaces/FetchMetadata.md +5 -5
  53. package/docs/interfaces/FetchResponse.md +14 -14
  54. package/docs/interfaces/FetchReturnTypeRegistry.md +7 -7
  55. package/docs/interfaces/FetchSite.md +34 -30
  56. package/docs/interfaces/FetcherOptions.md +33 -29
  57. package/docs/interfaces/GotoActionOptions.md +14 -6
  58. package/docs/interfaces/KeyboardPressParams.md +25 -0
  59. package/docs/interfaces/KeyboardTypeParams.md +25 -0
  60. package/docs/interfaces/MouseClickParams.md +49 -0
  61. package/docs/interfaces/MouseMoveParams.md +41 -0
  62. package/docs/interfaces/PendingEngineRequest.md +3 -3
  63. package/docs/interfaces/StorageOptions.md +5 -5
  64. package/docs/interfaces/SubmitActionOptions.md +2 -2
  65. package/docs/interfaces/TrimActionOptions.md +3 -3
  66. package/docs/interfaces/WaitForActionOptions.md +5 -5
  67. package/docs/type-aliases/BaseFetchActionOptions.md +1 -1
  68. package/docs/type-aliases/BaseFetchCollectorOptions.md +1 -1
  69. package/docs/type-aliases/BrowserEngine.md +1 -1
  70. package/docs/type-aliases/FetchActionCapabilities.md +1 -1
  71. package/docs/type-aliases/FetchActionCapabilityMode.md +1 -1
  72. package/docs/type-aliases/FetchActionOptions.md +1 -1
  73. package/docs/type-aliases/FetchEngineAction.md +2 -2
  74. package/docs/type-aliases/FetchEngineType.md +1 -1
  75. package/docs/type-aliases/FetchReturnType.md +1 -1
  76. package/docs/type-aliases/FetchReturnTypeFor.md +1 -1
  77. package/docs/type-aliases/OnFetchPauseCallback.md +1 -1
  78. package/docs/type-aliases/ResourceType.md +1 -1
  79. package/docs/type-aliases/TrimPreset.md +1 -1
  80. package/docs/variables/DefaultFetcherProperties.md +1 -1
  81. package/docs/variables/FetcherOptionKeys.md +1 -1
  82. package/docs/variables/TRIM_PRESETS.md +1 -1
  83. package/package.json +10 -10
@@ -247,6 +247,52 @@ Retrieves the full content of the current page state.
247
247
  * **`params`**: (none)
248
248
  * **`returns`**: `response`
249
249
 
250
+ #### `mouseMove`
251
+
252
+ Moves the mouse cursor to a specific coordinate or element. In `browser` mode, it uses a **Bézier curve** to simulate a human-like non-linear trajectory with slight jitter for realism.
253
+
254
+ * **`id`**: `mouseMove`
255
+ * **`params`**:
256
+ * `x` (number, optional): The absolute X coordinate.
257
+ * `y` (number, optional): The absolute Y coordinate.
258
+ * `selector` (string, optional): A CSS selector. If provided, the mouse moves to the center of the element.
259
+ * `steps` (number, optional): The number of intermediate steps for the trajectory (default: `-1`). Set to `-1` to calculate steps automatically based on distance (simulating natural speed).
260
+ * **`returns`**: `none`
261
+
262
+ #### `mouseClick`
263
+
264
+ Triggers a mouse click at the current position or specified coordinates. If a `selector` is provided, the cursor will first move smoothly to the target element (using dynamic steps) before clicking.
265
+
266
+ * **`id`**: `mouseClick`
267
+ * **`params`**:
268
+ * `x` (number, optional): The absolute X coordinate to click.
269
+ * `y` (number, optional): The absolute Y coordinate to click.
270
+ * `selector` (string, optional): A CSS selector. If provided, moves the mouse to the element first.
271
+ * `button` (string, optional): The mouse button to use (`left`, `right`, or `middle`). Default is `left`.
272
+ * `clickCount` (number, optional): The number of clicks (e.g., 2 for double-click). Default is 1.
273
+ * `delay` (number, optional): Delay between mousedown and mouseup in milliseconds.
274
+ * **`returns`**: `none`
275
+
276
+ #### `keyboardType`
277
+
278
+ Simulates a person typing text into the currently focused element.
279
+
280
+ * **`id`**: `keyboardType`
281
+ * **`params`**:
282
+ * `text` (string): The text to type.
283
+ * `delay` (number, optional): The delay between key presses in milliseconds (default: 100).
284
+ * **`returns`**: `none`
285
+
286
+ #### `keyboardPress`
287
+
288
+ Simulates pressing a single key or a key combination (e.g., `Enter`, `Control+A`).
289
+
290
+ * **`id`**: `keyboardPress`
291
+ * **`params`**:
292
+ * `key` (string): The name of the key to press (e.g., `Enter`, `Tab`, `Backspace`, `ArrowUp`).
293
+ * `delay` (number, optional): The delay after the key press in milliseconds.
294
+ * **`returns`**: `none`
295
+
250
296
  #### `evaluate`
251
297
 
252
298
  Executes custom JavaScript code or an expression within the page context.
@@ -306,321 +352,17 @@ $`).
306
352
 
307
353
  #### `extract`
308
354
 
309
- Extracts structured data from the page using a powerful and declarative Schema. This is the core Action for data collection.
355
+ Extracts structured data from the page using a powerful and declarative Schema.
310
356
 
311
357
  * **`id`**: `extract`
312
- * **`params`**: An `ExtractSchema` object that defines the extraction rules.
313
- * **`returns`**: `any` (the extracted data)
314
-
315
- ##### Detailed Explanation of Extraction Schema
316
-
317
- The `params` object itself is a Schema that describes the data structure you want to extract.
318
-
319
- ###### 1. Extracting a Single Value
320
-
321
- The most basic extraction. You can specify a `selector` (CSS selector), an `attribute` (the name of the attribute to extract), a `type` (string, number, boolean, html), and a `mode` (text, innerText).
322
-
323
- * **`depth`** (number, optional): After matching the element with `selector`, it bubbles up the DOM tree by the specified number of levels. The resulting ancestor element becomes the actual target for value extraction (e.g., to extract an attribute from a parent wrapper).
324
-
325
- ```json
326
- {
327
- "id": "extract",
328
- "params": {
329
- "selector": "h1.main-title",
330
- "type": "string",
331
- "mode": "innerText"
332
- }
333
- }
334
- ```
335
-
336
- > **Extraction Modes:**
337
- >
338
- > * **`text`** (default): Extracts the `textContent` of the element.
339
- > * **`innerText`**: Extracts the rendered text, respecting CSS styling and line breaks.
340
- > * **`html`**: Returns the `innerHTML` of the element.
341
- > * **`outerHTML`**: Returns the HTML including the tag itself. Useful for preserving the full element structure.
342
- > The example above will extract the text content of the `<h1>` tag with the class `main-title` using the `innerText` mode.
343
-
344
- ###### 2. Extracting an Object
345
-
346
- Define a structured object using `type: 'object'` and the `properties` field.
347
-
348
- ```json
349
- {
350
- "id": "extract",
351
- "params": {
352
- "type": "object",
353
- "selector": ".author-bio",
354
- "properties": {
355
- "name": { "selector": ".author-name" },
356
- "email": { "selector": "a.email", "attribute": "href" }
357
- }
358
- }
359
- }
360
- ```
361
-
362
- * **`depth`** (number, optional): Enables "Try-And-Bubble" strategy. If a `required` field is missing in the matched element, the engine attempts to bubble up the DOM tree (up to `depth` levels) to find an ancestor where the required field exists. This is useful when the selector matches a descendant (e.g., an inner `span`) but the data resides on a parent container.
363
-
364
- **Advanced Object Features:**
365
-
366
- * **Anchor Jumping (`anchor`)**: Specifies a starting reference point for a field.
367
- * **Field Reference**: Use the DOM element of a previously extracted field.
368
- * **CSS Selector**: Query an anchor element on the fly within the object's scope.
369
- * **`depth`** (number, optional): When using an anchor, defines how many parent levels to traverse upwards to collect following siblings.
370
- * **Note**: If omitted, the engine defaults to maximum depth (up to the object's root) for backward compatibility. To strictly limit the search to the anchor's own siblings, set `depth: 0`.
371
- * **Effect**: Once an anchor is set, the search scope for that field becomes the siblings **following** the anchor (and its ancestors, depending on `depth`). This allows for non-linear "jumping" extraction in flat structures.
372
- * **Sequential Consumption (`relativeTo: "previous"`)**:
373
- * Combined with the `order` property, this ensures each field's search scope starts *after* the previous field's match.
374
- * Essential for extracting from lists composed of identical tags (e.g., consecutive `<p>` tags with different meanings).
375
-
376
- ###### 3. Extracting an Array (Convenient Usage)
377
-
378
- Extract a list using `type: 'array'`. To make the most common operations simpler, we provide some convenient usages.
379
-
380
- * **Extracting an Array of Texts (Default Behavior)**: When you want to extract a list of text, just provide the selector and omit `items`. This is the most common usage.
381
-
382
- ```json
383
- {
384
- "id": "extract",
385
- "params": {
386
- "type": "array",
387
- "selector": ".tags li"
388
- }
389
- }
390
- ```
391
-
392
- > The example above will return an array of the text from all `<li>` tags, e.g., `["tech", "news"]`.
393
-
394
- * **Extracting an Array of Attributes (Shortcut)**: When you only want to extract a list of attributes (e.g., all `href`s from links), there's no need to nest `items` either. Just declare `attribute` directly in the `array` definition.
395
-
396
- ```json
397
- {
398
- "id": "extract",
399
- "params": {
400
- "type": "array",
401
- "selector": ".gallery img",
402
- "attribute": "src"
403
- }
404
- }
405
- ```
406
-
407
- > The example above will return an array of the `src` attributes from all `<img>` tags.
408
-
409
- * **Array Extraction Modes**: When extracting an array, the engine supports different modes to handle various DOM structures.
410
-
411
- * **`nested`** (Default): The `selector` matches individual item wrappers.
412
- * **`columnar`** (formerly Zip): The `selector` matches a **container**, and fields in `items` are parallel columns stitched together by index.
413
- * **`segmented`**: The `selector` matches a **container**, and items are segmented by an "anchor" field.
414
-
415
- ###### 4. Columnar Mode (formerly Zip Strategy)
416
-
417
- This mode is used when the `selector` points to a **container** (like a results list) and item data is scattered as separate columns. It is highly optimized for performance, especially in browser mode, by minimizing the number of DOM queries and RPC calls.
418
-
419
- > **💡 Broadcasting & Performance**: If a property matches the container element itself (e.g. by omitting a selector or matching the container's own attributes), its value is **broadcasted** to every row. This is not only a feature but also a major performance optimization: the value is extracted **once** and reused across all rows, avoiding thousands of redundant engine calls.
420
-
421
- ```json
422
- {
423
- "id": "extract",
424
- "params": {
425
- "type": "array",
426
- "selector": "#search-results",
427
- "mode": "columnar",
428
- "items": {
429
- "title": { "selector": ".item-title" },
430
- "link": { "selector": "a.item-link", "attribute": "href" }
431
- }
432
- }
433
- }
434
- ```
435
-
436
- > **Heuristic Detection:** If `mode` is omitted and the `selector` matches exactly one element while `items` contains nested selectors, the engine automatically uses **columnar** mode.
358
+ * **`params`**: An `ExtractSchema` object.
359
+ * **`returns`**: The extracted structured data.
437
360
 
438
- **Example: Columnar Broadcasting**
439
-
440
- When you have a list where the category is on the container, but items are inside.
441
-
442
- ```json
443
- {
444
- "id": "extract",
445
- "params": {
446
- "type": "array",
447
- "selector": "#book-category",
448
- "mode": "columnar",
449
- "items": {
450
- "category": { "attribute": "data-category" },
451
- "title": { "selector": ".book-title" }
452
- }
453
- }
454
- }
455
- ```
456
-
457
- > If `#book-category` has `data-category="Sci-Fi"` and contains 3 books, the result will be 3 items, each having `"category": "Sci-Fi"`.
458
-
459
- **Columnar Configuration:**
460
-
461
- * **`strict`** (boolean, default: `true`): If `true`, throws an error if fields have different match counts.
462
- * **`inference`** (boolean, default: `false`): If `true`, tries to automatically find the "item wrapper" elements to fix misaligned lists. It uses an **optimized ancestor search** that is significantly faster in browser mode than manual traversal.
463
- * **Performance Note**: The engine automatically detects shared structures and pre-calculates alignment to ensure O(N) performance even in complex DOM trees. In browser mode, it minimizes IPC round-trips by pre-calculating "broadcast" flags.
464
-
465
- ###### 5. Segmented Mode (Anchor-based Scanning)
466
-
467
- Ideal for "flat" structures where there are no item wrappers. It uses a specified `anchor` to segment the container's content.
468
-
469
- **Core Feature: Automatic Container Detection (Bubble Up)**
470
-
471
- To handle structures that appear flat but have subtle containers, the engine uses a bubble-up strategy:
472
-
473
- - **Smart Bubble Up**: When an anchor is nested deep (e.g., `div.card > h3.title`), the engine automatically crawls up the DOM to find the largest "safe container" (e.g., `div.card`) that doesn't overlap with neighbors.
474
- - **Logical Isolation**: If a container is found, it becomes the scope for that segment. This allows you to extract any content within that container using simple relative selectors, even if it's "above" or deep alongside the anchor.
475
- - **Flat Fallback**: If no container isolation is possible, it automatically falls back to classic sibling scanning.
476
-
477
- ```json
478
- {
479
- "id": "extract",
480
- "params": {
481
- "type": "array",
482
- "selector": "#flat-container",
483
- "mode": { "type": "segmented", "anchor": "h3.item-title" },
484
- "items": {
485
- "title": { "selector": "h3" },
486
- "desc": { "selector": "p" }
487
- }
488
- }
489
- }
490
- ```
491
-
492
- **Segmented Configuration:**
493
-
494
- * **`anchor`** (string):
495
- * Can be a **field name** defined in `items` (e.g., `"title"`).
496
- * Can be a **direct CSS selector** (e.g., `"h3.item-title"`).
497
- * Defaults to the selector of the first field in `items`.
498
- * **`depth`** (number, optional): The maximum number of levels to bubble up from the anchor to find a segment container. If omitted, it bubbles up as high as possible without conflicting with neighboring segments.
499
- * **`strict`** (boolean, default: `false`): If `true`, throws an error if no anchor elements are found or if any item violates its own `required` constraints.
500
-
501
- ###### 5.1 Advanced: Handling Repeating Tags (`relativeTo`)
502
-
503
- When a segment contains multiple identical tags (e.g., several `<p>` tags in a row) representing different fields, use `relativeTo: "previous"` to "consume" them one by one.
504
-
505
- ```json
506
- {
507
- "id": "extract",
508
- "params": {
509
- "type": "array",
510
- "selector": "#container",
511
- "mode": {
512
- "type": "segmented",
513
- "anchor": ".item-start",
514
- "relativeTo": "previous"
515
- },
516
- "items": {
517
- "type": "object",
518
- "order": ["id", "desc", "extra"],
519
- "properties": {
520
- "id": "h1",
521
- "desc": "p",
522
- "extra": "p"
523
- }
524
- }
525
- }
526
- }
527
- ```
528
-
529
- * **`relativeTo: "previous"`**: After finding `id` (h1), the search for `desc` starts *after* that h1. After finding `desc` (the first p), the search for `extra` starts *after* that p, successfully picking up the second `<p>`.
530
- * **`order`**: Defines the sequence of consumption. Highly recommended with `relativeTo: "previous"`.
531
-
532
- ###### 6. Quality Control: `required` and `strict`
533
-
534
- - **`required`**: Marks a field as mandatory.
535
- - **In Objects**: If any required field is `null`, the entire object returns `null`.
536
- - **In Arrays**: Items missing a required field are automatically skipped.
537
- - **Null Propagation**: For implicit objects without a `selector`, if ALL sub-properties are `null`, the object itself becomes `null`, triggering parent-level required or skip logic.
538
- - **`strict`**:
539
- - `false` (Default): Silently skip or ignore incomplete data.
540
- - `true`: Throw an error on any missing required field or alignment mismatch.
541
- - **Inheritance**: Setting `strict: true` at the array level automatically propagates to all nested children.
542
-
543
- **Example: Ignoring items with missing mandatory fields**
544
-
545
- ```json
546
- {
547
- "id": "extract",
548
- "params": {
549
- "type": "array",
550
- "selector": ".product-list",
551
- "mode": "columnar",
552
- "items": {
553
- "name": { "selector": ".title", "required": true },
554
- "price": { "selector": ".price", "required": true },
555
- "discount": ".promo"
556
- }
557
- }
558
- }
559
- ```
560
-
561
- > In this example, if a product lacks either a `name` or a `price`, it will be completely omitted from the result array. The optional `discount` field doesn't affect the item's inclusion.
562
-
563
- ###### 7. Implicit Object Extraction (Simplest Syntax)
564
-
565
- For simpler object extraction, you can omit `type: 'object'` and `properties`. If the schema object contains keys that are not context-defining keywords (like `selector`, `has`, `exclude`, `required`, `strict`, `depth`), it is treated as an object schema where keys are property names.
566
-
567
- > **Keyword Collision Handling:** You can safely extract a data field named `type` as long as its value is not a reserved schema type (like `"string"`, `"object"`, `"array"`, etc.).
568
-
569
- ```json
570
- {
571
- "id": "extract",
572
- "params": {
573
- "selector": ".author-bio",
574
- "name": ".author-name",
575
- "type": ".author-rank",
576
- "items": { "type": "array", "selector": "li" }
577
- }
578
- }
579
- ```
580
-
581
- > **Key features of implicit objects:**
361
+ > **📚 Detailed Manual**: Because `extract` is very rich in features (including array modes, scope control, anchor jumping, etc.), we have prepared a dedicated detailed manual:
582
362
  >
583
- > 1. **Keyword Handling**: Common configuration keywords like `items`, `attribute`, or `mode` **can be used as property names** within an implicit object. They are only treated as configuration when a `type` (like `array`) is explicitly present. Configuration keywords like `required`, `strict`, and `depth` are also handled as context defining keys.
584
- > 2. **String Shorthand**: You can use a simple string as a property value (e.g., `"email": "a.email"`), which is automatically expanded to `{ "selector": "a.email" }`.
585
- > 3. **Context Separation**: Only `selector`, `has`, `exclude`, `required`, `strict`, and `depth` are used to define the context and validation for the implicit object; all other keys are treated as data to be extracted.
586
- > 4. **Null Propagation**: If an implicit object has no `selector` and ALL of its sub-properties extract to `null`, the object itself returns `null`. This is crucial for `required` validation on the parent object or for skipping items in an array.
587
-
588
- ###### 8. Advanced Filtering: `has` and `exclude`
589
-
590
- You can use the `has` and `exclude` fields in any schema that includes a `selector` to precisely control element selection.
591
-
592
- * `has`: A CSS selector to ensure the selected element **must contain** a descendant matching this selector.
593
- * `exclude`: A CSS selector to **exclude** elements matching this selector from the results.
594
-
595
- **Complete Example: Extracting links of articles that have an image and are not marked as "draft"**
596
-
597
- ```json
598
- {
599
- "actions": [
600
- { "id": "goto", "params": { "url": "https://example.com/articles" } },
601
- {
602
- "id": "extract",
603
- "params": {
604
- "type": "array",
605
- "selector": "div.article-card",
606
- "has": "img.cover-image",
607
- "exclude": ".draft",
608
- "items": {
609
- "selector": "a.title-link",
610
- "attribute": "href"
611
- }
612
- }
613
- }
614
- ]
615
- }
616
- ```
363
+ > 👉 **[Click to View Extract Action Deep Dive](./README.action.extract.md)**
617
364
 
618
- > The `extract` action above will:
619
- >
620
- > 1. Find all `div.article-card` elements.
621
- > 2. Filter them to only include those that contain an `<img class="cover-image">`.
622
- > 3. Further filter the results to exclude any that also have the `.draft` class.
623
- > 4. For each of the remaining `div.article-card` elements, find its descendant `a.title-link` and extract the `href` attribute.
365
+ ---
624
366
 
625
367
  ### Building High-Level Semantic Actions via "Composition"
626
368
 
@@ -800,7 +542,7 @@ In `@isdk/web-fetcher`, an Action's `static returnType` is more than a type hint
800
542
  * **Definition**: Any serializable data structure (Object, Array, string, etc.).
801
543
  * **Purpose**: Primary mechanism for business data extraction.
802
544
  * **Usage**: Use this when your action produces processed data that doesn't represent the whole page or system state.
803
- * **System Behavior**: If the action configuration includes `storeAs: "key"`, the framework automatically saves the `result` into `context.outputs["key"]`.
545
+ * **System Behavior**: If the action configuration includes `storeAs: "key"`, the framework automatically saves the `result` into `context.outputs["key"]`. If the target key already contains an object and the new result is also an object, they will be merged (shallow merge) instead of overwritten. This allows multiple `extract` actions to accumulate data into the same output key.
804
546
  * **Typical Actions**: `extract`.
805
547
  * **Example**:
806
548
 
@@ -20,9 +20,10 @@
20
20
  * **📜 声明式动作脚本**: 以简单、可读的 JSON 格式定义多步骤工作流(如登录、填写表单、点击按钮等)。
21
21
  * **📊 强大而灵活的数据提取**: 通过直观、强大的声明式 Schema,轻松提取从简单文本到复杂嵌套的各类结构化数据。
22
22
  * **🧠 智能引擎选择**: 可自动检测动态站点,并在需要时将引擎从 `http` 动态升级到 `browser`。
23
+ * **🛡️ 反爬虫/反屏蔽**: 在 `browser` 模式下,一个可选的 `antibot` 标志有助于绕过常见的反机器人措施,如 Cloudflare 挑战。
24
+ * **🕹️ 高仿真交互模拟**: 支持基于 **贝塞尔曲线** 的鼠标轨迹移动、真实的打字延迟模拟,以及复杂的键盘交互,大幅提升反爬避障能力。
23
25
  * **🧩 可扩展性**: 轻松创建自定义的、高级别的“组合动作”,以封装可复用的业务逻辑(例如,一个 `login` 动作)。
24
26
  * **🧲 高级收集器 (Collectors)**: 在主动作执行期间,由事件触发,在后台异步收集数据。
25
- * **🛡️ 反爬虫/反屏蔽**: 在 `browser` 模式下,一个可选的 `antibot` 标志有助于绕过常见的反机器人措施,如 Cloudflare 挑战。
26
27
 
27
28
  ---
28
29
 
@@ -145,6 +146,9 @@ searchGoogle('gemini');
145
146
  * `output` (object): 控制 `FetchResponse` 中的输出字段。
146
147
  * `cookies` (boolean): 是否在响应中包含 Cookie(默认:`true`)。
147
148
  * `sessionState` (boolean): 是否在响应中包含会话状态(默认:`true`)。
149
+ * `browser` (object): 浏览器引擎配置。
150
+ * `headless` (boolean): 是否以无头模式运行(默认:`true`)。
151
+ * `launchOptions` (object): Playwright 启动选项(例如 `{ slowMo: 50, args: [...] }`)。
148
152
  * `sessionPoolOptions` (SessionPoolOptions): 底层 Crawlee SessionPool 的高级配置。
149
153
  * ...以及许多其他用于代理、重试等的选项。
150
154
 
@@ -156,6 +160,10 @@ searchGoogle('gemini');
156
160
  * `click`: 点击选择器指定的元素(引擎相关)。
157
161
  * `fill`: 用指定值填充输入框(引擎相关)。
158
162
  * `submit`: 提交表单(引擎相关)。
163
+ * `mouseMove`: 将鼠标指针移动到指定的坐标或元素(支持贝塞尔曲线)。
164
+ * `mouseClick`: 在当前位置或指定坐标触发鼠标点击。
165
+ * `keyboardType`: 模拟真人在当前获得焦点的元素中输入文本。
166
+ * `keyboardPress`: 模拟按下单个按键或组合键。
159
167
  * `trim`: 从 DOM 中移除元素以清理页面(如脚本、广告、隐藏内容)。
160
168
  * `waitFor`: 暂停执行以等待特定条件(支持统一处理的固定超时)。
161
169
  * `pause`: 暂停执行以进行人工干预(如处理验证码,由核心层统一处理)。
@@ -174,7 +182,7 @@ searchGoogle('gemini');
174
182
  * `cookies`: Cookie 数组。
175
183
  * `sessionState`: Crawlee 会话状态。
176
184
  * `text`, `html`: 页面内容。
177
- * `outputs` (Record<string, any>): 通过 `storeAs` 提取并存储的数据。
185
+ * `outputs` (Record<string, any>): 通过 `storeAs` 提取并存储的数据。注意:当多个动作将对象存储到同一个键时,它们将被合并而不再是覆盖。
178
186
 
179
187
  ---
180
188
 
@@ -158,7 +158,7 @@ There are two primary engine implementations:
158
158
  * ✅ **Fast and Lightweight**: Ideal for speed and low resource consumption.
159
159
  * ✅ **HTTP-Compliant Redirects**: Correctly handles 301-303 and 307/308 redirects, preserving methods/bodies or converting to GET as per HTTP specifications.
160
160
  * ❌ **No JavaScript Execution**: Cannot interact with client-side rendered content.
161
- * ⚙️ **Simulated Interaction**: Actions like `click` and `submit` are simulated by making new HTTP requests.
161
+ * ⚙️ **Simulated Interaction**: Actions like `click` and `submit` are simulated by making new HTTP requests. **Browser-only actions** (e.g., `mouseMove`, `keyboardType`) will throw a `not_supported` error.
162
162
  * **Use Case**: Scraping static websites, server-rendered pages, or APIs.
163
163
 
164
164
  ### `PlaywrightFetchEngine` (browser mode)
@@ -183,6 +183,27 @@ To combat sophisticated anti-bot measures, the `PlaywrightFetchEngine` offers an
183
183
  * **Use Case**: Scraping websites protected by services like Cloudflare or other advanced bot-detection systems.
184
184
  * **Note**: This feature requires additional dependencies (`camoufox-js`, `firefox`) and may have a performance overhead.
185
185
 
186
+ #### Configuration
187
+
188
+ You can configure the browser engine via the `browser` property in options:
189
+
190
+ * `headless` (boolean): Whether to run browser in headless mode (default: `true`).
191
+ * `launchOptions` (object): Native Playwright [LaunchOptions](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) passed directly to the browser launcher (e.g., `slowMo`, `args`, `devtools`).
192
+
193
+ ```typescript
194
+ const result = await fetchWeb({
195
+ url: 'https://example.com',
196
+ engine: 'browser',
197
+ browser: {
198
+ headless: false,
199
+ launchOptions: {
200
+ slowMo: 100, // Slow down operations by 100ms
201
+ args: ['--start-maximized'] // Pass custom arguments
202
+ }
203
+ }
204
+ });
205
+ ```
206
+
186
207
  ---
187
208
 
188
209
  ## 📊 5. Data Extraction with `extract()`