@opencraw/core 0.1.2 → 0.1.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.
- package/README.md +1 -1
- package/dist/access/access-broker.use-case.d.ts +43 -0
- package/dist/access/access-config.error.d.ts +5 -0
- package/dist/access/access-config.repository.d.ts +11 -0
- package/dist/access/access-json-schema.mapper.d.ts +8 -0
- package/dist/access/access-plugin.contract.d.ts +48 -0
- package/dist/access/access-preset.store.d.ts +19 -0
- package/dist/access/access-profile.contract.d.ts +95 -0
- package/dist/access/index.d.ts +11 -0
- package/dist/access/render-access.mapper.d.ts +41 -0
- package/dist/access/session-id.algorithm.d.ts +8 -0
- package/dist/api-steps/extract-from-document.use-case.d.ts +41 -0
- package/dist/api-steps/index.d.ts +4 -0
- package/dist/api-steps/run-api-step.use-case.d.ts +20 -0
- package/dist/api-steps/send-request.use-case.d.ts +23 -0
- package/dist/browser-session/browser-profile.store.d.ts +52 -0
- package/dist/browser-session/browser-session.config.d.ts +21 -0
- package/dist/browser-session/browser.client.d.ts +75 -0
- package/dist/browser-session/index.d.ts +6 -0
- package/dist/captcha/captcha-budget.model.d.ts +21 -0
- package/dist/captcha/captcha-detection.client.d.ts +28 -0
- package/dist/captcha/captcha-guard.use-case.d.ts +64 -0
- package/dist/captcha/captcha-solver-registry.store.d.ts +19 -0
- package/dist/captcha/captcha-solver.contract.d.ts +47 -0
- package/dist/captcha/captcha.error.d.ts +13 -0
- package/dist/captcha/index.d.ts +10 -0
- package/dist/captcha/resolve-captcha.use-case.d.ts +40 -0
- package/dist/crawl-events/crawl-event.contract.d.ts +169 -0
- package/dist/crawl-events/event-bus.store.d.ts +10 -0
- package/dist/crawl-events/index.d.ts +4 -0
- package/dist/crawl-events/trace-line.mapper.d.ts +14 -0
- package/dist/crawl-execution/bootstrap-session.use-case.d.ts +79 -0
- package/dist/crawl-execution/crawl-options.config.d.ts +67 -0
- package/dist/crawl-execution/crawl-report.model.d.ts +33 -0
- package/dist/crawl-execution/create-crawler.use-case.d.ts +20 -0
- package/dist/crawl-execution/index.d.ts +8 -0
- package/dist/crawl-execution/rotating-runner.use-case.d.ts +66 -0
- package/dist/crawl-execution/run-crawl.use-case.d.ts +17 -0
- package/dist/crawl-execution/run-input-recipe.use-case.d.ts +51 -0
- package/dist/deck-document/deck-document.model.d.ts +58 -0
- package/dist/deck-document/deck-table.algorithm.d.ts +35 -0
- package/dist/deck-document/index.d.ts +6 -0
- package/dist/deck-document/read-pptx.client.d.ts +16 -0
- package/dist/docx-document/index.d.ts +2 -0
- package/dist/docx-document/read-docx-html.client.d.ts +23 -0
- package/dist/extraction-scope/extraction-scope.model.d.ts +77 -0
- package/dist/extraction-scope/index.d.ts +5 -0
- package/dist/extraction-scope/live-element.model.d.ts +28 -0
- package/dist/hooks/hook-registry.store.d.ts +16 -0
- package/dist/hooks/hook.contract.d.ts +17 -0
- package/dist/hooks/hook.error.d.ts +7 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/http-session/http-response.contract.d.ts +58 -0
- package/dist/http-session/http.client.d.ts +42 -0
- package/dist/http-session/index.d.ts +5 -0
- package/dist/http-session/text-decoding.algorithm.d.ts +35 -0
- package/dist/index.esm.js +1410 -95
- package/dist/markdown-document/index.d.ts +3 -0
- package/dist/markdown-document/read-markdown.client.d.ts +39 -0
- package/dist/output-mapping/coerce-field.mapper.d.ts +19 -0
- package/dist/output-mapping/generated-field.mapper.d.ts +16 -0
- package/dist/output-mapping/index.d.ts +9 -0
- package/dist/output-mapping/map-record.use-case.d.ts +27 -0
- package/dist/output-mapping/mapping.error.d.ts +17 -0
- package/dist/output-mapping/missing-value.policy.d.ts +14 -0
- package/dist/output-mapping/output-field.validator.d.ts +10 -0
- package/dist/output-mapping/output-record.model.d.ts +20 -0
- package/dist/pdf-document/index.d.ts +7 -0
- package/dist/pdf-document/pdf-document.model.d.ts +51 -0
- package/dist/pdf-document/pdf-table.algorithm.d.ts +43 -0
- package/dist/pdf-document/read-pdf.client.d.ts +18 -0
- package/dist/pdf-document/row-assembly.algorithm.d.ts +26 -0
- package/dist/recipe-loading/index.d.ts +9 -0
- package/dist/recipe-loading/load-recipe-set.use-case.d.ts +45 -0
- package/dist/recipe-loading/read-recipe-source.use-case.d.ts +14 -0
- package/dist/recipe-loading/recipe-binding.error.d.ts +14 -0
- package/dist/recipe-loading/recipe-binding.validator.d.ts +34 -0
- package/dist/recipe-loading/recipe-file.repository.d.ts +11 -0
- package/dist/recipe-loading/recipe-set.model.d.ts +12 -0
- package/dist/recipe-loading/recipe-source.contract.d.ts +28 -0
- package/dist/recipe-loading/recipe-text.mapper.d.ts +14 -0
- package/dist/recipe-schema/index.d.ts +15 -0
- package/dist/recipe-schema/input-recipe.contract.d.ts +156 -0
- package/dist/recipe-schema/json-schema.mapper.d.ts +15 -0
- package/dist/recipe-schema/output-recipe.contract.d.ts +47 -0
- package/dist/recipe-schema/recipe-kind.enum.d.ts +35 -0
- package/dist/recipe-schema/recipe-validation.error.d.ts +17 -0
- package/dist/recipe-schema/recipe.validator.d.ts +28 -0
- package/dist/recipe-schema/step.contract.d.ts +206 -0
- package/dist/recipe-schema/transform-rule.contract.d.ts +120 -0
- package/dist/record-diff/index.d.ts +4 -0
- package/dist/record-diff/record-diff.algorithm.d.ts +82 -0
- package/dist/record-diff/records-file.repository.d.ts +10 -0
- package/dist/record-sink/dedupe.policy.d.ts +29 -0
- package/dist/record-sink/index.d.ts +9 -0
- package/dist/record-sink/json-lines-sink.repository.d.ts +19 -0
- package/dist/record-sink/memory-sink.repository.d.ts +9 -0
- package/dist/record-sink/record-sink.contract.d.ts +17 -0
- package/dist/selection/html-selector.algorithm.d.ts +19 -0
- package/dist/selection/index.d.ts +8 -0
- package/dist/selection/json-path.algorithm.d.ts +9 -0
- package/dist/selection/json-text.algorithm.d.ts +58 -0
- package/dist/selection/regex.algorithm.d.ts +12 -0
- package/dist/selection/take-value.mapper.d.ts +27 -0
- package/dist/src/access/access-profile.contract.d.ts +4 -0
- package/dist/src/access/index.d.ts +1 -1
- package/dist/src/api-steps/extract-from-document.use-case.d.ts +5 -5
- package/dist/src/api-steps/send-request.use-case.d.ts +3 -2
- package/dist/src/browser-session/browser-profile.store.d.ts +52 -0
- package/dist/src/browser-session/browser.client.d.ts +8 -0
- package/dist/src/browser-session/index.d.ts +1 -0
- package/dist/src/crawl-events/crawl-event.contract.d.ts +8 -0
- package/dist/src/crawl-execution/bootstrap-session.use-case.d.ts +23 -2
- package/dist/src/crawl-execution/crawl-options.config.d.ts +27 -0
- package/dist/src/crawl-execution/rotating-runner.use-case.d.ts +9 -0
- package/dist/src/crawl-execution/run-crawl.use-case.d.ts +6 -2
- package/dist/src/crawl-execution/run-input-recipe.use-case.d.ts +11 -3
- package/dist/src/docx-document/index.d.ts +2 -0
- package/dist/src/docx-document/read-docx-html.client.d.ts +23 -0
- package/dist/src/extraction-scope/extraction-scope.model.d.ts +2 -1
- package/dist/src/http-session/http-response.contract.d.ts +2 -1
- package/dist/src/index.d.ts +9 -4
- package/dist/src/markdown-document/index.d.ts +1 -1
- package/dist/src/markdown-document/read-markdown.client.d.ts +10 -0
- package/dist/src/recipe-schema/index.d.ts +2 -2
- package/dist/src/recipe-schema/input-recipe.contract.d.ts +24 -1
- package/dist/src/recipe-schema/recipe-kind.enum.d.ts +1 -1
- package/dist/src/recipe-schema/step.contract.d.ts +4 -0
- package/dist/src/record-diff/index.d.ts +4 -0
- package/dist/src/record-diff/record-diff.algorithm.d.ts +82 -0
- package/dist/src/record-diff/records-file.repository.d.ts +10 -0
- package/dist/src/record-sink/dedupe.policy.d.ts +19 -7
- package/dist/src/record-sink/index.d.ts +1 -0
- package/dist/src/selection/html-selector.algorithm.d.ts +2 -1
- package/dist/src/step-flow/for-each.use-case.d.ts +4 -2
- package/dist/src/step-flow/host-throttle.policy.d.ts +49 -0
- package/dist/src/step-flow/index.d.ts +5 -0
- package/dist/src/step-flow/run-gate.policy.d.ts +12 -1
- package/dist/src/step-flow/step-runner.contract.d.ts +13 -0
- package/dist/src/step-flow/transport-retry.policy.d.ts +76 -0
- package/dist/src/web-steps/navigate.use-case.d.ts +3 -2
- package/dist/src/web-steps/run-web-step.use-case.d.ts +8 -1
- package/dist/src/xml-document/index.d.ts +6 -0
- package/dist/src/xml-document/xml-document.model.d.ts +13 -0
- package/dist/src/xml-document/xml-parser.client.d.ts +49 -0
- package/dist/src/xml-document/xpath.algorithm.d.ts +30 -0
- package/dist/step-flow/block-rule.policy.d.ts +21 -0
- package/dist/step-flow/blocked.error.d.ts +9 -0
- package/dist/step-flow/for-each.use-case.d.ts +20 -0
- package/dist/step-flow/host-throttle.policy.d.ts +49 -0
- package/dist/step-flow/index.d.ts +15 -0
- package/dist/step-flow/paginate.use-case.d.ts +17 -0
- package/dist/step-flow/retry.policy.d.ts +21 -0
- package/dist/step-flow/run-gate.policy.d.ts +50 -0
- package/dist/step-flow/run-steps.use-case.d.ts +39 -0
- package/dist/step-flow/step-failure.error.d.ts +14 -0
- package/dist/step-flow/step-runner.contract.d.ts +52 -0
- package/dist/step-flow/transport-retry.policy.d.ts +76 -0
- package/dist/template/expression.algorithm.d.ts +53 -0
- package/dist/template/index.d.ts +7 -0
- package/dist/template/template.algorithm.d.ts +53 -0
- package/dist/template/value-path.algorithm.d.ts +29 -0
- package/dist/template/value-text.algorithm.d.ts +18 -0
- package/dist/transformation/apply-transform-chain.use-case.d.ts +17 -0
- package/dist/transformation/collection.algorithm.d.ts +15 -0
- package/dist/transformation/currency.algorithm.d.ts +15 -0
- package/dist/transformation/date.algorithm.d.ts +13 -0
- package/dist/transformation/index.d.ts +10 -0
- package/dist/transformation/lookup.algorithm.d.ts +24 -0
- package/dist/transformation/number.algorithm.d.ts +30 -0
- package/dist/transformation/string.algorithm.d.ts +18 -0
- package/dist/transformation/transform-registry.store.d.ts +36 -0
- package/dist/transformation/transform.error.d.ts +8 -0
- package/dist/transformation/url.algorithm.d.ts +20 -0
- package/dist/web-steps/evaluate-script.use-case.d.ts +10 -0
- package/dist/web-steps/extract-from-page.use-case.d.ts +10 -0
- package/dist/web-steps/index.d.ts +2 -0
- package/dist/web-steps/interact.use-case.d.ts +36 -0
- package/dist/web-steps/navigate.use-case.d.ts +15 -0
- package/dist/web-steps/run-web-step.use-case.d.ts +37 -0
- package/dist/web-steps/snapshot-elements.use-case.d.ts +13 -0
- package/dist/workbook-document/csv-parser.algorithm.d.ts +26 -0
- package/dist/workbook-document/csv-workbook.mapper.d.ts +24 -0
- package/dist/workbook-document/grid-table.algorithm.d.ts +53 -0
- package/dist/workbook-document/html-tables.mapper.d.ts +14 -0
- package/dist/workbook-document/index.d.ts +9 -0
- package/dist/workbook-document/read-xlsx.client.d.ts +18 -0
- package/dist/workbook-document/workbook-document.model.d.ts +51 -0
- package/dist/xml-document/index.d.ts +6 -0
- package/dist/xml-document/xml-document.model.d.ts +13 -0
- package/dist/xml-document/xml-parser.client.d.ts +49 -0
- package/dist/xml-document/xpath.algorithm.d.ts +30 -0
- package/dist/yaml-document/index.d.ts +3 -0
- package/dist/yaml-document/read-yaml.client.d.ts +25 -0
- package/package.json +4 -2
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { AccessLease } from '../access/index.js';
|
|
3
|
+
import type { EventBus } from '../crawl-events/index.js';
|
|
4
|
+
import type { CaptchaStep, InputRecipe } from '../recipe-schema/index.js';
|
|
5
|
+
import type { BlockedError } from '../step-flow/index.js';
|
|
6
|
+
import type { CaptchaBudget } from './captcha-budget.model.js';
|
|
7
|
+
import type { CaptchaSolverRegistry } from './captcha-solver-registry.store.js';
|
|
8
|
+
export interface CaptchaGuardOptions {
|
|
9
|
+
recipe: InputRecipe;
|
|
10
|
+
events: EventBus;
|
|
11
|
+
solvers: CaptchaSolverRegistry;
|
|
12
|
+
/** Shared by every runner of the recipe run, rotations and the bootstrap included. */
|
|
13
|
+
budget: CaptchaBudget;
|
|
14
|
+
/** The access the page goes through, handed to solvers. */
|
|
15
|
+
lease?: AccessLease;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Where a web runner meets captchas: after each navigation, click and key
|
|
19
|
+
* press (`session.captcha`), on a block page (`onBlock.solve`), and at a
|
|
20
|
+
* `captcha` step.
|
|
21
|
+
*/
|
|
22
|
+
export declare class CaptchaGuard {
|
|
23
|
+
private readonly options;
|
|
24
|
+
constructor(options: CaptchaGuardOptions);
|
|
25
|
+
private settings;
|
|
26
|
+
private solve;
|
|
27
|
+
/** Whether a block page is searched for a challenge before the block counts. */
|
|
28
|
+
get solvesBlocks(): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* The automatic check: with `session.captcha`, solves the challenge the page
|
|
31
|
+
* shows, if any. Without it, nothing is looked for.
|
|
32
|
+
*
|
|
33
|
+
* @param page - The live page.
|
|
34
|
+
* @throws CaptchaError when the challenge could not be solved.
|
|
35
|
+
*/
|
|
36
|
+
check(page: Page): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* A block page under `onBlock.solve`: solves the challenge it shows. A block
|
|
39
|
+
* without a challenge stays a block.
|
|
40
|
+
*
|
|
41
|
+
* @param page - The page showing the block.
|
|
42
|
+
* @param blocked - The block.
|
|
43
|
+
* @throws BlockedError (`blocked`) when the page shows no challenge; CaptchaError when it could not be solved.
|
|
44
|
+
*/
|
|
45
|
+
solveBlock(page: Page, blocked: BlockedError): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* A `captcha` step: solves the challenge the page shows, reCAPTCHA v3
|
|
48
|
+
* included; a page without one is fine.
|
|
49
|
+
*
|
|
50
|
+
* @param page - The live page.
|
|
51
|
+
* @param step - The step.
|
|
52
|
+
* @throws CaptchaError when the challenge could not be solved.
|
|
53
|
+
*/
|
|
54
|
+
step(page: Page, step: CaptchaStep): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Every solver name a recipe uses (`session.captcha` and its `captcha`
|
|
58
|
+
* steps, the bootstrap's included), to check them before the run starts.
|
|
59
|
+
*
|
|
60
|
+
* @param recipe - The input recipe.
|
|
61
|
+
* @returns The names, without repeats.
|
|
62
|
+
*/
|
|
63
|
+
export declare function captchaSolverNames(recipe: InputRecipe): string[];
|
|
64
|
+
//# sourceMappingURL=captcha-guard.use-case.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CaptchaSolver } from './captcha-solver.contract.js';
|
|
2
|
+
/** The captcha solvers a crawler was given, by name. */
|
|
3
|
+
export declare class CaptchaSolverRegistry {
|
|
4
|
+
private readonly solvers;
|
|
5
|
+
private readonly order;
|
|
6
|
+
constructor(solvers?: readonly CaptchaSolver[]);
|
|
7
|
+
/** The registered names. */
|
|
8
|
+
get names(): string[];
|
|
9
|
+
has(name: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The solver of that name.
|
|
12
|
+
*
|
|
13
|
+
* @param name - As a recipe names it.
|
|
14
|
+
* @returns The solver.
|
|
15
|
+
* @throws Error naming what is registered when it is not.
|
|
16
|
+
*/
|
|
17
|
+
resolve(name: string): CaptchaSolver;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=captcha-solver-registry.store.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { AccessLease } from '../access/index.js';
|
|
3
|
+
/** The kinds of challenge detection tells apart. */
|
|
4
|
+
export type CaptchaKind = 'recaptcha-v2' | 'recaptcha-v3' | 'hcaptcha' | 'turnstile' | 'image' | 'unknown';
|
|
5
|
+
/** What the engine found on the page: enough for a token service, or for a solver that works on the page itself. */
|
|
6
|
+
export interface CaptchaChallenge {
|
|
7
|
+
kind: CaptchaKind;
|
|
8
|
+
/** The page the challenge is on. */
|
|
9
|
+
url: string;
|
|
10
|
+
/** The widget's site key (`data-sitekey`, or the `k` / `sitekey` of its iframe), when it has one. */
|
|
11
|
+
siteKey?: string;
|
|
12
|
+
/** The widget's action (`data-action`), when it declares one. */
|
|
13
|
+
action?: string;
|
|
14
|
+
/** A Playwright selector for the widget, or for the image of an image captcha. */
|
|
15
|
+
selector?: string;
|
|
16
|
+
}
|
|
17
|
+
export type CaptchaLog = (level: 'debug' | 'info' | 'warn' | 'error', message: string, meta?: Record<string, unknown>) => void;
|
|
18
|
+
/** What a solver gets besides the challenge. */
|
|
19
|
+
export interface CaptchaContext {
|
|
20
|
+
/** The live page: the solver may inject a token, fill a field, click. */
|
|
21
|
+
page: Page;
|
|
22
|
+
/** The access in use: token services often need the same IP (proxy) as the browser. */
|
|
23
|
+
lease?: AccessLease;
|
|
24
|
+
/** 1, 2, … within one solve loop. */
|
|
25
|
+
attempt: number;
|
|
26
|
+
/** Aborted when the engine's timeout for this attempt runs out. */
|
|
27
|
+
signal: AbortSignal;
|
|
28
|
+
log: CaptchaLog;
|
|
29
|
+
}
|
|
30
|
+
/** A solver's report. The engine checks it: `solved` is a claim until the page confirms it. */
|
|
31
|
+
export type CaptchaOutcome = {
|
|
32
|
+
status: 'solved';
|
|
33
|
+
} | {
|
|
34
|
+
status: 'failed';
|
|
35
|
+
reason: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* A captcha solver: solves a challenge and applies the answer on the page
|
|
39
|
+
* (injects a token and calls the widget's callback, types an image's text,
|
|
40
|
+
* submits). Detection, verification, retries, rotation and the budget are the
|
|
41
|
+
* engine's.
|
|
42
|
+
*/
|
|
43
|
+
export interface CaptchaSolver {
|
|
44
|
+
name: string;
|
|
45
|
+
solve: (challenge: CaptchaChallenge, context: CaptchaContext) => Promise<CaptchaOutcome> | CaptchaOutcome;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=captcha-solver.contract.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BlockedError } from '../step-flow/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A challenge the engine could not get past: the solver failed, the page did
|
|
4
|
+
* not confirm it, or the budget ran out. It is a block, so a recipe with
|
|
5
|
+
* `onBlock.rotate` retries the step on a new access lease (a new IP often
|
|
6
|
+
* means an easier challenge, or none), then the step's error policy applies.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CaptchaError extends BlockedError {
|
|
9
|
+
readonly kind: string;
|
|
10
|
+
readonly attempts: number;
|
|
11
|
+
constructor(url: string, kind: string, attempts: number, reason: string);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=captcha.error.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { CaptchaSolver, CaptchaChallenge, CaptchaContext, CaptchaOutcome, CaptchaKind, CaptchaLog } from './captcha-solver.contract.js';
|
|
2
|
+
export { CaptchaError } from './captcha.error.js';
|
|
3
|
+
export { CaptchaSolverRegistry } from './captcha-solver-registry.store.js';
|
|
4
|
+
export { CaptchaBudget, DEFAULT_MAX_SOLVES } from './captcha-budget.model.js';
|
|
5
|
+
export { DEFAULT_CAPTCHA_SELECTOR, detectChallenge } from './captcha-detection.client.js';
|
|
6
|
+
export { resolveCaptcha, DEFAULT_CAPTCHA_ATTEMPTS, DEFAULT_CAPTCHA_TIMEOUT_MS } from './resolve-captcha.use-case.js';
|
|
7
|
+
export type { CaptchaAttemptPlan } from './resolve-captcha.use-case.js';
|
|
8
|
+
export { CaptchaGuard, captchaSolverNames } from './captcha-guard.use-case.js';
|
|
9
|
+
export type { CaptchaGuardOptions } from './captcha-guard.use-case.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { AccessLease } from '../access/index.js';
|
|
3
|
+
import type { EventBus } from '../crawl-events/index.js';
|
|
4
|
+
import type { CaptchaCheck } from '../recipe-schema/index.js';
|
|
5
|
+
import type { CaptchaBudget } from './captcha-budget.model.js';
|
|
6
|
+
import type { CaptchaChallenge, CaptchaSolver } from './captcha-solver.contract.js';
|
|
7
|
+
/** Default solves tried per challenge. */
|
|
8
|
+
export declare const DEFAULT_CAPTCHA_ATTEMPTS = 3;
|
|
9
|
+
/** Default time one solve may take: token services take 10 to 60 seconds. */
|
|
10
|
+
export declare const DEFAULT_CAPTCHA_TIMEOUT_MS = 120000;
|
|
11
|
+
/** One challenge to get past, and everything the loop needs for it. */
|
|
12
|
+
export interface CaptchaAttemptPlan {
|
|
13
|
+
recipeId: string;
|
|
14
|
+
page: Page;
|
|
15
|
+
challenge: CaptchaChallenge;
|
|
16
|
+
solver: CaptchaSolver;
|
|
17
|
+
/** Where challenges are, to re-detect and to confirm one is gone. */
|
|
18
|
+
selector: string;
|
|
19
|
+
verify?: CaptchaCheck;
|
|
20
|
+
attempts: number;
|
|
21
|
+
timeoutMs: number;
|
|
22
|
+
budget: CaptchaBudget;
|
|
23
|
+
events: EventBus;
|
|
24
|
+
lease?: AccessLease;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Gets past one challenge: asks the solver, then checks the page (a solver's
|
|
28
|
+
* `solved` is a claim; the challenge must be gone and/or the `verify` element
|
|
29
|
+
* must appear), and tries again with what the page shows next, up to
|
|
30
|
+
* `attempts`. Each try spends one solve of the run's budget.
|
|
31
|
+
*
|
|
32
|
+
* A failed try re-detects the challenge (a widget re-renders after a wrong
|
|
33
|
+
* answer). When it is gone without the page confirming, the page is reloaded
|
|
34
|
+
* for a fresh one; when a reload shows none, there is nothing left to solve.
|
|
35
|
+
*
|
|
36
|
+
* @param plan - The challenge, the solver and the limits.
|
|
37
|
+
* @throws CaptchaError when every try failed, or the budget is spent.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveCaptcha(plan: CaptchaAttemptPlan): Promise<void>;
|
|
40
|
+
//# sourceMappingURL=resolve-captcha.use-case.d.ts.map
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything a crawl reports while it runs. Payloads are structural on purpose:
|
|
3
|
+
* this slice is a leaf, so it declares its own shapes instead of importing the
|
|
4
|
+
* richer record and error types from the slices above it.
|
|
5
|
+
*/
|
|
6
|
+
interface Base {
|
|
7
|
+
at: string;
|
|
8
|
+
recipeId: string;
|
|
9
|
+
}
|
|
10
|
+
export type CrawlEvent = (Base & {
|
|
11
|
+
type: 'recipe:start';
|
|
12
|
+
mode: 'web' | 'api';
|
|
13
|
+
}) | (Base & {
|
|
14
|
+
type: 'recipe:finish';
|
|
15
|
+
emitted: number;
|
|
16
|
+
rejected: number;
|
|
17
|
+
duplicates: number;
|
|
18
|
+
skipped: number;
|
|
19
|
+
stepsSkipped?: number;
|
|
20
|
+
pages: number;
|
|
21
|
+
durationMs: number;
|
|
22
|
+
error?: string;
|
|
23
|
+
}) |
|
|
24
|
+
/** `status` is the HTTP status of the navigation or request, when there was a response. */
|
|
25
|
+
(Base & {
|
|
26
|
+
type: 'page:visit';
|
|
27
|
+
url: string;
|
|
28
|
+
number: number;
|
|
29
|
+
status?: number;
|
|
30
|
+
}) |
|
|
31
|
+
/** How a recipe run reaches the network. Never carries credentials. */
|
|
32
|
+
(Base & {
|
|
33
|
+
type: 'access:lease';
|
|
34
|
+
profile: string;
|
|
35
|
+
kind: string;
|
|
36
|
+
server?: string;
|
|
37
|
+
session?: string;
|
|
38
|
+
}) |
|
|
39
|
+
/** A response matched the recipe's block rule. */
|
|
40
|
+
(Base & {
|
|
41
|
+
type: 'access:blocked';
|
|
42
|
+
url: string;
|
|
43
|
+
status: number;
|
|
44
|
+
reason: string;
|
|
45
|
+
}) |
|
|
46
|
+
/** The run gave up its access lease after a block and is taking a new one. */
|
|
47
|
+
(Base & {
|
|
48
|
+
type: 'access:rotate';
|
|
49
|
+
attempt: number;
|
|
50
|
+
reason: string;
|
|
51
|
+
}) |
|
|
52
|
+
/** A request failed in passing (a dropped connection, a 503, a 429) and is sent again after `delayMs`. */
|
|
53
|
+
(Base & {
|
|
54
|
+
type: 'request:retry';
|
|
55
|
+
url: string;
|
|
56
|
+
attempt: number;
|
|
57
|
+
reason: string;
|
|
58
|
+
delayMs: number;
|
|
59
|
+
}) |
|
|
60
|
+
/** A captcha challenge is on the page. */
|
|
61
|
+
(Base & {
|
|
62
|
+
type: 'captcha:detected';
|
|
63
|
+
url: string;
|
|
64
|
+
kind: string;
|
|
65
|
+
siteKey?: string;
|
|
66
|
+
}) |
|
|
67
|
+
/** A solver is trying (`attempt` counts from 1 per challenge). */
|
|
68
|
+
(Base & {
|
|
69
|
+
type: 'captcha:solve';
|
|
70
|
+
url: string;
|
|
71
|
+
kind: string;
|
|
72
|
+
solver: string;
|
|
73
|
+
attempt: number;
|
|
74
|
+
}) |
|
|
75
|
+
/** The page confirmed the solve. */
|
|
76
|
+
(Base & {
|
|
77
|
+
type: 'captcha:solved';
|
|
78
|
+
url: string;
|
|
79
|
+
kind: string;
|
|
80
|
+
solver: string;
|
|
81
|
+
attempt: number;
|
|
82
|
+
durationMs: number;
|
|
83
|
+
}) |
|
|
84
|
+
/** The solver failed, timed out, or the page still shows the challenge. */
|
|
85
|
+
(Base & {
|
|
86
|
+
type: 'captcha:failed';
|
|
87
|
+
url: string;
|
|
88
|
+
kind: string;
|
|
89
|
+
solver: string;
|
|
90
|
+
attempt: number;
|
|
91
|
+
reason: string;
|
|
92
|
+
}) |
|
|
93
|
+
/** A challenge was left unsolved: the run spent its `maxSolves`. */
|
|
94
|
+
(Base & {
|
|
95
|
+
type: 'captcha:budget';
|
|
96
|
+
url: string;
|
|
97
|
+
kind: string;
|
|
98
|
+
max: number;
|
|
99
|
+
}) | (Base & {
|
|
100
|
+
type: 'step:start';
|
|
101
|
+
stepType: string;
|
|
102
|
+
stepId?: string;
|
|
103
|
+
path: string;
|
|
104
|
+
}) | (Base & {
|
|
105
|
+
type: 'step:finish';
|
|
106
|
+
stepType: string;
|
|
107
|
+
stepId?: string;
|
|
108
|
+
path: string;
|
|
109
|
+
durationMs: number;
|
|
110
|
+
}) | (Base & {
|
|
111
|
+
type: 'step:retry';
|
|
112
|
+
stepType: string;
|
|
113
|
+
stepId?: string;
|
|
114
|
+
path: string;
|
|
115
|
+
attempt: number;
|
|
116
|
+
error: string;
|
|
117
|
+
}) | (Base & {
|
|
118
|
+
type: 'step:skip';
|
|
119
|
+
stepType: string;
|
|
120
|
+
stepId?: string;
|
|
121
|
+
path: string;
|
|
122
|
+
error: string;
|
|
123
|
+
}) | (Base & {
|
|
124
|
+
type: 'step:branch';
|
|
125
|
+
path: string;
|
|
126
|
+
branch: 'then' | 'else';
|
|
127
|
+
}) |
|
|
128
|
+
/** `scope` (the snapshot the record was mapped from) is present only under `CrawlOptions.debug`. */
|
|
129
|
+
(Base & {
|
|
130
|
+
type: 'record:emit';
|
|
131
|
+
url: string;
|
|
132
|
+
key: string | null;
|
|
133
|
+
data: Record<string, unknown>;
|
|
134
|
+
scope?: Record<string, unknown>;
|
|
135
|
+
}) | (Base & {
|
|
136
|
+
type: 'record:reject';
|
|
137
|
+
url: string;
|
|
138
|
+
field: string;
|
|
139
|
+
reason: string;
|
|
140
|
+
scope?: Record<string, unknown>;
|
|
141
|
+
}) | (Base & {
|
|
142
|
+
type: 'record:duplicate';
|
|
143
|
+
url: string;
|
|
144
|
+
key: string;
|
|
145
|
+
}) |
|
|
146
|
+
/** A resumed run found the key already in the sink. */
|
|
147
|
+
(Base & {
|
|
148
|
+
type: 'record:skipped';
|
|
149
|
+
url: string;
|
|
150
|
+
key: string;
|
|
151
|
+
}) | (Base & {
|
|
152
|
+
type: 'warning';
|
|
153
|
+
message: string;
|
|
154
|
+
meta?: Record<string, unknown>;
|
|
155
|
+
}) | (Base & {
|
|
156
|
+
type: 'error';
|
|
157
|
+
message: string;
|
|
158
|
+
meta?: Record<string, unknown>;
|
|
159
|
+
});
|
|
160
|
+
export type CrawlEventType = CrawlEvent['type'];
|
|
161
|
+
/** An event without its timestamp; the bus stamps `at`. */
|
|
162
|
+
export type CrawlEventInput = {
|
|
163
|
+
[K in CrawlEventType]: Omit<Extract<CrawlEvent, {
|
|
164
|
+
type: K;
|
|
165
|
+
}>, 'at'>;
|
|
166
|
+
}[CrawlEventType];
|
|
167
|
+
export type CrawlListener = (event: CrawlEvent) => void;
|
|
168
|
+
export {};
|
|
169
|
+
//# sourceMappingURL=crawl-event.contract.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CrawlEventInput, CrawlListener } from './crawl-event.contract.js';
|
|
2
|
+
/** Fans crawl events out to listeners. A listener that throws never breaks the crawl. */
|
|
3
|
+
export declare class EventBus {
|
|
4
|
+
private readonly listeners;
|
|
5
|
+
constructor(listener?: CrawlListener);
|
|
6
|
+
/** @returns A function that removes the listener. */
|
|
7
|
+
subscribe(listener: CrawlListener): () => void;
|
|
8
|
+
emit(input: CrawlEventInput): void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=event-bus.store.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CrawlEvent } from './crawl-event.contract.js';
|
|
2
|
+
/**
|
|
3
|
+
* One line of a crawl trace: the route a recipe takes (pages visited, steps
|
|
4
|
+
* run, records produced, policies fired), indented by how deep in the step
|
|
5
|
+
* tree the event happened. `step:start` yields nothing; `step:finish` carries
|
|
6
|
+
* the duration, so every step prints once.
|
|
7
|
+
*
|
|
8
|
+
* @param event - Any crawl event.
|
|
9
|
+
* @returns The line, or `undefined` for events a trace does not show.
|
|
10
|
+
*/
|
|
11
|
+
export declare function traceLine(event: CrawlEvent): string | undefined;
|
|
12
|
+
/** How deep a step path such as `steps.8.steps.2` or `steps.1.else.0` sits: one level per nested `steps` or `else`. */
|
|
13
|
+
export declare function depthOf(path: string): number;
|
|
14
|
+
//# sourceMappingURL=trace-line.mapper.d.ts.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { AccessLease } from '../access/index.js';
|
|
2
|
+
import type { BrowserClient, BrowserProfiles, BrowserSession, SessionOptions, StorageState } from '../browser-session/index.js';
|
|
3
|
+
import type { CaptchaGuard } from '../captcha/index.js';
|
|
4
|
+
import type { EventBus } from '../crawl-events/index.js';
|
|
5
|
+
import type { HookRegistry } from '../hooks/index.js';
|
|
6
|
+
import type { InputRecipe } from '../recipe-schema/index.js';
|
|
7
|
+
import type { HostThrottle } from '../step-flow/index.js';
|
|
8
|
+
export interface BootstrapDependencies {
|
|
9
|
+
/** Launches (or returns) the shared browser; only called when a browser is needed. */
|
|
10
|
+
browser: () => Promise<BrowserClient>;
|
|
11
|
+
hooks: HookRegistry;
|
|
12
|
+
events: EventBus;
|
|
13
|
+
storageStateDir?: string;
|
|
14
|
+
/** The crawler's per-site throttle: the bootstrap's pages count too. */
|
|
15
|
+
hosts?: HostThrottle;
|
|
16
|
+
/** The runner's persistent browser profiles, for `session.browserProfile`. */
|
|
17
|
+
profiles?: BrowserProfiles;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The session options an access lease contributes: its proxy, TLS leniency,
|
|
21
|
+
* blocked resources, and its headers under the recipe's own.
|
|
22
|
+
*
|
|
23
|
+
* @param lease - The lease, if any.
|
|
24
|
+
* @param headers - The recipe's `session.headers`.
|
|
25
|
+
* @returns Options for `BrowserClient.newSession`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function accessOptions(lease: AccessLease | undefined, headers: Record<string, string> | undefined): Pick<SessionOptions, 'proxy' | 'ignoreHTTPSErrors' | 'blockResources' | 'headers'>;
|
|
28
|
+
/**
|
|
29
|
+
* The storage state a recipe starts from: a saved file, else what its
|
|
30
|
+
* `session.bootstrap` steps produce in a browser (filtered by `keep`, saved
|
|
31
|
+
* when asked), else nothing.
|
|
32
|
+
*
|
|
33
|
+
* The bootstrap runs through the same access lease as the crawl that follows,
|
|
34
|
+
* so a login and the requests that use its cookies come from one IP.
|
|
35
|
+
*
|
|
36
|
+
* With `session.browserProfile`, the bootstrap runs in that profile, and
|
|
37
|
+
* without a bootstrap the profile's own cookies and storage are the state: an
|
|
38
|
+
* api recipe picks up a login a browser left in the profile.
|
|
39
|
+
*
|
|
40
|
+
* @param recipe - The input recipe.
|
|
41
|
+
* @param deps - Browser, hooks, events.
|
|
42
|
+
* @param lease - The recipe run's access; direct when omitted.
|
|
43
|
+
* @param captcha - Solves the bootstrap's captchas (a login form's).
|
|
44
|
+
* @param owner - The recipe run, which a browser profile is held by.
|
|
45
|
+
* @returns The state, or `undefined` when the recipe declares none.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveStorageState(recipe: InputRecipe, deps: BootstrapDependencies, lease?: AccessLease, captcha?: CaptchaGuard, owner?: object): Promise<StorageState | undefined>;
|
|
48
|
+
/**
|
|
49
|
+
* Opens the recipe's `session.browserProfile` with its session options and
|
|
50
|
+
* the lease's proxy.
|
|
51
|
+
*
|
|
52
|
+
* @param recipe - A recipe with `session.browserProfile`.
|
|
53
|
+
* @param deps - For `profiles`.
|
|
54
|
+
* @param lease - The access lease.
|
|
55
|
+
* @param owner - The recipe run.
|
|
56
|
+
* @returns The session in the profile.
|
|
57
|
+
*/
|
|
58
|
+
export declare function openBrowserProfile(recipe: InputRecipe, deps: Pick<BootstrapDependencies, 'profiles'>, lease: AccessLease | undefined, owner: object): Promise<BrowserSession>;
|
|
59
|
+
/**
|
|
60
|
+
* The storage state saved by an earlier bootstrap (`session.storageStatePath`), if the recipe names one.
|
|
61
|
+
*
|
|
62
|
+
* @param recipe - The input recipe.
|
|
63
|
+
* @param deps - For `storageStateDir`.
|
|
64
|
+
* @returns The state, or `undefined`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function readSavedState(recipe: InputRecipe, deps: Pick<BootstrapDependencies, 'storageStateDir'>): Promise<StorageState | undefined>;
|
|
67
|
+
/**
|
|
68
|
+
* Runs a recipe's bootstrap steps in a browser session, then captures what
|
|
69
|
+
* `keep` lists and saves it when `saveTo` asks. The session stays open: a
|
|
70
|
+
* remote browser keeps it for the crawl, a local one is closed by the caller.
|
|
71
|
+
*
|
|
72
|
+
* @param recipe - An input recipe with `session.bootstrap`.
|
|
73
|
+
* @param browserSession - Where the steps run.
|
|
74
|
+
* @param deps - Hooks, events, `storageStateDir`.
|
|
75
|
+
* @param captcha - Solves the bootstrap's captchas.
|
|
76
|
+
* @returns The kept state.
|
|
77
|
+
*/
|
|
78
|
+
export declare function runBootstrap(recipe: InputRecipe, browserSession: BrowserSession, deps: Omit<BootstrapDependencies, 'browser'>, captcha?: CaptchaGuard): Promise<StorageState>;
|
|
79
|
+
//# sourceMappingURL=bootstrap-session.use-case.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { AccessConfig, AccessPlugin } from '../access/index.js';
|
|
2
|
+
import type { BrowserSessionConfig } from '../browser-session/index.js';
|
|
3
|
+
import type { CaptchaSolver } from '../captcha/index.js';
|
|
4
|
+
import type { CrawlListener } from '../crawl-events/index.js';
|
|
5
|
+
import type { HookMap } from '../hooks/index.js';
|
|
6
|
+
import type { ThrottleConfig } from '../step-flow/index.js';
|
|
7
|
+
import type { RetryRule } from '../recipe-schema/index.js';
|
|
8
|
+
import type { DedupeScope, RecordSink } from '../record-sink/index.js';
|
|
9
|
+
/** How a crawler is created. Everything is optional. */
|
|
10
|
+
export interface CrawlOptions {
|
|
11
|
+
/** Browser launch settings for web recipes and bootstraps. */
|
|
12
|
+
browser?: BrowserSessionConfig;
|
|
13
|
+
/** Handlers recipes reference by name. */
|
|
14
|
+
hooks?: HookMap;
|
|
15
|
+
/** Where records go; default: kept in memory and returned in the report. */
|
|
16
|
+
sink?: RecordSink;
|
|
17
|
+
onEvent?: CrawlListener;
|
|
18
|
+
/** Default `run`: a key seen once is dropped for the rest of the run. */
|
|
19
|
+
dedupe?: DedupeScope;
|
|
20
|
+
/**
|
|
21
|
+
* How many input recipes of a set run at once; default 1, one after
|
|
22
|
+
* another. Each has its own browser context or HTTP session; the browser,
|
|
23
|
+
* the sink and the per-site `throttle` are shared.
|
|
24
|
+
*/
|
|
25
|
+
parallel?: number;
|
|
26
|
+
/** Whether a failed input recipe stops the run; default `continue`. */
|
|
27
|
+
onRecipeError?: 'continue' | 'stop';
|
|
28
|
+
/** Base directory for relative `storageStatePath` and `saveTo` values. */
|
|
29
|
+
storageStateDir?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Where `session.browserProfile` profiles live, one directory each. Default:
|
|
32
|
+
* `.opencraw/profiles` under `storageStateDir` (or the working directory).
|
|
33
|
+
*/
|
|
34
|
+
profilesDir?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Skip records whose key the sink already has (`sink.has`), reporting them as
|
|
37
|
+
* `skipped`. Needs a sink that can answer, such as `jsonLinesSink(path, { append: true })`.
|
|
38
|
+
*/
|
|
39
|
+
resume?: boolean;
|
|
40
|
+
/** Attach the scope snapshot to `record:emit` and `record:reject` events, for inspecting what a mapping saw. */
|
|
41
|
+
debug?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Where traffic goes: named proxy profiles (presets for common providers,
|
|
44
|
+
* credentials as `{{env.NAME}}`) and the default one. Recipes pick a profile
|
|
45
|
+
* with `session.access.profile`. Without it every recipe goes direct.
|
|
46
|
+
*/
|
|
47
|
+
access?: AccessConfig;
|
|
48
|
+
/**
|
|
49
|
+
* How gently each site is crawled, across every recipe this crawler runs:
|
|
50
|
+
* `delayMs` between request starts and `concurrency` requests in flight,
|
|
51
|
+
* per site, with `domains` for site-specific rules. Defaults to
|
|
52
|
+
* `access.throttle`; without either, only each recipe's `limits` apply.
|
|
53
|
+
*/
|
|
54
|
+
throttle?: ThrottleConfig;
|
|
55
|
+
/**
|
|
56
|
+
* How a request that fails in passing (a dropped connection, a timeout, a
|
|
57
|
+
* 503, a 429) is sent again, for recipes whose `limits.retry` says
|
|
58
|
+
* nothing: `{ attempts?, backoffMs?, maxDelayMs?, statuses? }`. Default:
|
|
59
|
+
* three tries, one then two seconds apart, `Retry-After` honoured.
|
|
60
|
+
*/
|
|
61
|
+
retry?: RetryRule;
|
|
62
|
+
/** Plugins `{ kind: 'plugin', name }` profiles refer to. */
|
|
63
|
+
accessPlugins?: AccessPlugin[];
|
|
64
|
+
/** Solvers recipes name in `session.captcha.solver` and `captcha` steps. */
|
|
65
|
+
captchaSolvers?: CaptchaSolver[];
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=crawl-options.config.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { SinkSummary } from '../record-sink/index.js';
|
|
2
|
+
/** What one input recipe did. */
|
|
3
|
+
export interface RecipeReport {
|
|
4
|
+
recipeId: string;
|
|
5
|
+
mode: 'web' | 'api';
|
|
6
|
+
emitted: number;
|
|
7
|
+
rejected: number;
|
|
8
|
+
duplicates: number;
|
|
9
|
+
/** Records a resumed run found in the sink already. */
|
|
10
|
+
skipped: number;
|
|
11
|
+
/** Steps whose `onError: skip` policy swallowed a failure: a check that found nothing, a value a page lacked. */
|
|
12
|
+
stepsSkipped: number;
|
|
13
|
+
pages: number;
|
|
14
|
+
durationMs: number;
|
|
15
|
+
/** Captcha challenges met, solved, and solve attempts that failed; present when any was met. */
|
|
16
|
+
captchas?: {
|
|
17
|
+
detected: number;
|
|
18
|
+
solved: number;
|
|
19
|
+
failed: number;
|
|
20
|
+
};
|
|
21
|
+
/** Set when the recipe stopped on a failure. */
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
/** What a whole run did. */
|
|
25
|
+
export interface CrawlReport {
|
|
26
|
+
outputId: string;
|
|
27
|
+
recipes: RecipeReport[];
|
|
28
|
+
/** Records written to the sink across every recipe. */
|
|
29
|
+
records: number;
|
|
30
|
+
sink: SinkSummary;
|
|
31
|
+
durationMs: number;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=crawl-report.model.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RecipeSet } from '../recipe-loading/index.js';
|
|
2
|
+
import type { CrawlOptions } from './crawl-options.config.js';
|
|
3
|
+
import type { CrawlReport } from './crawl-report.model.js';
|
|
4
|
+
/** A configured engine: run recipe sets, then close it to release the browser. */
|
|
5
|
+
export interface Crawler {
|
|
6
|
+
run: (set: RecipeSet) => Promise<CrawlReport>;
|
|
7
|
+
/** Closes the browser if one was launched. Safe to call more than once. */
|
|
8
|
+
close: () => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates a crawler. The browser is launched lazily, on the first recipe or
|
|
12
|
+
* bootstrap that needs it, and shared by every run until `close`.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Hooks, sink, events, browser settings, access, captcha solvers, policies.
|
|
15
|
+
* @returns The crawler.
|
|
16
|
+
* @throws AccessConfigError when the access config cannot work.
|
|
17
|
+
* @throws Error when two captcha solvers share a name.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createCrawler(options?: CrawlOptions): Crawler;
|
|
20
|
+
//# sourceMappingURL=create-crawler.use-case.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createCrawler } from './create-crawler.use-case.js';
|
|
2
|
+
export type { Crawler } from './create-crawler.use-case.js';
|
|
3
|
+
export type { CrawlOptions } from './crawl-options.config.js';
|
|
4
|
+
export type { CrawlReport, RecipeReport } from './crawl-report.model.js';
|
|
5
|
+
export { runInputRecipe } from './run-input-recipe.use-case.js';
|
|
6
|
+
export { runCrawl } from './run-crawl.use-case.js';
|
|
7
|
+
export { resolveStorageState, readSavedState, runBootstrap } from './bootstrap-session.use-case.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|