@wenathlan/saddle 1.8.17 → 2.0.2
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/Dockerfile +1339 -0
- package/README.md +68 -22
- package/alternatives.ts +1218 -0
- package/biome.json +153 -0
- package/boards.json +1517 -0
- package/compute.ts +3144 -0
- package/cores.json +1801 -0
- package/dist/acquisition.d.ts +359 -0
- package/dist/acquisition.d.ts.map +1 -0
- package/dist/acquisition.js +629 -0
- package/dist/acquisition.js.map +1 -0
- package/dist/alternatives.d.ts +509 -0
- package/dist/alternatives.d.ts.map +1 -0
- package/dist/alternatives.js +951 -0
- package/dist/alternatives.js.map +1 -0
- package/dist/automation.d.ts +426 -0
- package/dist/automation.d.ts.map +1 -0
- package/dist/automation.js +561 -0
- package/dist/automation.js.map +1 -0
- package/dist/browser.d.ts +562 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +1057 -0
- package/dist/browser.js.map +1 -0
- package/dist/capacitor.config.d.ts +13 -0
- package/dist/capacitor.config.d.ts.map +1 -0
- package/dist/capacitor.config.js +26 -0
- package/dist/capacitor.config.js.map +1 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +111 -0
- package/dist/cli.js.map +1 -0
- package/dist/communication.d.ts +192 -0
- package/dist/communication.d.ts.map +1 -0
- package/dist/communication.js +418 -0
- package/dist/communication.js.map +1 -0
- package/dist/compute.d.ts +1161 -0
- package/dist/compute.d.ts.map +1 -0
- package/dist/compute.js +2273 -0
- package/dist/compute.js.map +1 -0
- package/dist/distribution.d.ts +529 -0
- package/dist/distribution.d.ts.map +1 -0
- package/dist/distribution.js +811 -0
- package/dist/distribution.js.map +1 -0
- package/dist/execution.d.ts +530 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +761 -0
- package/dist/execution.js.map +1 -0
- package/dist/format.d.ts +19 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +60 -0
- package/dist/format.js.map +1 -0
- package/dist/foundation.d.ts +176 -0
- package/dist/foundation.d.ts.map +1 -0
- package/dist/foundation.js +309 -0
- package/dist/foundation.js.map +1 -0
- package/dist/index.d.ts +733 -122
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1018 -122
- package/dist/index.js.map +1 -1
- package/dist/integration.d.ts +236 -0
- package/dist/integration.d.ts.map +1 -0
- package/dist/integration.js +236 -0
- package/dist/integration.js.map +1 -0
- package/dist/intelligence.d.ts +94 -0
- package/dist/intelligence.d.ts.map +1 -0
- package/dist/intelligence.js +145 -0
- package/dist/intelligence.js.map +1 -0
- package/dist/isolation.d.ts +129 -0
- package/dist/isolation.d.ts.map +1 -0
- package/dist/isolation.js +96 -0
- package/dist/isolation.js.map +1 -0
- package/dist/media.d.ts +344 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +986 -0
- package/dist/media.js.map +1 -0
- package/dist/modes.d.ts +359 -0
- package/dist/modes.d.ts.map +1 -0
- package/dist/modes.js +134 -0
- package/dist/modes.js.map +1 -0
- package/dist/{library/public.d.ts → operations.d.ts} +15 -1
- package/dist/operations.d.ts.map +1 -0
- package/dist/{library/public.js → operations.js} +18 -7
- package/dist/operations.js.map +1 -0
- package/dist/orchestrator.d.ts +1339 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +4308 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/performance.d.ts +416 -0
- package/dist/performance.d.ts.map +1 -0
- package/dist/performance.js +827 -0
- package/dist/performance.js.map +1 -0
- package/dist/quantum.d.ts +810 -0
- package/dist/quantum.d.ts.map +1 -0
- package/dist/quantum.js +2073 -0
- package/dist/quantum.js.map +1 -0
- package/dist/render.d.ts +381 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +1073 -0
- package/dist/render.js.map +1 -0
- package/dist/scheduler.d.ts +596 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +1259 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/security.d.ts +501 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +1170 -0
- package/dist/security.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/{server/node.js → server.js} +16 -2
- package/dist/server.js.map +1 -0
- package/dist/tiers.d.ts +1002 -0
- package/dist/tiers.d.ts.map +1 -0
- package/dist/tiers.js +2165 -0
- package/dist/tiers.js.map +1 -0
- package/dist/virtual.d.ts +641 -0
- package/dist/virtual.d.ts.map +1 -0
- package/dist/virtual.js +1285 -0
- package/dist/virtual.js.map +1 -0
- package/dist/virtualcpu.d.ts +316 -0
- package/dist/virtualcpu.d.ts.map +1 -0
- package/dist/virtualcpu.js +1180 -0
- package/dist/virtualcpu.js.map +1 -0
- package/dist/virtualgpu.d.ts +345 -0
- package/dist/virtualgpu.d.ts.map +1 -0
- package/dist/virtualgpu.js +1000 -0
- package/dist/virtualgpu.js.map +1 -0
- package/dist/virtualization.d.ts +607 -0
- package/dist/virtualization.d.ts.map +1 -0
- package/dist/virtualization.js +1187 -0
- package/dist/virtualization.js.map +1 -0
- package/dist/virtualmemory.d.ts +818 -0
- package/dist/virtualmemory.d.ts.map +1 -0
- package/dist/virtualmemory.js +1796 -0
- package/dist/virtualmemory.js.map +1 -0
- package/dist/webscrape.d.ts +720 -0
- package/dist/webscrape.d.ts.map +1 -0
- package/dist/webscrape.js +2697 -0
- package/dist/webscrape.js.map +1 -0
- package/docker.config +769 -0
- package/docs/CONVERSA.txt +1523 -0
- package/docs/alternatives.md +499 -0
- package/docs/architecture-1.8.19.md +76 -0
- package/docs/architecture-1.8.19.mmd +33 -0
- package/docs/architecture-1.8.19.png +0 -0
- package/docs/architecture.md +355 -0
- package/docs/artifactavailability.md +6 -0
- package/docs/brancharchive-2026-08-18.md +18 -0
- package/docs/browser.md +7 -0
- package/docs/consolidation.md +70 -0
- package/docs/e2ugh-engine.md +528 -0
- package/{dist/examples/localjob.js → docs/example-localjob.ts} +3 -3
- package/{dist/examples/publicapi.js → docs/example-publicapi.ts} +2 -2
- package/docs/hardware.md +342 -0
- package/docs/optimization.md +126 -0
- package/docs/performance.md +499 -0
- package/docs/planning.1.8.18.md +94 -0
- package/docs/planning.1.8.19.md +49 -0
- package/docs/releasenotes-1.8.17.md +6 -0
- package/docs/releasenotes-1.8.18.md +32 -0
- package/docs/releasenotes-1.8.19.md +35 -0
- package/docs/research-1.8.18-isolation.md +43 -0
- package/docs/research-1.8.19-virtual-browser.md +27 -0
- package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
- package/docs/security.md +454 -0
- package/docs/todo-1.8.16.md +56 -1
- package/docs/todo-1.8.18.md +164 -0
- package/docs/todo-1.8.19.md +241 -0
- package/docs/viability.md +777 -0
- package/docs/virtualization.md +335 -0
- package/docs/web-duplicatecleanup.md +9 -0
- package/docs/web-ideas.md +106 -0
- package/docs/workflowimprovements-2026-08-19.md +70 -0
- package/gpumonitor.cpp +1543 -0
- package/gpus.json +2408 -0
- package/index.ts +1478 -0
- package/media.ts +1337 -0
- package/mttg.config +1549 -0
- package/orchestrator.ts +5462 -0
- package/package.json +304 -55
- package/passage.config +1331 -0
- package/performance.ts +1049 -0
- package/processors.json +2217 -0
- package/qemu.config +1062 -0
- package/qemubridge.py +1340 -0
- package/quantum.ts +2393 -0
- package/render.ts +1325 -0
- package/scheduler.ts +1600 -0
- package/security.ts +1449 -0
- package/tiers.ts +2871 -0
- package/tsconfig.json +29 -0
- package/virtualcpu.ts +1273 -0
- package/virtualgpu.ts +1181 -0
- package/virtualhardware.c +1011 -0
- package/virtualhardware.json +739 -0
- package/virtualization.ts +1628 -0
- package/virtualizationcore.cpp +4635 -0
- package/virtualmemory.ts +2303 -0
- package/vm.config.json +1910 -0
- package/{extension → web/extension}/manifest.json +1 -1
- package/web/readme.md +382 -0
- package/web/tsconfig.json +25 -0
- package/dist/adapters/forge.d.ts +0 -17
- package/dist/adapters/forge.d.ts.map +0 -1
- package/dist/adapters/forge.js +0 -19
- package/dist/adapters/forge.js.map +0 -1
- package/dist/adapters/forgejo.d.ts +0 -49
- package/dist/adapters/forgejo.d.ts.map +0 -1
- package/dist/adapters/forgejo.js +0 -8
- package/dist/adapters/forgejo.js.map +0 -1
- package/dist/adapters/github.d.ts +0 -12
- package/dist/adapters/github.d.ts.map +0 -1
- package/dist/adapters/github.js +0 -20
- package/dist/adapters/github.js.map +0 -1
- package/dist/adapters/gitlab.d.ts +0 -17
- package/dist/adapters/gitlab.d.ts.map +0 -1
- package/dist/adapters/gitlab.js +0 -10
- package/dist/adapters/gitlab.js.map +0 -1
- package/dist/adapters/huggingface.d.ts +0 -17
- package/dist/adapters/huggingface.d.ts.map +0 -1
- package/dist/adapters/huggingface.js +0 -6
- package/dist/adapters/huggingface.js.map +0 -1
- package/dist/adapters/socket.d.ts +0 -11
- package/dist/adapters/socket.d.ts.map +0 -1
- package/dist/adapters/socket.js +0 -17
- package/dist/adapters/socket.js.map +0 -1
- package/dist/adapters/transport.d.ts +0 -7
- package/dist/adapters/transport.d.ts.map +0 -1
- package/dist/adapters/transport.js +0 -36
- package/dist/adapters/transport.js.map +0 -1
- package/dist/ai/chunk.d.ts +0 -2
- package/dist/ai/chunk.d.ts.map +0 -1
- package/dist/ai/chunk.js +0 -36
- package/dist/ai/chunk.js.map +0 -1
- package/dist/ai/llmstxt.d.ts +0 -6
- package/dist/ai/llmstxt.d.ts.map +0 -1
- package/dist/ai/llmstxt.js +0 -12
- package/dist/ai/llmstxt.js.map +0 -1
- package/dist/ai/provenance.d.ts +0 -22
- package/dist/ai/provenance.d.ts.map +0 -1
- package/dist/ai/provenance.js +0 -25
- package/dist/ai/provenance.js.map +0 -1
- package/dist/ai/rag.d.ts +0 -26
- package/dist/ai/rag.d.ts.map +0 -1
- package/dist/ai/rag.js +0 -22
- package/dist/ai/rag.js.map +0 -1
- package/dist/ai/tokens.d.ts +0 -15
- package/dist/ai/tokens.d.ts.map +0 -1
- package/dist/ai/tokens.js +0 -9
- package/dist/ai/tokens.js.map +0 -1
- package/dist/api/auth.d.ts +0 -16
- package/dist/api/auth.d.ts.map +0 -1
- package/dist/api/auth.js +0 -19
- package/dist/api/auth.js.map +0 -1
- package/dist/api/contracts.d.ts +0 -28
- package/dist/api/contracts.d.ts.map +0 -1
- package/dist/api/contracts.js +0 -14
- package/dist/api/contracts.js.map +0 -1
- package/dist/api/control.d.ts +0 -10
- package/dist/api/control.d.ts.map +0 -1
- package/dist/api/control.js +0 -35
- package/dist/api/control.js.map +0 -1
- package/dist/api/http.d.ts +0 -7
- package/dist/api/http.d.ts.map +0 -1
- package/dist/api/http.js +0 -12
- package/dist/api/http.js.map +0 -1
- package/dist/api/rate.d.ts +0 -28
- package/dist/api/rate.d.ts.map +0 -1
- package/dist/api/rate.js +0 -36
- package/dist/api/rate.js.map +0 -1
- package/dist/api/security.d.ts +0 -12
- package/dist/api/security.d.ts.map +0 -1
- package/dist/api/security.js +0 -56
- package/dist/api/security.js.map +0 -1
- package/dist/api/service.d.ts +0 -5
- package/dist/api/service.d.ts.map +0 -1
- package/dist/api/service.js +0 -70
- package/dist/api/service.js.map +0 -1
- package/dist/apps/registry.d.ts +0 -33
- package/dist/apps/registry.d.ts.map +0 -1
- package/dist/apps/registry.js +0 -24
- package/dist/apps/registry.js.map +0 -1
- package/dist/binary/archive.d.ts +0 -27
- package/dist/binary/archive.d.ts.map +0 -1
- package/dist/binary/archive.js +0 -46
- package/dist/binary/archive.js.map +0 -1
- package/dist/binary/build.d.ts +0 -29
- package/dist/binary/build.d.ts.map +0 -1
- package/dist/binary/build.js +0 -17
- package/dist/binary/build.js.map +0 -1
- package/dist/binary/transform.d.ts +0 -70
- package/dist/binary/transform.d.ts.map +0 -1
- package/dist/binary/transform.js +0 -105
- package/dist/binary/transform.js.map +0 -1
- package/dist/bot/adapter.d.ts +0 -5
- package/dist/bot/adapter.d.ts.map +0 -1
- package/dist/bot/adapter.js +0 -11
- package/dist/bot/adapter.js.map +0 -1
- package/dist/bot/bot.d.ts +0 -28
- package/dist/bot/bot.d.ts.map +0 -1
- package/dist/bot/bot.js +0 -52
- package/dist/bot/bot.js.map +0 -1
- package/dist/bot/commands.d.ts +0 -8
- package/dist/bot/commands.d.ts.map +0 -1
- package/dist/bot/commands.js +0 -19
- package/dist/bot/commands.js.map +0 -1
- package/dist/bot/permissions.d.ts +0 -13
- package/dist/bot/permissions.d.ts.map +0 -1
- package/dist/bot/permissions.js +0 -16
- package/dist/bot/permissions.js.map +0 -1
- package/dist/browser/actions.d.ts +0 -33
- package/dist/browser/actions.d.ts.map +0 -1
- package/dist/browser/actions.js +0 -44
- package/dist/browser/actions.js.map +0 -1
- package/dist/browser/agent.d.ts +0 -21
- package/dist/browser/agent.d.ts.map +0 -1
- package/dist/browser/agent.js +0 -13
- package/dist/browser/agent.js.map +0 -1
- package/dist/browser/context.d.ts +0 -43
- package/dist/browser/context.d.ts.map +0 -1
- package/dist/browser/context.js +0 -54
- package/dist/browser/context.js.map +0 -1
- package/dist/browser/fingerprint.d.ts +0 -4
- package/dist/browser/fingerprint.d.ts.map +0 -1
- package/dist/browser/fingerprint.js +0 -12
- package/dist/browser/fingerprint.js.map +0 -1
- package/dist/browser/index.d.ts +0 -11
- package/dist/browser/index.d.ts.map +0 -1
- package/dist/browser/index.js +0 -11
- package/dist/browser/index.js.map +0 -1
- package/dist/browser/playwright.d.ts +0 -11
- package/dist/browser/playwright.d.ts.map +0 -1
- package/dist/browser/playwright.js +0 -24
- package/dist/browser/playwright.js.map +0 -1
- package/dist/browser/recorder.d.ts +0 -21
- package/dist/browser/recorder.d.ts.map +0 -1
- package/dist/browser/recorder.js +0 -58
- package/dist/browser/recorder.js.map +0 -1
- package/dist/browser/session.d.ts +0 -14
- package/dist/browser/session.d.ts.map +0 -1
- package/dist/browser/session.js +0 -21
- package/dist/browser/session.js.map +0 -1
- package/dist/browser/snapshot.d.ts +0 -69
- package/dist/browser/snapshot.d.ts.map +0 -1
- package/dist/browser/snapshot.js +0 -133
- package/dist/browser/snapshot.js.map +0 -1
- package/dist/captcha/contract.d.ts +0 -35
- package/dist/captcha/contract.d.ts.map +0 -1
- package/dist/captcha/contract.js +0 -17
- package/dist/captcha/contract.js.map +0 -1
- package/dist/captcha/evidence.d.ts +0 -10
- package/dist/captcha/evidence.d.ts.map +0 -1
- package/dist/captcha/evidence.js +0 -9
- package/dist/captcha/evidence.js.map +0 -1
- package/dist/captcha/guard.d.ts +0 -23
- package/dist/captcha/guard.d.ts.map +0 -1
- package/dist/captcha/guard.js +0 -12
- package/dist/captcha/guard.js.map +0 -1
- package/dist/cli/main.d.ts +0 -4
- package/dist/cli/main.d.ts.map +0 -1
- package/dist/cli/main.js +0 -46
- package/dist/cli/main.js.map +0 -1
- package/dist/core/errors.d.ts +0 -84
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js +0 -54
- package/dist/core/errors.js.map +0 -1
- package/dist/core/events.d.ts +0 -9
- package/dist/core/events.d.ts.map +0 -1
- package/dist/core/events.js +0 -21
- package/dist/core/events.js.map +0 -1
- package/dist/core/hash.d.ts +0 -10
- package/dist/core/hash.d.ts.map +0 -1
- package/dist/core/hash.js +0 -82
- package/dist/core/hash.js.map +0 -1
- package/dist/core/ids.d.ts +0 -10
- package/dist/core/ids.d.ts.map +0 -1
- package/dist/core/ids.js +0 -15
- package/dist/core/ids.js.map +0 -1
- package/dist/delivery/manifest.d.ts +0 -35
- package/dist/delivery/manifest.d.ts.map +0 -1
- package/dist/delivery/manifest.js +0 -68
- package/dist/delivery/manifest.js.map +0 -1
- package/dist/deploy/index.d.ts +0 -6
- package/dist/deploy/index.d.ts.map +0 -1
- package/dist/deploy/index.js +0 -6
- package/dist/deploy/index.js.map +0 -1
- package/dist/dispatch/resumable.d.ts +0 -102
- package/dist/dispatch/resumable.d.ts.map +0 -1
- package/dist/dispatch/resumable.js +0 -64
- package/dist/dispatch/resumable.js.map +0 -1
- package/dist/dispatch/workflow.d.ts +0 -6
- package/dist/dispatch/workflow.d.ts.map +0 -1
- package/dist/dispatch/workflow.js +0 -37
- package/dist/dispatch/workflow.js.map +0 -1
- package/dist/domain/artifacts.d.ts +0 -12
- package/dist/domain/artifacts.d.ts.map +0 -1
- package/dist/domain/artifacts.js +0 -14
- package/dist/domain/artifacts.js.map +0 -1
- package/dist/domain/jobs.d.ts +0 -12
- package/dist/domain/jobs.d.ts.map +0 -1
- package/dist/domain/jobs.js +0 -20
- package/dist/domain/jobs.js.map +0 -1
- package/dist/domain/providers.d.ts +0 -10
- package/dist/domain/providers.d.ts.map +0 -1
- package/dist/domain/providers.js +0 -8
- package/dist/domain/providers.js.map +0 -1
- package/dist/domain/runtime.d.ts +0 -14
- package/dist/domain/runtime.d.ts.map +0 -1
- package/dist/domain/runtime.js +0 -10
- package/dist/domain/runtime.js.map +0 -1
- package/dist/domain/sessions.d.ts +0 -12
- package/dist/domain/sessions.d.ts.map +0 -1
- package/dist/domain/sessions.js +0 -57
- package/dist/domain/sessions.js.map +0 -1
- package/dist/examples/localjob.d.ts +0 -2
- package/dist/examples/localjob.d.ts.map +0 -1
- package/dist/examples/localjob.js.map +0 -1
- package/dist/examples/publicapi.d.ts +0 -2
- package/dist/examples/publicapi.d.ts.map +0 -1
- package/dist/examples/publicapi.js.map +0 -1
- package/dist/extension/build.d.ts +0 -9
- package/dist/extension/build.d.ts.map +0 -1
- package/dist/extension/build.js +0 -85
- package/dist/extension/build.js.map +0 -1
- package/dist/extension/content.d.ts +0 -6
- package/dist/extension/content.d.ts.map +0 -1
- package/dist/extension/content.js +0 -135
- package/dist/extension/content.js.map +0 -1
- package/dist/extension/index.d.ts +0 -7
- package/dist/extension/index.d.ts.map +0 -1
- package/dist/extension/index.js +0 -7
- package/dist/extension/index.js.map +0 -1
- package/dist/extension/pagebridge.d.ts +0 -6
- package/dist/extension/pagebridge.d.ts.map +0 -1
- package/dist/extension/pagebridge.js +0 -42
- package/dist/extension/pagebridge.js.map +0 -1
- package/dist/extension/permissions.d.ts +0 -26
- package/dist/extension/permissions.d.ts.map +0 -1
- package/dist/extension/permissions.js +0 -28
- package/dist/extension/permissions.js.map +0 -1
- package/dist/extension/popup.d.ts +0 -5
- package/dist/extension/popup.d.ts.map +0 -1
- package/dist/extension/popup.js +0 -26
- package/dist/extension/popup.js.map +0 -1
- package/dist/extension/protocol.d.ts +0 -58
- package/dist/extension/protocol.d.ts.map +0 -1
- package/dist/extension/protocol.js +0 -101
- package/dist/extension/protocol.js.map +0 -1
- package/dist/extension/serviceworker.d.ts +0 -25
- package/dist/extension/serviceworker.d.ts.map +0 -1
- package/dist/extension/serviceworker.js +0 -102
- package/dist/extension/serviceworker.js.map +0 -1
- package/dist/extension/worker.d.ts +0 -28
- package/dist/extension/worker.d.ts.map +0 -1
- package/dist/extension/worker.js +0 -22
- package/dist/extension/worker.js.map +0 -1
- package/dist/format/check.d.ts +0 -8
- package/dist/format/check.d.ts.map +0 -1
- package/dist/format/check.js +0 -38
- package/dist/format/check.js.map +0 -1
- package/dist/library/public.d.ts.map +0 -1
- package/dist/library/public.js.map +0 -1
- package/dist/mcp/browser.d.ts +0 -9
- package/dist/mcp/browser.d.ts.map +0 -1
- package/dist/mcp/browser.js +0 -13
- package/dist/mcp/browser.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -35
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js +0 -40
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/transport.d.ts +0 -7
- package/dist/mcp/transport.d.ts.map +0 -1
- package/dist/mcp/transport.js +0 -17
- package/dist/mcp/transport.js.map +0 -1
- package/dist/memory/bridge.d.ts +0 -14
- package/dist/memory/bridge.d.ts.map +0 -1
- package/dist/memory/bridge.js +0 -16
- package/dist/memory/bridge.js.map +0 -1
- package/dist/memory/engine.d.ts +0 -38
- package/dist/memory/engine.d.ts.map +0 -1
- package/dist/memory/engine.js +0 -109
- package/dist/memory/engine.js.map +0 -1
- package/dist/memory/modes.d.ts +0 -43
- package/dist/memory/modes.d.ts.map +0 -1
- package/dist/memory/modes.js +0 -66
- package/dist/memory/modes.js.map +0 -1
- package/dist/memory/objects.d.ts +0 -21
- package/dist/memory/objects.d.ts.map +0 -1
- package/dist/memory/objects.js +0 -20
- package/dist/memory/objects.js.map +0 -1
- package/dist/memory/planner.d.ts +0 -66
- package/dist/memory/planner.d.ts.map +0 -1
- package/dist/memory/planner.js +0 -108
- package/dist/memory/planner.js.map +0 -1
- package/dist/memory/targets.d.ts +0 -78
- package/dist/memory/targets.d.ts.map +0 -1
- package/dist/memory/targets.js +0 -29
- package/dist/memory/targets.js.map +0 -1
- package/dist/memory/transforms.d.ts +0 -19
- package/dist/memory/transforms.d.ts.map +0 -1
- package/dist/memory/transforms.js +0 -14
- package/dist/memory/transforms.js.map +0 -1
- package/dist/modes/matrix.d.ts +0 -23
- package/dist/modes/matrix.d.ts.map +0 -1
- package/dist/modes/matrix.js +0 -18
- package/dist/modes/matrix.js.map +0 -1
- package/dist/modes/modes.d.ts +0 -33
- package/dist/modes/modes.d.ts.map +0 -1
- package/dist/modes/modes.js +0 -15
- package/dist/modes/modes.js.map +0 -1
- package/dist/modes/resolve.d.ts +0 -96
- package/dist/modes/resolve.d.ts.map +0 -1
- package/dist/modes/resolve.js +0 -48
- package/dist/modes/resolve.js.map +0 -1
- package/dist/observability/metrics.d.ts +0 -14
- package/dist/observability/metrics.d.ts.map +0 -1
- package/dist/observability/metrics.js +0 -18
- package/dist/observability/metrics.js.map +0 -1
- package/dist/packager/manifest.d.ts +0 -66
- package/dist/packager/manifest.d.ts.map +0 -1
- package/dist/packager/manifest.js +0 -94
- package/dist/packager/manifest.js.map +0 -1
- package/dist/packager/publish.d.ts +0 -51
- package/dist/packager/publish.d.ts.map +0 -1
- package/dist/packager/publish.js +0 -18
- package/dist/packager/publish.js.map +0 -1
- package/dist/packager/targetcli.d.ts +0 -7
- package/dist/packager/targetcli.d.ts.map +0 -1
- package/dist/packager/targetcli.js +0 -22
- package/dist/packager/targetcli.js.map +0 -1
- package/dist/persistence/adapter.d.ts +0 -5
- package/dist/persistence/adapter.d.ts.map +0 -1
- package/dist/persistence/adapter.js +0 -11
- package/dist/persistence/adapter.js.map +0 -1
- package/dist/persistence/drizzle.d.ts +0 -2
- package/dist/persistence/drizzle.d.ts.map +0 -1
- package/dist/persistence/drizzle.js +0 -12
- package/dist/persistence/drizzle.js.map +0 -1
- package/dist/persistence/memory.d.ts +0 -2
- package/dist/persistence/memory.d.ts.map +0 -1
- package/dist/persistence/memory.js +0 -27
- package/dist/persistence/memory.js.map +0 -1
- package/dist/persistence/migrations.d.ts +0 -19
- package/dist/persistence/migrations.d.ts.map +0 -1
- package/dist/persistence/migrations.js +0 -13
- package/dist/persistence/migrations.js.map +0 -1
- package/dist/persistence/prisma.d.ts +0 -2
- package/dist/persistence/prisma.d.ts.map +0 -1
- package/dist/persistence/prisma.js +0 -25
- package/dist/persistence/prisma.js.map +0 -1
- package/dist/persistence/schema.d.ts +0 -63
- package/dist/persistence/schema.d.ts.map +0 -1
- package/dist/persistence/schema.js +0 -28
- package/dist/persistence/schema.js.map +0 -1
- package/dist/persistence/sql.d.ts +0 -3
- package/dist/persistence/sql.d.ts.map +0 -1
- package/dist/persistence/sql.js +0 -37
- package/dist/persistence/sql.js.map +0 -1
- package/dist/protocol/blocks.d.ts +0 -10
- package/dist/protocol/blocks.d.ts.map +0 -1
- package/dist/protocol/blocks.js +0 -26
- package/dist/protocol/blocks.js.map +0 -1
- package/dist/protocol/json.d.ts +0 -6
- package/dist/protocol/json.d.ts.map +0 -1
- package/dist/protocol/json.js +0 -6
- package/dist/protocol/json.js.map +0 -1
- package/dist/protocol/ndjson.d.ts +0 -3
- package/dist/protocol/ndjson.d.ts.map +0 -1
- package/dist/protocol/ndjson.js +0 -20
- package/dist/protocol/ndjson.js.map +0 -1
- package/dist/protocol/sse.d.ts +0 -7
- package/dist/protocol/sse.d.ts.map +0 -1
- package/dist/protocol/sse.js +0 -25
- package/dist/protocol/sse.js.map +0 -1
- package/dist/proxy/pool.d.ts +0 -9
- package/dist/proxy/pool.d.ts.map +0 -1
- package/dist/proxy/pool.js +0 -27
- package/dist/proxy/pool.js.map +0 -1
- package/dist/queue/idempotency.d.ts +0 -10
- package/dist/queue/idempotency.d.ts.map +0 -1
- package/dist/queue/idempotency.js +0 -13
- package/dist/queue/idempotency.js.map +0 -1
- package/dist/queue/persistent.d.ts +0 -14
- package/dist/queue/persistent.d.ts.map +0 -1
- package/dist/queue/persistent.js +0 -66
- package/dist/queue/persistent.js.map +0 -1
- package/dist/queue/queue.d.ts +0 -7
- package/dist/queue/queue.d.ts.map +0 -1
- package/dist/queue/queue.js +0 -55
- package/dist/queue/queue.js.map +0 -1
- package/dist/queue/saga.d.ts +0 -5
- package/dist/queue/saga.d.ts.map +0 -1
- package/dist/queue/saga.js +0 -20
- package/dist/queue/saga.js.map +0 -1
- package/dist/release/assets.d.ts +0 -144
- package/dist/release/assets.d.ts.map +0 -1
- package/dist/release/assets.js +0 -157
- package/dist/release/assets.js.map +0 -1
- package/dist/release/evidence.d.ts +0 -92
- package/dist/release/evidence.d.ts.map +0 -1
- package/dist/release/evidence.js +0 -148
- package/dist/release/evidence.js.map +0 -1
- package/dist/release/verify.d.ts +0 -12
- package/dist/release/verify.d.ts.map +0 -1
- package/dist/release/verify.js +0 -112
- package/dist/release/verify.js.map +0 -1
- package/dist/runners/chain.d.ts +0 -125
- package/dist/runners/chain.d.ts.map +0 -1
- package/dist/runners/chain.js +0 -95
- package/dist/runners/chain.js.map +0 -1
- package/dist/runners/health.d.ts +0 -36
- package/dist/runners/health.d.ts.map +0 -1
- package/dist/runners/health.js +0 -26
- package/dist/runners/health.js.map +0 -1
- package/dist/runners/heartbeat.d.ts +0 -23
- package/dist/runners/heartbeat.d.ts.map +0 -1
- package/dist/runners/heartbeat.js +0 -29
- package/dist/runners/heartbeat.js.map +0 -1
- package/dist/runners/inprocess.d.ts +0 -17
- package/dist/runners/inprocess.d.ts.map +0 -1
- package/dist/runners/inprocess.js +0 -20
- package/dist/runners/inprocess.js.map +0 -1
- package/dist/runners/scheduler.d.ts +0 -5
- package/dist/runners/scheduler.d.ts.map +0 -1
- package/dist/runners/scheduler.js +0 -19
- package/dist/runners/scheduler.js.map +0 -1
- package/dist/runtime/abort.d.ts +0 -8
- package/dist/runtime/abort.d.ts.map +0 -1
- package/dist/runtime/abort.js +0 -13
- package/dist/runtime/abort.js.map +0 -1
- package/dist/runtime/compatibility.d.ts +0 -37
- package/dist/runtime/compatibility.d.ts.map +0 -1
- package/dist/runtime/compatibility.js +0 -10
- package/dist/runtime/compatibility.js.map +0 -1
- package/dist/runtime/detect.d.ts +0 -13
- package/dist/runtime/detect.d.ts.map +0 -1
- package/dist/runtime/detect.js +0 -18
- package/dist/runtime/detect.js.map +0 -1
- package/dist/runtime/engine.d.ts +0 -20
- package/dist/runtime/engine.d.ts.map +0 -1
- package/dist/runtime/engine.js +0 -61
- package/dist/runtime/engine.js.map +0 -1
- package/dist/runtime/retry.d.ts +0 -19
- package/dist/runtime/retry.d.ts.map +0 -1
- package/dist/runtime/retry.js +0 -54
- package/dist/runtime/retry.js.map +0 -1
- package/dist/runtime/worker.d.ts +0 -10
- package/dist/runtime/worker.d.ts.map +0 -1
- package/dist/runtime/worker.js +0 -25
- package/dist/runtime/worker.js.map +0 -1
- package/dist/scrape/cache.d.ts +0 -45
- package/dist/scrape/cache.d.ts.map +0 -1
- package/dist/scrape/cache.js +0 -45
- package/dist/scrape/cache.js.map +0 -1
- package/dist/scrape/crawl.d.ts +0 -47
- package/dist/scrape/crawl.d.ts.map +0 -1
- package/dist/scrape/crawl.js +0 -114
- package/dist/scrape/crawl.js.map +0 -1
- package/dist/scrape/extract.d.ts +0 -63
- package/dist/scrape/extract.d.ts.map +0 -1
- package/dist/scrape/extract.js +0 -47
- package/dist/scrape/extract.js.map +0 -1
- package/dist/scrape/normalize.d.ts +0 -52
- package/dist/scrape/normalize.d.ts.map +0 -1
- package/dist/scrape/normalize.js +0 -102
- package/dist/scrape/normalize.js.map +0 -1
- package/dist/scrape/robots.d.ts +0 -37
- package/dist/scrape/robots.d.ts.map +0 -1
- package/dist/scrape/robots.js +0 -71
- package/dist/scrape/robots.js.map +0 -1
- package/dist/scrape/schema.d.ts +0 -23
- package/dist/scrape/schema.d.ts.map +0 -1
- package/dist/scrape/schema.js +0 -92
- package/dist/scrape/schema.js.map +0 -1
- package/dist/scrape/scraper.d.ts +0 -6
- package/dist/scrape/scraper.d.ts.map +0 -1
- package/dist/scrape/scraper.js +0 -46
- package/dist/scrape/scraper.js.map +0 -1
- package/dist/scrape/semantic.d.ts +0 -25
- package/dist/scrape/semantic.d.ts.map +0 -1
- package/dist/scrape/semantic.js +0 -27
- package/dist/scrape/semantic.js.map +0 -1
- package/dist/server/node.d.ts +0 -7
- package/dist/server/node.d.ts.map +0 -1
- package/dist/server/node.js.map +0 -1
- package/dist/sessions/file.d.ts +0 -25
- package/dist/sessions/file.d.ts.map +0 -1
- package/dist/sessions/file.js +0 -13
- package/dist/sessions/file.js.map +0 -1
- package/dist/sessions/replay.d.ts +0 -9
- package/dist/sessions/replay.d.ts.map +0 -1
- package/dist/sessions/replay.js +0 -70
- package/dist/sessions/replay.js.map +0 -1
- package/dist/sessions/store.d.ts +0 -25
- package/dist/sessions/store.d.ts.map +0 -1
- package/dist/sessions/store.js +0 -13
- package/dist/sessions/store.js.map +0 -1
- package/dist/storage/adapter.d.ts +0 -5
- package/dist/storage/adapter.d.ts.map +0 -1
- package/dist/storage/adapter.js +0 -11
- package/dist/storage/adapter.js.map +0 -1
- package/dist/storage/cache.d.ts +0 -23
- package/dist/storage/cache.d.ts.map +0 -1
- package/dist/storage/cache.js +0 -79
- package/dist/storage/cache.js.map +0 -1
- package/dist/storage/checksum.d.ts +0 -3
- package/dist/storage/checksum.d.ts.map +0 -1
- package/dist/storage/checksum.js +0 -19
- package/dist/storage/checksum.js.map +0 -1
- package/dist/storage/chunked.d.ts +0 -21
- package/dist/storage/chunked.d.ts.map +0 -1
- package/dist/storage/chunked.js +0 -67
- package/dist/storage/chunked.js.map +0 -1
- package/dist/storage/content.d.ts +0 -24
- package/dist/storage/content.d.ts.map +0 -1
- package/dist/storage/content.js +0 -44
- package/dist/storage/content.js.map +0 -1
- package/dist/storage/filehosting.d.ts +0 -2
- package/dist/storage/filehosting.d.ts.map +0 -1
- package/dist/storage/filehosting.js +0 -24
- package/dist/storage/filehosting.js.map +0 -1
- package/dist/storage/githubcontents.d.ts +0 -2
- package/dist/storage/githubcontents.d.ts.map +0 -1
- package/dist/storage/githubcontents.js +0 -29
- package/dist/storage/githubcontents.js.map +0 -1
- package/dist/storage/index.d.ts +0 -12
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js +0 -12
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/local.d.ts +0 -2
- package/dist/storage/local.d.ts.map +0 -1
- package/dist/storage/local.js +0 -72
- package/dist/storage/local.js.map +0 -1
- package/dist/storage/memory.d.ts +0 -6
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js +0 -36
- package/dist/storage/memory.js.map +0 -1
- package/dist/storage/pool.d.ts +0 -95
- package/dist/storage/pool.d.ts.map +0 -1
- package/dist/storage/pool.js +0 -202
- package/dist/storage/pool.js.map +0 -1
- package/dist/storage/s3compatible.d.ts +0 -3
- package/dist/storage/s3compatible.d.ts.map +0 -1
- package/dist/storage/s3compatible.js +0 -70
- package/dist/storage/s3compatible.js.map +0 -1
- package/dist/storage/sync.d.ts +0 -47
- package/dist/storage/sync.d.ts.map +0 -1
- package/dist/storage/sync.js +0 -75
- package/dist/storage/sync.js.map +0 -1
- package/dist/surfaces/adapters.d.ts +0 -97
- package/dist/surfaces/adapters.d.ts.map +0 -1
- package/dist/surfaces/adapters.js +0 -50
- package/dist/surfaces/adapters.js.map +0 -1
- package/dist/surfaces/controls.d.ts +0 -18
- package/dist/surfaces/controls.d.ts.map +0 -1
- package/dist/surfaces/controls.js +0 -45
- package/dist/surfaces/controls.js.map +0 -1
- package/dist/surfaces/manifest.d.ts +0 -68
- package/dist/surfaces/manifest.d.ts.map +0 -1
- package/dist/surfaces/manifest.js +0 -42
- package/dist/surfaces/manifest.js.map +0 -1
- package/dist/surfaces/n8n.d.ts +0 -25
- package/dist/surfaces/n8n.d.ts.map +0 -1
- package/dist/surfaces/n8n.js +0 -31
- package/dist/surfaces/n8n.js.map +0 -1
- package/dist/surfaces/operations.d.ts +0 -32
- package/dist/surfaces/operations.d.ts.map +0 -1
- package/dist/surfaces/operations.js +0 -53
- package/dist/surfaces/operations.js.map +0 -1
- package/dist/surfaces/requirements.d.ts +0 -29
- package/dist/surfaces/requirements.d.ts.map +0 -1
- package/dist/surfaces/requirements.js +0 -50
- package/dist/surfaces/requirements.js.map +0 -1
- package/dist/surfaces/targets.d.ts +0 -196
- package/dist/surfaces/targets.d.ts.map +0 -1
- package/dist/surfaces/targets.js +0 -27
- package/dist/surfaces/targets.js.map +0 -1
- package/dist/webhook/delivery.d.ts +0 -18
- package/dist/webhook/delivery.d.ts.map +0 -1
- package/dist/webhook/delivery.js +0 -36
- package/dist/webhook/delivery.js.map +0 -1
- package/dist/webhook/receiver.d.ts +0 -26
- package/dist/webhook/receiver.d.ts.map +0 -1
- package/dist/webhook/receiver.js +0 -24
- package/dist/webhook/receiver.js.map +0 -1
- package/dist/webhook/signature.d.ts +0 -3
- package/dist/webhook/signature.d.ts.map +0 -1
- package/dist/webhook/signature.js +0 -7
- package/dist/webhook/signature.js.map +0 -1
- package/dist/workflow/manifest.d.ts +0 -22
- package/dist/workflow/manifest.d.ts.map +0 -1
- package/dist/workflow/manifest.js +0 -21
- package/dist/workflow/manifest.js.map +0 -1
- package/dist/workflow/registry.d.ts +0 -7
- package/dist/workflow/registry.d.ts.map +0 -1
- package/dist/workflow/registry.js +0 -18
- package/dist/workflow/registry.js.map +0 -1
- package/dist/workflow/templates.d.ts +0 -6
- package/dist/workflow/templates.d.ts.map +0 -1
- package/dist/workflow/templates.js +0 -18
- package/dist/workflow/templates.js.map +0 -1
- package/dist/workflow/triggers.d.ts +0 -64
- package/dist/workflow/triggers.d.ts.map +0 -1
- package/dist/workflow/triggers.js +0 -99
- package/dist/workflow/triggers.js.map +0 -1
- package/docs/logs/.gitkeep +0 -0
- package/docs/plans/00.index.md +0 -50
- package/docs/plans/01.architecture.md +0 -86
- package/docs/plans/02.research.computer.use.md +0 -58
- package/docs/plans/03.research.captcha.bypass.md +0 -68
- package/docs/plans/04.research.sandbox.ai.md +0 -52
- package/docs/plans/05.capture.platform.md +0 -57
- package/docs/plans/06.dependencies.md +0 -97
- package/docs/plans/07.captcha.test.page.md +0 -41
- package/docs/plans/08.production.infra.md +0 -70
- package/docs/plans/09.database.schema.md +0 -121
- package/docs/plans/10.cloudinary.storage.md +0 -57
- package/docs/plans/11.movement.logs.json.md +0 -72
- package/docs/plans/12.research.atlas.agent.browser.md +0 -79
- package/docs/plans/13.research.anti.detection.md +0 -898
- package/docs/plans/14.research.proxy.md +0 -1495
- package/docs/plans/15.research.retry.rate.limit.md +0 -1958
- package/docs/plans/16.research.crawling.md +0 -1417
- package/docs/plans/17.research.caching.md +0 -1610
- package/docs/plans/18.research.content.extraction.md +0 -1952
- package/docs/plans/19.research.errors.events.md +0 -1523
- package/docs/plans/20.research.zod.validation.md +0 -1350
- package/docs/plans/21.research.batch.concurrency.md +0 -1888
- package/docs/plans/22.research.universal.runtime.md +0 -944
- package/docs/plans/23.research.ai.integration.md +0 -1465
- package/docs/plans/24.research.memory.persistence.md +0 -1979
- package/docs/plans/25.research.server.api.md +0 -342
- package/docs/plans/26.research.compilation.md +0 -249
- package/docs/plans/27.research.html.parsing.md +0 -251
- package/docs/plans/28.action.plan.md +0 -50
- package/docs/plans/29.api.reference.md +0 -174
- package/docs/plans/30.architecture.plan.md +0 -94
- package/docs/plans/31.auditoria.dados.md +0 -163
- package/docs/plans/32.bots.automacao.computacional.md +0 -214
- package/docs/plans/33.bots.codigo.revisao.md +0 -220
- package/docs/plans/34.bots.seguranca.cicd.md +0 -366
- package/docs/plans/35.comparativo.concorrencia.md +0 -464
- package/docs/plans/36.computational.memory.md +0 -340
- package/docs/plans/37.deploystrategy.md +0 -394
- package/docs/plans/38.flow.md +0 -155
- package/docs/plans/39.multi.platform.bot.md +0 -252
- package/docs/plans/40.npm.publish.md +0 -250
- package/docs/plans/41.o.que.falta.md +0 -407
- package/docs/plans/42.pesquisa.concorrencia.md +0 -721
- package/docs/plans/43.plan.universal.architecture.md +0 -496
- package/docs/plans/44.reference.md +0 -100
- package/docs/plans/45.robotarchitecture.md +0 -237
- package/docs/plans/46.scdnintegration.md +0 -284
- package/docs/plans/47.multiforge.readme.md +0 -129
- package/docs/plans/48.theory.v4.repo.os.md +0 -152
- package/docs/plans/49.third.party.infra.md +0 -12
- package/docs/plans/50.file.as.compute.md +0 -39
- package/docs/plans/51.architecture.virtual.processor.md +0 -80
- package/docs/plans/52.manifesto.v8.md +0 -11
- package/docs/plans/58.cdn.list.md +0 -23
- package/docs/plans/59.sql.frameworks.md +0 -33
- package/docs/plans/60.sql.thirdparty.md +0 -26
- package/docs/plans/61.objective.multiforge.md +0 -63
- package/docs/plans/62.huggingface.upload.md +0 -26
- package/docs/plans/63.kaggle.upload.md +0 -24
- package/docs/plans/64.npm.storage.md +0 -30
- package/docs/plans/65.rclone.terabox.md +0 -32
- package/docs/plans/66.buckets.and.models.todo.md +0 -14
- package/docs/plans/67.database.todo.md +0 -13
- package/docs/plans/68.deploy.packages.todo.md +0 -12
- package/docs/plans/69.report.human.operator.md +0 -133
- package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
- package/docs/plans/71.report.hd.infinito.vram.md +0 -155
- package/docs/plans/72.plan.hd.infinito.node.md +0 -146
- package/docs/plans/73.plan.scifi.repos.md +0 -125
- package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
- package/docs/plans/README.md +0 -489
- package/docs/plans/aggregate_platforms.mjs +0 -146
- package/docs/plans/examplesession.json +0 -36
- package/docs/plans/missing-facts.md +0 -192
- package/docs/plans/models.md +0 -64
- package/docs/plans/organize.cjs +0 -270
- package/docs/plans/platforms.md +0 -2887
- package/docs/plans/sites.md +0 -31322
- package/docs/sources/farm.py +0 -117
- package/docs/sources/html/saddle1.html +0 -132
- package/docs/sources/html/saddle2.html +0 -157
- package/docs/sources/html/saddle3.html +0 -119
- package/docs/sources/html/saddle4.html +0 -144
- package/docs/sources/html/saddle5.html +0 -72
- package/docs/sources/html/saddle6.html +0 -171
- package/docs/sources/html/saddle7.html +0 -236
- package/docs/sources/saddle.ts +0 -74
- package/docs/sources/schema.prisma +0 -88
- package/docs/sources/script.sh +0 -64
- package/docs/sources/workflows.yml +0 -458
- package/docs/talks1/_body.txt +0 -14
- package/docs/talks1/_index.md +0 -15
- package/docs/talks1/_screenshot.png +0 -0
- package/docs/talks1/assistant-01.md +0 -5
- package/docs/talks1/assistant-02.md +0 -5
- package/docs/talks1/assistant-03.md +0 -531
- package/docs/talks1/assistant-04.md +0 -26
- package/docs/talks1/assistant-05.md +0 -774
- package/docs/talks1/assistant-06.md +0 -1718
- package/docs/talks1/scrape-share.cjs +0 -185
- package/docs/talks1/scrape-share.ts +0 -183
- package/docs/talks1/user-01.md +0 -3
- package/docs/talks1/user-02.md +0 -3
- package/docs/talks1/user-03.md +0 -88
- package/docs/talks1/user-04.md +0 -3
- package/docs/talks1/user-05.md +0 -3
- package/docs/talks1/user-06.md +0 -88
- package/docs/talks1/user-07.md +0 -88
- package/docs/talks2/_body.txt +0 -14
- package/docs/talks2/_index.md +0 -16
- package/docs/talks2/_screenshot.png +0 -0
- package/docs/talks2/assistant-01.md +0 -5
- package/docs/talks2/assistant-02.md +0 -5
- package/docs/talks2/assistant-03.md +0 -424
- package/docs/talks2/assistant-04.md +0 -598
- package/docs/talks2/assistant-05.md +0 -1280
- package/docs/talks2/assistant-06.md +0 -1227
- package/docs/talks2/assistant-07.md +0 -1252
- package/docs/talks2/user-01.md +0 -3
- package/docs/talks2/user-02.md +0 -3
- package/docs/talks2/user-03.md +0 -88
- package/docs/talks2/user-04.md +0 -88
- package/docs/talks2/user-05.md +0 -88
- package/docs/talks2/user-06.md +0 -88
- package/docs/talks2/user-07.md +0 -3
- package/docs/talks3/_body.txt +0 -467
- package/docs/talks3/_index.md +0 -10
- package/docs/talks3/_screenshot.png +0 -0
- package/docs/talks3/assistant-01.md +0 -417
- package/docs/talks3/assistant-02.md +0 -417
- package/docs/talks3/assistant-03.md +0 -29
- package/docs/talks3/assistant-04.md +0 -727
- package/docs/talks3/user-01.md +0 -88
- package/docs/talks3/user-02.md +0 -88
- package/docs/talks3/user-03.md +0 -3
- package/docs/talks3/user-04.md +0 -3
- package/docs/talks4/_body.txt +0 -14
- package/docs/talks4/_index.md +0 -12
- package/docs/talks4/_screenshot.png +0 -0
- package/docs/talks4/assistant-01.md +0 -5
- package/docs/talks4/assistant-02.md +0 -5
- package/docs/talks4/assistant-03.md +0 -35
- package/docs/talks4/assistant-04.md +0 -512
- package/docs/talks4/assistant-05.md +0 -599
- package/docs/talks4/user-01.md +0 -3
- package/docs/talks4/user-02.md +0 -3
- package/docs/talks4/user-03.md +0 -88
- package/docs/talks4/user-04.md +0 -88
- package/docs/talks4/user-05.md +0 -7
- package/docs/talks5/_body.txt +0 -14
- package/docs/talks5/_index.md +0 -13
- package/docs/talks5/_screenshot.png +0 -0
- package/docs/talks5/assistant-01.md +0 -5
- package/docs/talks5/assistant-02.md +0 -5
- package/docs/talks5/assistant-03.md +0 -690
- package/docs/talks5/assistant-04.md +0 -758
- package/docs/talks5/assistant-05.md +0 -974
- package/docs/talks5/user-01.md +0 -3
- package/docs/talks5/user-02.md +0 -3
- package/docs/talks5/user-03.md +0 -105
- package/docs/talks5/user-04.md +0 -105
- package/docs/talks5/user-05.md +0 -63
- package/docs/talks5/user-06.md +0 -105
- package/docs/talks6/_body.txt +0 -14
- package/docs/talks6/_index.md +0 -9
- package/docs/talks6/_screenshot.png +0 -0
- package/docs/talks6/assistant-01.md +0 -5
- package/docs/talks6/assistant-02.md +0 -5
- package/docs/talks6/assistant-03.md +0 -1499
- package/docs/talks6/user-01.md +0 -3
- package/docs/talks6/user-02.md +0 -3
- package/docs/talks6/user-03.md +0 -88
- package/docs/talks6/user-04.md +0 -88
- package/docs/talks7/_body.txt +0 -14
- package/docs/talks7/_index.md +0 -10
- package/docs/talks7/_screenshot.png +0 -0
- package/docs/talks7/assistant-01.md +0 -5
- package/docs/talks7/assistant-02.md +0 -5
- package/docs/talks7/assistant-03.md +0 -523
- package/docs/talks7/assistant-04.md +0 -617
- package/docs/talks7/user-01.md +0 -3
- package/docs/talks7/user-02.md +0 -3
- package/docs/talks7/user-03.md +0 -105
- package/docs/talks7/user-04.md +0 -67
- package/docs/talks8/conversa1.txt +0 -1322
- package/docs/talks8/conversa2.txt +0 -237
- package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +0 -174
- package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +0 -59
- package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +0 -91
- package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +0 -116
- package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +0 -128
- package/docs/talks9/README (2).md +0 -489
- package/docs/talks9/README.md +0 -198
- package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +0 -80
- package/docs/talks9/conversa.txt +0 -544
- package/docs/talks9/other (2).md +0 -39
- package/docs/talks9/other.md +0 -57
- package/docs/talks9/outro.txt +0 -24
- /package/{extension/README.md → docs/extension.md} +0 -0
|
@@ -1,1495 +0,0 @@
|
|
|
1
|
-
# Pesquisa: Proxy Rotation e Management (2026)
|
|
2
|
-
|
|
3
|
-
## Sumário
|
|
4
|
-
|
|
5
|
-
1. [Pacotes de Proxy Rotation](#1-pacotes-de-proxy-rotation)
|
|
6
|
-
2. [HTTP Agent Packages](#2-http-agent-packages)
|
|
7
|
-
3. [Crawlee ProxyConfiguration](#3-crawlee-proxyconfiguration)
|
|
8
|
-
4. [Session-Based Proxy Pinning](#4-session-based-proxy-pinning)
|
|
9
|
-
5. [Protocolos Suportados](#5-protocolos-suportados)
|
|
10
|
-
6. [Health Checking de Proxies](#6-health-checking-de-proxies)
|
|
11
|
-
7. [Proxy Pool com Remoção Automática](#7-proxy-pool-com-remoção-automática)
|
|
12
|
-
8. [Melhores Práticas](#8-melhores-práticas)
|
|
13
|
-
9. [Exemplos de Implementação](#9-exemplos-de-implementação)
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 1. Pacotes de Proxy Rotation
|
|
18
|
-
|
|
19
|
-
### 1.1 proxy-rotator-js
|
|
20
|
-
|
|
21
|
-
**Versão:** 1.3.2
|
|
22
|
-
**Descrição:** Rotação simples de proxies com suporte a múltiplos protocolos
|
|
23
|
-
**Última atualização:** 2025
|
|
24
|
-
|
|
25
|
-
```javascript
|
|
26
|
-
import { ProxyRotator } from 'proxy-rotator-js';
|
|
27
|
-
|
|
28
|
-
const rotator = new ProxyRotator({
|
|
29
|
-
proxies: [
|
|
30
|
-
{ host: 'proxy1.example.com', port: 8080, protocol: 'http' },
|
|
31
|
-
{ host: 'proxy2.example.com', port: 8080, protocol: 'http' },
|
|
32
|
-
{ host: 'proxy3.example.com', port: 1080, protocol: 'socks5' },
|
|
33
|
-
],
|
|
34
|
-
strategy: 'round-robin', // round-robin, random, least-used
|
|
35
|
-
healthCheck: true,
|
|
36
|
-
healthCheckInterval: 60000, // 1 minuto
|
|
37
|
-
retryDelay: 5000,
|
|
38
|
-
maxRetries: 3,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Obter próximo proxy
|
|
42
|
-
const proxy = rotator.getNextProxy();
|
|
43
|
-
console.log(proxy);
|
|
44
|
-
// { host: 'proxy1.example.com', port: 8080, protocol: 'http', url: 'http://proxy1.example.com:8080' }
|
|
45
|
-
|
|
46
|
-
// Marcar proxy como falho
|
|
47
|
-
rotator.markFailed(proxy.host);
|
|
48
|
-
|
|
49
|
-
// Obter proxy com retry automático
|
|
50
|
-
const safeProxy = await rotator.getProxyWithRetry();
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### 1.2 rezo
|
|
54
|
-
|
|
55
|
-
**Versão:** 1.x
|
|
56
|
-
**Descrição:** Proxy management com health checking integrado
|
|
57
|
-
**Última atualização:** 2026
|
|
58
|
-
|
|
59
|
-
```javascript
|
|
60
|
-
import { ProxyManager } from 'rezo';
|
|
61
|
-
|
|
62
|
-
const manager = new ProxyManager({
|
|
63
|
-
proxies: [
|
|
64
|
-
'http://user:pass@proxy1.com:8080',
|
|
65
|
-
'http://user:pass@proxy2.com:8080',
|
|
66
|
-
'socks5://user:pass@proxy3.com:1080',
|
|
67
|
-
],
|
|
68
|
-
healthCheck: {
|
|
69
|
-
enabled: true,
|
|
70
|
-
interval: 30000, // 30 segundos
|
|
71
|
-
timeout: 5000,
|
|
72
|
-
testUrl: 'http://httpbin.org/ip',
|
|
73
|
-
},
|
|
74
|
-
rotation: {
|
|
75
|
-
strategy: 'round-robin',
|
|
76
|
-
stickySession: false,
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Obter proxy saudável
|
|
81
|
-
const proxy = await manager.getProxy();
|
|
82
|
-
|
|
83
|
-
// Usar com fetch
|
|
84
|
-
const response = await fetch('https://example.com', {
|
|
85
|
-
agent: manager.getAgent(proxy),
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Reportar sucesso/falha
|
|
89
|
-
manager.reportSuccess(proxy);
|
|
90
|
-
manager.reportFailure(proxy);
|
|
91
|
-
|
|
92
|
-
// Obter estatísticas
|
|
93
|
-
const stats = manager.getStats();
|
|
94
|
-
console.log(stats);
|
|
95
|
-
// { total: 10, healthy: 8, unhealthy: 2, avgResponseTime: 245 }
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### 1.3 Crawlee ProxyConfiguration
|
|
99
|
-
|
|
100
|
-
**Versão:** 3.x
|
|
101
|
-
**Descrição:** Proxy management integrado ao Crawlee
|
|
102
|
-
**Última atualização:** 2026
|
|
103
|
-
|
|
104
|
-
```javascript
|
|
105
|
-
import { ProxyConfiguration } from 'crawlee';
|
|
106
|
-
|
|
107
|
-
// Lista estática de proxies
|
|
108
|
-
const proxyConfiguration = new ProxyConfiguration({
|
|
109
|
-
proxyUrls: [
|
|
110
|
-
'http://user:pass@proxy1.com:8080',
|
|
111
|
-
'http://user:pass@proxy2.com:8080',
|
|
112
|
-
'socks5://user:pass@proxy3.com:1080',
|
|
113
|
-
],
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Função personalizada de proxy
|
|
117
|
-
const proxyConfigurationCustom = new ProxyConfiguration({
|
|
118
|
-
newUrlFunction: (sessionId) => {
|
|
119
|
-
const proxies = [
|
|
120
|
-
'http://proxy1.com:8080',
|
|
121
|
-
'http://proxy2.com:8080',
|
|
122
|
-
'http://proxy3.com:8080',
|
|
123
|
-
];
|
|
124
|
-
const index = sessionId.charCodeAt(0) % proxies.length;
|
|
125
|
-
return proxies[index];
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// Usar com crawler
|
|
130
|
-
const crawler = new PlaywrightCrawler({
|
|
131
|
-
proxyConfiguration,
|
|
132
|
-
// ou
|
|
133
|
-
proxyConfiguration: proxyConfigurationCustom,
|
|
134
|
-
});
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## 2. HTTP Agent Packages
|
|
140
|
-
|
|
141
|
-
### 2.1 https-proxy-agent
|
|
142
|
-
|
|
143
|
-
**Versão:** 7.x
|
|
144
|
-
**Descrição:** HTTP/HTTPS proxy agent para Node.js
|
|
145
|
-
**Última atualização:** 2024
|
|
146
|
-
|
|
147
|
-
```javascript
|
|
148
|
-
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
149
|
-
|
|
150
|
-
const agent = new HttpsProxyAgent('http://user:pass@proxy.example.com:8080');
|
|
151
|
-
|
|
152
|
-
// Usar com fetch (Node 18+)
|
|
153
|
-
const response = await fetch('https://example.com', {
|
|
154
|
-
dispatcher: agent,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// Usar com axios
|
|
158
|
-
import axios from 'axios';
|
|
159
|
-
const response = await axios.get('https://example.com', {
|
|
160
|
-
httpsAgent: agent,
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// Usar com got
|
|
164
|
-
import got from 'got';
|
|
165
|
-
const response = await got('https://example.com', {
|
|
166
|
-
agent: { https: agent },
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Configurações avançadas
|
|
170
|
-
const agentAdvanced = new HttpsProxyAgent('http://proxy.example.com:8080', {
|
|
171
|
-
auth: 'user:password',
|
|
172
|
-
headers: { 'X-Custom-Header': 'value' },
|
|
173
|
-
rejectUnauthorized: false,
|
|
174
|
-
});
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### 2.2 socks-proxy-agent
|
|
178
|
-
|
|
179
|
-
**Versão:** 8.x
|
|
180
|
-
**Descrição:** SOCKS proxy agent para Node.js
|
|
181
|
-
**Última atualização:** 2024
|
|
182
|
-
|
|
183
|
-
```javascript
|
|
184
|
-
import { SocksProxyAgent } from 'socks-proxy-agent';
|
|
185
|
-
|
|
186
|
-
// SOCKS5 proxy
|
|
187
|
-
const agent5 = new SocksProxyAgent('socks5://user:pass@proxy.example.com:1080');
|
|
188
|
-
|
|
189
|
-
// SOCKS4 proxy
|
|
190
|
-
const agent4 = new SocksProxyAgent('socks4://proxy.example.com:1080');
|
|
191
|
-
|
|
192
|
-
// SOCKS4a proxy
|
|
193
|
-
const agent4a = new SocksProxyAgent('socks4a://proxy.example.com:1080');
|
|
194
|
-
|
|
195
|
-
// SOCKS5h proxy (DNS via proxy)
|
|
196
|
-
const agent5h = new SocksProxyAgent('socks5h://proxy.example.com:1080');
|
|
197
|
-
|
|
198
|
-
// Usar com HTTPS
|
|
199
|
-
import https from 'https';
|
|
200
|
-
const options = {
|
|
201
|
-
agent: agent5,
|
|
202
|
-
hostname: 'example.com',
|
|
203
|
-
port: 443,
|
|
204
|
-
path: '/',
|
|
205
|
-
method: 'GET',
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const req = https.request(options);
|
|
209
|
-
req.end();
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### 2.3 socks
|
|
213
|
-
|
|
214
|
-
**Versão:** 2.8.9
|
|
215
|
-
**Descrição:** Cliente SOCKS puro para Node.js
|
|
216
|
-
**Última atualização:** 2024
|
|
217
|
-
|
|
218
|
-
```javascript
|
|
219
|
-
import { SocksClient } from 'socks';
|
|
220
|
-
|
|
221
|
-
// Conexão SOCKS5
|
|
222
|
-
const info = await SocksClient.createConnection({
|
|
223
|
-
proxy: {
|
|
224
|
-
host: 'proxy.example.com',
|
|
225
|
-
port: 1080,
|
|
226
|
-
type: 5,
|
|
227
|
-
userId: 'user',
|
|
228
|
-
password: 'pass',
|
|
229
|
-
},
|
|
230
|
-
command: 'connect',
|
|
231
|
-
destination: {
|
|
232
|
-
host: 'example.com',
|
|
233
|
-
port: 443,
|
|
234
|
-
},
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
// info.socket = socket conectado via SOCKS
|
|
238
|
-
|
|
239
|
-
// Usar com TLS
|
|
240
|
-
import tls from 'tls';
|
|
241
|
-
const tlsSocket = tls.connect({
|
|
242
|
-
socket: info.socket,
|
|
243
|
-
servername: 'example.com',
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// Connecção SOCKS4
|
|
247
|
-
const info4 = await SocksClient.createConnection({
|
|
248
|
-
proxy: {
|
|
249
|
-
host: 'proxy.example.com',
|
|
250
|
-
port: 1080,
|
|
251
|
-
type: 4,
|
|
252
|
-
},
|
|
253
|
-
command: 'connect',
|
|
254
|
-
destination: {
|
|
255
|
-
host: '93.184.216.34', // SOCK4 não suporta DNS
|
|
256
|
-
port: 443,
|
|
257
|
-
},
|
|
258
|
-
});
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
### 2.4 proxy-chain
|
|
262
|
-
|
|
263
|
-
**Versão:** 2.4.0
|
|
264
|
-
**Descrição:** Proxy chaining e roteamento avançado
|
|
265
|
-
**Última atualização:** 2023
|
|
266
|
-
|
|
267
|
-
```javascript
|
|
268
|
-
import { ProxyChain } from 'proxy-chain';
|
|
269
|
-
|
|
270
|
-
// Criar proxy local que encaminha para proxy remoto
|
|
271
|
-
const server = ProxyChain.createServer({
|
|
272
|
-
targetHost: 'proxy.example.com',
|
|
273
|
-
targetPort: 8080,
|
|
274
|
-
auth: function(url) {
|
|
275
|
-
return {
|
|
276
|
-
username: 'user',
|
|
277
|
-
password: 'pass',
|
|
278
|
-
};
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
server.listen(8000, () => {
|
|
283
|
-
console.log('Proxy local rodando na porta 8000');
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// Usar com Playwright
|
|
287
|
-
import { chromium } from 'playwright';
|
|
288
|
-
const browser = await chromium.launch({
|
|
289
|
-
proxy: {
|
|
290
|
-
server: 'http://localhost:8000',
|
|
291
|
-
},
|
|
292
|
-
});
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
---
|
|
296
|
-
|
|
297
|
-
## 3. Crawlee ProxyConfiguration
|
|
298
|
-
|
|
299
|
-
### 3.1 Proxy Estático (Round-Robin)
|
|
300
|
-
|
|
301
|
-
```javascript
|
|
302
|
-
import { ProxyConfiguration, PlaywrightCrawler } from 'crawlee';
|
|
303
|
-
|
|
304
|
-
const proxyConfiguration = new ProxyConfiguration({
|
|
305
|
-
proxyUrls: [
|
|
306
|
-
'http://user:pass@proxy1.com:8080',
|
|
307
|
-
'http://user:pass@proxy2.com:8080',
|
|
308
|
-
'http://user:pass@proxy3.com:8080',
|
|
309
|
-
],
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
const crawler = new PlaywrightCrawler({
|
|
313
|
-
proxyConfiguration,
|
|
314
|
-
requestHandler: async ({ request, page, proxyInfo }) => {
|
|
315
|
-
console.log(`Usando proxy: ${proxyInfo.url}`);
|
|
316
|
-
await page.goto(request.url);
|
|
317
|
-
return { title: await page.title() };
|
|
318
|
-
},
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
await crawler.run(['https://example.com']);
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
**Comportamento:**
|
|
325
|
-
- Rotaciona proxies em ordem (round-robin)
|
|
326
|
-
- Cada request usa um proxy diferente
|
|
327
|
-
- Se um proxy falhar, tenta o próximo
|
|
328
|
-
- Não mantém sessão por proxy
|
|
329
|
-
|
|
330
|
-
### 3.2 Função Personalizada de Proxy
|
|
331
|
-
|
|
332
|
-
```javascript
|
|
333
|
-
import { ProxyConfiguration, PlaywrightCrawler } from 'crawlee';
|
|
334
|
-
|
|
335
|
-
const proxyConfiguration = new ProxyConfiguration({
|
|
336
|
-
newUrlFunction: (sessionId) => {
|
|
337
|
-
// Baseado no sessionId, retorna um proxy específico
|
|
338
|
-
const proxies = {
|
|
339
|
-
'session1': 'http://proxy1.com:8080',
|
|
340
|
-
'session2': 'http://proxy2.com:8080',
|
|
341
|
-
'session3': 'socks5://proxy3.com:1080',
|
|
342
|
-
};
|
|
343
|
-
return proxies[sessionId] || 'http://default-proxy.com:8080';
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
const crawler = new PlaywrightCrawler({
|
|
348
|
-
proxyConfiguration,
|
|
349
|
-
useSessionPool: true,
|
|
350
|
-
sessionOptions: {
|
|
351
|
-
maxAgeSecs: 3600,
|
|
352
|
-
maxUsageCount: 50,
|
|
353
|
-
},
|
|
354
|
-
requestHandler: async ({ request, page, session, proxyInfo }) => {
|
|
355
|
-
console.log(`Sessão: ${session.id}, Proxy: ${proxyInfo.url}`);
|
|
356
|
-
await page.goto(request.url);
|
|
357
|
-
return { title: await page.title() };
|
|
358
|
-
},
|
|
359
|
-
});
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### 3.3 Proxies em Cascata (Tiered)
|
|
363
|
-
|
|
364
|
-
```javascript
|
|
365
|
-
import { ProxyConfiguration, PlaywrightCrawler } from 'crawlee';
|
|
366
|
-
|
|
367
|
-
// Sistema de proxies em camadas
|
|
368
|
-
class TieredProxyConfiguration {
|
|
369
|
-
constructor() {
|
|
370
|
-
this.tiers = [
|
|
371
|
-
// Tier 1: Proxies residenciais (mais caros, menos bloqueio)
|
|
372
|
-
{
|
|
373
|
-
proxies: [
|
|
374
|
-
'http://residential1.com:8080',
|
|
375
|
-
'http://residential2.com:8080',
|
|
376
|
-
],
|
|
377
|
-
priority: 1,
|
|
378
|
-
costPer1000: 15.00,
|
|
379
|
-
},
|
|
380
|
-
// Tier 2: Proxies datacenter (mais baratos, mais bloqueio)
|
|
381
|
-
{
|
|
382
|
-
proxies: [
|
|
383
|
-
'http://datacenter1.com:8080',
|
|
384
|
-
'http://datacenter2.com:8080',
|
|
385
|
-
],
|
|
386
|
-
priority: 2,
|
|
387
|
-
costPer1000: 0.50,
|
|
388
|
-
},
|
|
389
|
-
// Tier 3: Proxies públicos (gratuitos, instáveis)
|
|
390
|
-
{
|
|
391
|
-
proxies: [
|
|
392
|
-
'http://public1.com:8080',
|
|
393
|
-
'http://public2.com:8080',
|
|
394
|
-
],
|
|
395
|
-
priority: 3,
|
|
396
|
-
costPer1000: 0,
|
|
397
|
-
},
|
|
398
|
-
];
|
|
399
|
-
this.currentTier = 0;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
getNextProxy() {
|
|
403
|
-
const tier = this.tiers[this.currentTier];
|
|
404
|
-
const proxy = tier.proxies[Math.floor(Math.random() * tier.proxies.length)];
|
|
405
|
-
return { proxy, tier: this.currentTier };
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
downgradeTier() {
|
|
409
|
-
if (this.currentTier < this.tiers.length - 1) {
|
|
410
|
-
this.currentTier++;
|
|
411
|
-
console.log(`Downgrading to tier ${this.currentTier}`);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
upgradeTier() {
|
|
416
|
-
if (this.currentTier > 0) {
|
|
417
|
-
this.currentTier--;
|
|
418
|
-
console.log(`Upgrading to tier ${this.currentTier}`);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// Usar com Crawlee
|
|
424
|
-
const tieredConfig = new TieredProxyConfiguration();
|
|
425
|
-
|
|
426
|
-
const crawler = new PlaywrightCrawler({
|
|
427
|
-
proxyConfiguration: new ProxyConfiguration({
|
|
428
|
-
newUrlFunction: () => tieredConfig.getNextProxy().proxy,
|
|
429
|
-
}),
|
|
430
|
-
requestHandler: async ({ request, page }) => {
|
|
431
|
-
await page.goto(request.url);
|
|
432
|
-
return { title: await page.title() };
|
|
433
|
-
},
|
|
434
|
-
});
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
---
|
|
438
|
-
|
|
439
|
-
## 4. Session-Based Proxy Pinning
|
|
440
|
-
|
|
441
|
-
### 4.1 Pinner de Sessão com Scoring
|
|
442
|
-
|
|
443
|
-
```javascript
|
|
444
|
-
import { SessionPool, ProxyConfiguration } from 'crawlee';
|
|
445
|
-
|
|
446
|
-
class SessionProxyPinner {
|
|
447
|
-
constructor(proxies) {
|
|
448
|
-
this.proxies = proxies;
|
|
449
|
-
this.sessions = new Map();
|
|
450
|
-
this.errorScores = new Map();
|
|
451
|
-
this.maxErrorScore = 5;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
getProxyForSession(sessionId) {
|
|
455
|
-
// Se já tem proxy atribuído, retorna o mesmo
|
|
456
|
-
if (this.sessions.has(sessionId)) {
|
|
457
|
-
return this.sessions.get(sessionId);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// Encontrar proxy com menor score de erro
|
|
461
|
-
const availableProxies = this.proxies
|
|
462
|
-
.filter(p => (this.errorScores.get(p) || 0) < this.maxErrorScore)
|
|
463
|
-
.sort((a, b) => (this.errorScores.get(a) || 0) - (this.errorScores.get(b) || 0));
|
|
464
|
-
|
|
465
|
-
if (availableProxies.length === 0) {
|
|
466
|
-
// Resetar scores se todos falharam
|
|
467
|
-
this.errorScores.clear();
|
|
468
|
-
return this.proxies[0];
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
const selectedProxy = availableProxies[0];
|
|
472
|
-
this.sessions.set(sessionId, selectedProxy);
|
|
473
|
-
return selectedProxy;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
reportSuccess(sessionId) {
|
|
477
|
-
const proxy = this.sessions.get(sessionId);
|
|
478
|
-
if (proxy) {
|
|
479
|
-
this.errorScores.set(proxy, 0);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
reportFailure(sessionId) {
|
|
484
|
-
const proxy = this.sessions.get(sessionId);
|
|
485
|
-
if (proxy) {
|
|
486
|
-
const currentScore = this.errorScores.get(proxy) || 0;
|
|
487
|
-
this.errorScores.set(proxy, currentScore + 1);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
getStats() {
|
|
492
|
-
const stats = {
|
|
493
|
-
totalProxies: this.proxies.length,
|
|
494
|
-
healthyProxies: 0,
|
|
495
|
-
unhealthyProxies: 0,
|
|
496
|
-
activeSessions: this.sessions.size,
|
|
497
|
-
};
|
|
498
|
-
|
|
499
|
-
for (const proxy of this.proxies) {
|
|
500
|
-
const score = this.errorScores.get(proxy) || 0;
|
|
501
|
-
if (score < this.maxErrorScore) {
|
|
502
|
-
stats.healthyProxies++;
|
|
503
|
-
} else {
|
|
504
|
-
stats.unhealthyProxies++;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
return stats;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// Usar com Crawlee
|
|
513
|
-
const pinner = new SessionProxyPinner([
|
|
514
|
-
'http://proxy1.com:8080',
|
|
515
|
-
'http://proxy2.com:8080',
|
|
516
|
-
'http://proxy3.com:8080',
|
|
517
|
-
]);
|
|
518
|
-
|
|
519
|
-
const crawler = new PlaywrightCrawler({
|
|
520
|
-
useSessionPool: true,
|
|
521
|
-
sessionOptions: {
|
|
522
|
-
maxAgeSecs: 3600,
|
|
523
|
-
maxUsageCount: 50,
|
|
524
|
-
},
|
|
525
|
-
proxyConfiguration: new ProxyConfiguration({
|
|
526
|
-
newUrlFunction: (sessionId) => pinner.getProxyForSession(sessionId),
|
|
527
|
-
}),
|
|
528
|
-
requestHandler: async ({ request, page, session, proxyInfo }) => {
|
|
529
|
-
try {
|
|
530
|
-
await page.goto(request.url);
|
|
531
|
-
pinner.reportSuccess(session.id);
|
|
532
|
-
return { title: await page.title() };
|
|
533
|
-
} catch (error) {
|
|
534
|
-
pinner.reportFailure(session.id);
|
|
535
|
-
throw error;
|
|
536
|
-
}
|
|
537
|
-
},
|
|
538
|
-
});
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
### 4.2 Sticky Sessions por Dominio
|
|
542
|
-
|
|
543
|
-
```javascript
|
|
544
|
-
import { SessionPool } from 'crawlee';
|
|
545
|
-
|
|
546
|
-
class DomainStickyProxy {
|
|
547
|
-
constructor(proxies) {
|
|
548
|
-
this.proxies = proxies;
|
|
549
|
-
this.domainProxies = new Map();
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
getProxyForDomain(domain) {
|
|
553
|
-
if (this.domainProxies.has(domain)) {
|
|
554
|
-
return this.domainProxies.get(domain);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// Selecionar proxy baseado no hash do domínio
|
|
558
|
-
const hash = this.hashCode(domain);
|
|
559
|
-
const index = Math.abs(hash) % this.proxies.length;
|
|
560
|
-
const proxy = this.proxies[index];
|
|
561
|
-
|
|
562
|
-
this.domainProxies.set(domain, proxy);
|
|
563
|
-
return proxy;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
hashCode(str) {
|
|
567
|
-
let hash = 0;
|
|
568
|
-
for (let i = 0; i < str.length; i++) {
|
|
569
|
-
const char = str.charCodeAt(i);
|
|
570
|
-
hash = ((hash << 5) - hash) + char;
|
|
571
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
572
|
-
}
|
|
573
|
-
return hash;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// Usar
|
|
578
|
-
const stickyProxy = new DomainStickyProxy([
|
|
579
|
-
'http://proxy1.com:8080',
|
|
580
|
-
'http://proxy2.com:8080',
|
|
581
|
-
'http://proxy3.com:8080',
|
|
582
|
-
]);
|
|
583
|
-
|
|
584
|
-
const crawler = new PlaywrightCrawler({
|
|
585
|
-
proxyConfiguration: new ProxyConfiguration({
|
|
586
|
-
newUrlFunction: (sessionId) => {
|
|
587
|
-
const domain = new URL(sessionId).hostname;
|
|
588
|
-
return stickyProxy.getProxyForDomain(domain);
|
|
589
|
-
},
|
|
590
|
-
}),
|
|
591
|
-
});
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
---
|
|
595
|
-
|
|
596
|
-
## 5. Protocolos Suportados
|
|
597
|
-
|
|
598
|
-
### Tabela de Protocolos
|
|
599
|
-
|
|
600
|
-
| Protocolo | Porta Padrão | Autenticação | DNS Resolution | Velocidade | Segurança |
|
|
601
|
-
|-----------|--------------|--------------|----------------|------------|-----------|
|
|
602
|
-
| HTTP | 80/8080 | Opcional | Cliente | Rápido | Baixa |
|
|
603
|
-
| HTTPS | 443/8443 | Opcional | Cliente | Rápido | Alta |
|
|
604
|
-
| SOCKS4 | 1080 | Não | Cliente | Média | Baixa |
|
|
605
|
-
| SOCKS4a | 1080 | Não | Proxy | Média | Baixa |
|
|
606
|
-
| SOCKS5 | 1080 | Sim | Ambos | Média | Média |
|
|
607
|
-
| SOCKS5h | 1080 | Sim | Proxy | Média | Média |
|
|
608
|
-
|
|
609
|
-
### Detalhes por Protocolo
|
|
610
|
-
|
|
611
|
-
**HTTP Proxy:**
|
|
612
|
-
```
|
|
613
|
-
- Mais comum e amplamente suportado
|
|
614
|
-
- Não criptografa tráfego
|
|
615
|
-
- Suitable para scraping básico
|
|
616
|
-
- Autenticação via headers ou URL
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
**HTTPS Proxy:**
|
|
620
|
-
```
|
|
621
|
-
- Criptografa tráfego entre cliente e proxy
|
|
622
|
-
- Suporta CONNECT method
|
|
623
|
-
- Ideal para sites HTTPS
|
|
624
|
-
- Mais seguro que HTTP
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
**SOCKS4:**
|
|
628
|
-
```
|
|
629
|
-
- Proxy de camada de transporte
|
|
630
|
-
- Não suporta autenticação
|
|
631
|
-
- Apenas TCP
|
|
632
|
-
- Não resolve DNS (precisa de IP)
|
|
633
|
-
```
|
|
634
|
-
|
|
635
|
-
**SOCKS4a:**
|
|
636
|
-
```
|
|
637
|
-
- Extensão do SOCKS4
|
|
638
|
-
- Suporta DNS resolution via proxy
|
|
639
|
-
- Não suporta autenticação
|
|
640
|
-
- Apenas TCP
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
**SOCKS5:**
|
|
644
|
-
```
|
|
645
|
-
- Proxy completo de camada de transporte
|
|
646
|
-
- Suporta autenticação (user/pass)
|
|
647
|
-
- Suporta TCP e UDP
|
|
648
|
-
- Suporta DNS resolution
|
|
649
|
-
- Mais flexível e seguro
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
**SOCKS5h:**
|
|
653
|
-
```
|
|
654
|
-
- SOCKS5 com DNS resolution forçada via proxy
|
|
655
|
-
- Mais seguro para privacidade
|
|
656
|
-
- Evita DNS leaks
|
|
657
|
-
- Recomendado para scraping avançado
|
|
658
|
-
```
|
|
659
|
-
|
|
660
|
-
### Exemplos de Uso por Protocolo
|
|
661
|
-
|
|
662
|
-
```javascript
|
|
663
|
-
// HTTP
|
|
664
|
-
const httpProxy = 'http://user:pass@proxy.com:8080';
|
|
665
|
-
|
|
666
|
-
// HTTPS
|
|
667
|
-
const httpsProxy = 'https://user:pass@proxy.com:8443';
|
|
668
|
-
|
|
669
|
-
// SOCKS4
|
|
670
|
-
const socks4Proxy = 'socks4://proxy.com:1080';
|
|
671
|
-
|
|
672
|
-
// SOCKS4a
|
|
673
|
-
const socks4aProxy = 'socks4a://proxy.com:1080';
|
|
674
|
-
|
|
675
|
-
// SOCKS5
|
|
676
|
-
const socks5Proxy = 'socks5://user:pass@proxy.com:1080';
|
|
677
|
-
|
|
678
|
-
// SOCKS5h
|
|
679
|
-
const socks5hProxy = 'socks5h://user:pass@proxy.com:1080';
|
|
680
|
-
|
|
681
|
-
// Usar com Playwright
|
|
682
|
-
import { chromium } from 'playwright';
|
|
683
|
-
|
|
684
|
-
const browser = await chromium.launch({
|
|
685
|
-
proxy: {
|
|
686
|
-
server: socks5Proxy,
|
|
687
|
-
username: 'user',
|
|
688
|
-
password: 'pass',
|
|
689
|
-
},
|
|
690
|
-
});
|
|
691
|
-
```
|
|
692
|
-
|
|
693
|
-
---
|
|
694
|
-
|
|
695
|
-
## 6. Health Checking de Proxies
|
|
696
|
-
|
|
697
|
-
### 6.1 Health Checking Ativo (Pre-Use)
|
|
698
|
-
|
|
699
|
-
```javascript
|
|
700
|
-
class ActiveHealthChecker {
|
|
701
|
-
constructor(proxies, options = {}) {
|
|
702
|
-
this.proxies = proxies;
|
|
703
|
-
this.testUrl = options.testUrl || 'http://httpbin.org/ip';
|
|
704
|
-
this.timeout = options.timeout || 5000;
|
|
705
|
-
this.retries = options.retries || 2;
|
|
706
|
-
this.results = new Map();
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
async checkProxy(proxy) {
|
|
710
|
-
const startTime = Date.now();
|
|
711
|
-
|
|
712
|
-
for (let i = 0; i < this.retries; i++) {
|
|
713
|
-
try {
|
|
714
|
-
const controller = new AbortController();
|
|
715
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
716
|
-
|
|
717
|
-
const response = await fetch(this.testUrl, {
|
|
718
|
-
signal: controller.signal,
|
|
719
|
-
dispatcher: this.getAgent(proxy),
|
|
720
|
-
});
|
|
721
|
-
|
|
722
|
-
clearTimeout(timeoutId);
|
|
723
|
-
|
|
724
|
-
const endTime = Date.now();
|
|
725
|
-
const responseTime = endTime - startTime;
|
|
726
|
-
|
|
727
|
-
this.results.set(proxy, {
|
|
728
|
-
healthy: true,
|
|
729
|
-
responseTime,
|
|
730
|
-
lastChecked: new Date(),
|
|
731
|
-
status: response.status,
|
|
732
|
-
});
|
|
733
|
-
|
|
734
|
-
return { healthy: true, responseTime };
|
|
735
|
-
} catch (error) {
|
|
736
|
-
if (i === this.retries - 1) {
|
|
737
|
-
this.results.set(proxy, {
|
|
738
|
-
healthy: false,
|
|
739
|
-
error: error.message,
|
|
740
|
-
lastChecked: new Date(),
|
|
741
|
-
});
|
|
742
|
-
return { healthy: false, error: error.message };
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
getAgent(proxy) {
|
|
749
|
-
if (proxy.startsWith('socks')) {
|
|
750
|
-
const { SocksProxyAgent } = require('socks-proxy-agent');
|
|
751
|
-
return new SocksProxyAgent(proxy);
|
|
752
|
-
} else {
|
|
753
|
-
const { HttpsProxyAgent } = require('https-proxy-agent');
|
|
754
|
-
return new HttpsProxyAgent(proxy);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
async checkAll() {
|
|
759
|
-
const results = await Promise.allSettled(
|
|
760
|
-
this.proxies.map(proxy => this.checkProxy(proxy))
|
|
761
|
-
);
|
|
762
|
-
|
|
763
|
-
return results.map((result, index) => ({
|
|
764
|
-
proxy: this.proxies[index],
|
|
765
|
-
...result.value,
|
|
766
|
-
}));
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
getHealthyProxies() {
|
|
770
|
-
return this.proxies.filter(proxy => {
|
|
771
|
-
const result = this.results.get(proxy);
|
|
772
|
-
return result && result.healthy;
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
getUnhealthyProxies() {
|
|
777
|
-
return this.proxies.filter(proxy => {
|
|
778
|
-
const result = this.results.get(proxy);
|
|
779
|
-
return result && !result.healthy;
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// Uso
|
|
785
|
-
const checker = new ActiveHealthChecker([
|
|
786
|
-
'http://proxy1.com:8080',
|
|
787
|
-
'http://proxy2.com:8080',
|
|
788
|
-
'socks5://proxy3.com:1080',
|
|
789
|
-
], {
|
|
790
|
-
testUrl: 'http://httpbin.org/ip',
|
|
791
|
-
timeout: 5000,
|
|
792
|
-
retries: 2,
|
|
793
|
-
});
|
|
794
|
-
|
|
795
|
-
const results = await checker.checkAll();
|
|
796
|
-
console.log('Healthy proxies:', checker.getHealthyProxies());
|
|
797
|
-
```
|
|
798
|
-
|
|
799
|
-
### 6.2 Health Checking Passivo (Runtime)
|
|
800
|
-
|
|
801
|
-
```javascript
|
|
802
|
-
class PassiveHealthChecker {
|
|
803
|
-
constructor(options = {}) {
|
|
804
|
-
this.failureThreshold = options.failureThreshold || 3;
|
|
805
|
-
this.recoveryTime = options.recoveryTime || 300000; // 5 minutos
|
|
806
|
-
this.stats = new Map();
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
reportSuccess(proxy) {
|
|
810
|
-
const stat = this.stats.get(proxy) || {
|
|
811
|
-
successes: 0,
|
|
812
|
-
failures: 0,
|
|
813
|
-
lastFailure: null,
|
|
814
|
-
isHealthy: true,
|
|
815
|
-
};
|
|
816
|
-
|
|
817
|
-
stat.successes++;
|
|
818
|
-
stat.isHealthy = true;
|
|
819
|
-
this.stats.set(proxy, stat);
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
reportFailure(proxy) {
|
|
823
|
-
const stat = this.stats.get(proxy) || {
|
|
824
|
-
successes: 0,
|
|
825
|
-
failures: 0,
|
|
826
|
-
lastFailure: null,
|
|
827
|
-
isHealthy: true,
|
|
828
|
-
};
|
|
829
|
-
|
|
830
|
-
stat.failures++;
|
|
831
|
-
stat.lastFailure = Date.now();
|
|
832
|
-
|
|
833
|
-
if (stat.failures >= this.failureThreshold) {
|
|
834
|
-
stat.isHealthy = false;
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
this.stats.set(proxy, stat);
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
isHealthy(proxy) {
|
|
841
|
-
const stat = this.stats.get(proxy);
|
|
842
|
-
if (!stat) return true;
|
|
843
|
-
|
|
844
|
-
if (!stat.isHealthy) {
|
|
845
|
-
// Verificar se já passou tempo de recuperação
|
|
846
|
-
if (Date.now() - stat.lastFailure > this.recoveryTime) {
|
|
847
|
-
stat.isHealthy = true;
|
|
848
|
-
stat.failures = 0;
|
|
849
|
-
this.stats.set(proxy, stat);
|
|
850
|
-
return true;
|
|
851
|
-
}
|
|
852
|
-
return false;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
return true;
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
getStats() {
|
|
859
|
-
const stats = {
|
|
860
|
-
total: 0,
|
|
861
|
-
healthy: 0,
|
|
862
|
-
unhealthy: 0,
|
|
863
|
-
details: [],
|
|
864
|
-
};
|
|
865
|
-
|
|
866
|
-
for (const [proxy, stat] of this.stats) {
|
|
867
|
-
stats.total++;
|
|
868
|
-
if (stat.isHealthy) {
|
|
869
|
-
stats.healthy++;
|
|
870
|
-
} else {
|
|
871
|
-
stats.unhealthy++;
|
|
872
|
-
}
|
|
873
|
-
stats.details.push({ proxy, ...stat });
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
return stats;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
// Usar com Crawlee
|
|
881
|
-
const passiveChecker = new PassiveHealthChecker({
|
|
882
|
-
failureThreshold: 3,
|
|
883
|
-
recoveryTime: 300000,
|
|
884
|
-
});
|
|
885
|
-
|
|
886
|
-
const crawler = new PlaywrightCrawler({
|
|
887
|
-
requestHandler: async ({ request, page, session }) => {
|
|
888
|
-
try {
|
|
889
|
-
await page.goto(request.url);
|
|
890
|
-
passiveChecker.reportSuccess(session.id);
|
|
891
|
-
return { title: await page.title() };
|
|
892
|
-
} catch (error) {
|
|
893
|
-
passiveChecker.reportFailure(session.id);
|
|
894
|
-
throw error;
|
|
895
|
-
}
|
|
896
|
-
},
|
|
897
|
-
});
|
|
898
|
-
```
|
|
899
|
-
|
|
900
|
-
### 6.3 Health Checking Integrado (rezo)
|
|
901
|
-
|
|
902
|
-
```javascript
|
|
903
|
-
import { ProxyManager } from 'rezo';
|
|
904
|
-
|
|
905
|
-
const manager = new ProxyManager({
|
|
906
|
-
proxies: [
|
|
907
|
-
'http://proxy1.com:8080',
|
|
908
|
-
'http://proxy2.com:8080',
|
|
909
|
-
'socks5://proxy3.com:1080',
|
|
910
|
-
],
|
|
911
|
-
healthCheck: {
|
|
912
|
-
enabled: true,
|
|
913
|
-
interval: 30000, // Verificar a cada 30 segundos
|
|
914
|
-
timeout: 5000,
|
|
915
|
-
testUrl: 'http://httpbin.org/ip',
|
|
916
|
-
retries: 2,
|
|
917
|
-
},
|
|
918
|
-
});
|
|
919
|
-
|
|
920
|
-
// O manager automaticamente:
|
|
921
|
-
// 1. Verifica saúde dos proxies periodicamente
|
|
922
|
-
// 2. Remove proxies não saudáveis do pool
|
|
923
|
-
// 3. Tenta recuperar proxies após timeout
|
|
924
|
-
// 4. Reporta estatísticas
|
|
925
|
-
|
|
926
|
-
const proxy = await manager.getProxy(); // Sempre retorna proxy saudável
|
|
927
|
-
```
|
|
928
|
-
|
|
929
|
-
---
|
|
930
|
-
|
|
931
|
-
## 7. Proxy Pool com Remoção Automática
|
|
932
|
-
|
|
933
|
-
### 7.1 Sistema de Cemetery (Graveyard)
|
|
934
|
-
|
|
935
|
-
```javascript
|
|
936
|
-
class ProxyPool {
|
|
937
|
-
constructor(proxies, options = {}) {
|
|
938
|
-
this.proxies = new Map();
|
|
939
|
-
this.graveyard = new Map();
|
|
940
|
-
this.maxFailures = options.maxFailures || 3;
|
|
941
|
-
this.reviveTimer = options.reviveTimer || 300000; // 5 minutos
|
|
942
|
-
this.currentIndex = 0;
|
|
943
|
-
|
|
944
|
-
// Inicializar proxies
|
|
945
|
-
for (const proxy of proxies) {
|
|
946
|
-
this.proxies.set(proxy, {
|
|
947
|
-
failures: 0,
|
|
948
|
-
successes: 0,
|
|
949
|
-
lastUsed: null,
|
|
950
|
-
lastError: null,
|
|
951
|
-
status: 'healthy',
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
getNextProxy() {
|
|
957
|
-
const healthyProxies = Array.from(this.proxies.entries())
|
|
958
|
-
.filter(([_, stat]) => stat.status === 'healthy');
|
|
959
|
-
|
|
960
|
-
if (healthyProxies.length === 0) {
|
|
961
|
-
// Tentar reviver proxies do graveyard
|
|
962
|
-
this.reviveProxies();
|
|
963
|
-
|
|
964
|
-
// Se ainda não há proxies saudáveis, usar qualquer um
|
|
965
|
-
const allProxies = Array.from(this.proxies.entries());
|
|
966
|
-
if (allProxies.length === 0) {
|
|
967
|
-
throw new Error('No proxies available');
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
return allProxies[this.currentIndex % allProxies.length][0];
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
const proxy = healthyProxies[this.currentIndex % healthyProxies.length][0];
|
|
974
|
-
this.currentIndex++;
|
|
975
|
-
|
|
976
|
-
const stat = this.proxies.get(proxy);
|
|
977
|
-
stat.lastUsed = Date.now();
|
|
978
|
-
|
|
979
|
-
return proxy;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
reportSuccess(proxy) {
|
|
983
|
-
const stat = this.proxies.get(proxy);
|
|
984
|
-
if (stat) {
|
|
985
|
-
stat.successes++;
|
|
986
|
-
stat.failures = Math.max(0, stat.failures - 1); // Reduzir falhas
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
reportFailure(proxy, error) {
|
|
991
|
-
const stat = this.proxies.get(proxy);
|
|
992
|
-
if (stat) {
|
|
993
|
-
stat.failures++;
|
|
994
|
-
stat.lastError = error;
|
|
995
|
-
|
|
996
|
-
if (stat.failures >= this.maxFailures) {
|
|
997
|
-
this.buryProxy(proxy);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
buryProxy(proxy) {
|
|
1003
|
-
const stat = this.proxies.get(proxy);
|
|
1004
|
-
if (stat) {
|
|
1005
|
-
stat.status = 'dead';
|
|
1006
|
-
this.graveyard.set(proxy, {
|
|
1007
|
-
...stat,
|
|
1008
|
-
buriedAt: Date.now(),
|
|
1009
|
-
});
|
|
1010
|
-
this.proxies.delete(proxy);
|
|
1011
|
-
console.log(`Proxy buried: ${proxy}`);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
reviveProxies() {
|
|
1016
|
-
const now = Date.now();
|
|
1017
|
-
|
|
1018
|
-
for (const [proxy, stat] of this.graveyard) {
|
|
1019
|
-
if (now - stat.buriedAt >= this.reviveTimer) {
|
|
1020
|
-
// Reviver proxy com contadores resetados
|
|
1021
|
-
this.proxies.set(proxy, {
|
|
1022
|
-
failures: 0,
|
|
1023
|
-
successes: 0,
|
|
1024
|
-
lastUsed: null,
|
|
1025
|
-
lastError: null,
|
|
1026
|
-
status: 'healthy',
|
|
1027
|
-
});
|
|
1028
|
-
this.graveyard.delete(proxy);
|
|
1029
|
-
console.log(`Proxy revived: ${proxy}`);
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
getStats() {
|
|
1035
|
-
return {
|
|
1036
|
-
healthy: Array.from(this.proxies.values()).filter(s => s.status === 'healthy').length,
|
|
1037
|
-
dead: this.graveyard.size,
|
|
1038
|
-
total: this.proxies.size + this.graveyard.size,
|
|
1039
|
-
details: {
|
|
1040
|
-
proxies: Object.fromEntries(this.proxies),
|
|
1041
|
-
graveyard: Object.fromEntries(this.graveyard),
|
|
1042
|
-
},
|
|
1043
|
-
};
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
// Usar com Crawlee
|
|
1048
|
-
const pool = new ProxyPool([
|
|
1049
|
-
'http://proxy1.com:8080',
|
|
1050
|
-
'http://proxy2.com:8080',
|
|
1051
|
-
'socks5://proxy3.com:1080',
|
|
1052
|
-
], {
|
|
1053
|
-
maxFailures: 3,
|
|
1054
|
-
reviveTimer: 300000,
|
|
1055
|
-
});
|
|
1056
|
-
|
|
1057
|
-
const crawler = new PlaywrightCrawler({
|
|
1058
|
-
proxyConfiguration: new ProxyConfiguration({
|
|
1059
|
-
newUrlFunction: () => pool.getNextProxy(),
|
|
1060
|
-
}),
|
|
1061
|
-
requestHandler: async ({ request, page, proxyInfo }) => {
|
|
1062
|
-
try {
|
|
1063
|
-
await page.goto(request.url);
|
|
1064
|
-
pool.reportSuccess(proxyInfo.url);
|
|
1065
|
-
return { title: await page.title() };
|
|
1066
|
-
} catch (error) {
|
|
1067
|
-
pool.reportFailure(proxyInfo.url, error.message);
|
|
1068
|
-
throw error;
|
|
1069
|
-
}
|
|
1070
|
-
},
|
|
1071
|
-
});
|
|
1072
|
-
```
|
|
1073
|
-
|
|
1074
|
-
### 7.2 Integração com Crawlee
|
|
1075
|
-
|
|
1076
|
-
```javascript
|
|
1077
|
-
import { PlaywrightCrawler, ProxyConfiguration } from 'crawlee';
|
|
1078
|
-
|
|
1079
|
-
class CrawleeProxyPool {
|
|
1080
|
-
constructor(proxies, options = {}) {
|
|
1081
|
-
this.pool = new ProxyPool(proxies, options);
|
|
1082
|
-
this.proxyConfiguration = new ProxyConfiguration({
|
|
1083
|
-
newUrlFunction: () => this.pool.getNextProxy(),
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
getCrawlerOptions() {
|
|
1088
|
-
return {
|
|
1089
|
-
proxyConfiguration: this.proxyConfiguration,
|
|
1090
|
-
requestHandler: async ({ request, page, proxyInfo }) => {
|
|
1091
|
-
try {
|
|
1092
|
-
await page.goto(request.url);
|
|
1093
|
-
this.pool.reportSuccess(proxyInfo.url);
|
|
1094
|
-
return { title: await page.title() };
|
|
1095
|
-
} catch (error) {
|
|
1096
|
-
this.pool.reportFailure(proxyInfo.url, error.message);
|
|
1097
|
-
throw error;
|
|
1098
|
-
}
|
|
1099
|
-
},
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
getStats() {
|
|
1104
|
-
return this.pool.getStats();
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
// Uso
|
|
1109
|
-
const crawlerPool = new CrawleeProxyPool([
|
|
1110
|
-
'http://proxy1.com:8080',
|
|
1111
|
-
'http://proxy2.com:8080',
|
|
1112
|
-
'socks5://proxy3.com:1080',
|
|
1113
|
-
], {
|
|
1114
|
-
maxFailures: 3,
|
|
1115
|
-
reviveTimer: 300000,
|
|
1116
|
-
});
|
|
1117
|
-
|
|
1118
|
-
const crawler = new PlaywrightCrawler(crawlerPool.getCrawlerOptions());
|
|
1119
|
-
await crawler.run(['https://example.com']);
|
|
1120
|
-
|
|
1121
|
-
console.log(crawlerPool.getStats());
|
|
1122
|
-
```
|
|
1123
|
-
|
|
1124
|
-
---
|
|
1125
|
-
|
|
1126
|
-
## 8. Melhores Práticas
|
|
1127
|
-
|
|
1128
|
-
### 8.1 Correspondência Tipo de Proxy ↔ Target
|
|
1129
|
-
|
|
1130
|
-
```
|
|
1131
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
1132
|
-
│ Tipo de Target │
|
|
1133
|
-
├─────────────────────────────────────────────────────────────┤
|
|
1134
|
-
│ Site Básico → HTTP/HTTPS Proxy (datacenter) │
|
|
1135
|
-
│ Site Médio → HTTPS Proxy (residential) │
|
|
1136
|
-
│ Site Avançado → SOCKS5 Proxy (residential) │
|
|
1137
|
-
│ Site Premium → Mobile Proxy (4G/5G) │
|
|
1138
|
-
└─────────────────────────────────────────────────────────────┘
|
|
1139
|
-
```
|
|
1140
|
-
|
|
1141
|
-
**Recomendações por tipo de target:**
|
|
1142
|
-
|
|
1143
|
-
| Target | Tipo Proxy | Localização | Velocidade | Custo |
|
|
1144
|
-
|--------|------------|-------------|------------|-------|
|
|
1145
|
-
| Sites governamentais | Residencial | País específico | Média | Alto |
|
|
1146
|
-
| E-commerce | Residencial/Mobile | País do target | Média | Alto |
|
|
1147
|
-
| Redes sociais | Mobile (4G) | País do target | Baixa | Muito Alto |
|
|
1148
|
-
| APIs públicas | Datacenter | Qualquer | Alta | Baixo |
|
|
1149
|
-
| Sites de notícias | Residencial | País do target | Média | Médio |
|
|
1150
|
-
|
|
1151
|
-
### 8.2 Rotação Inteligente vs Cega
|
|
1152
|
-
|
|
1153
|
-
**Rotação cega (NÃO fazer):**
|
|
1154
|
-
```javascript
|
|
1155
|
-
// NÃO: Rotacionar proxy a cada request
|
|
1156
|
-
const proxy = proxies[requestCount % proxies.length];
|
|
1157
|
-
```
|
|
1158
|
-
|
|
1159
|
-
**Rotação inteligente (FAZER):**
|
|
1160
|
-
```javascript
|
|
1161
|
-
// SIM: Rotacionar baseado em contexto
|
|
1162
|
-
const getSmartProxy = (target, session) => {
|
|
1163
|
-
// 1. Manter mesma sessão para requests relacionados
|
|
1164
|
-
if (session && session.proxy) {
|
|
1165
|
-
return session.proxy;
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// 2. Usar proxy do mesmo país do target
|
|
1169
|
-
const targetCountry = getCountryFromDomain(target);
|
|
1170
|
-
const countryProxies = proxies.filter(p => p.country === targetCountry);
|
|
1171
|
-
|
|
1172
|
-
// 3. Selecionar proxy menos usado
|
|
1173
|
-
return selectLeastUsedProxy(countryProxies);
|
|
1174
|
-
};
|
|
1175
|
-
```
|
|
1176
|
-
|
|
1177
|
-
### 8.3 Monitorar e Reagir
|
|
1178
|
-
|
|
1179
|
-
```javascript
|
|
1180
|
-
class ProxyMonitor {
|
|
1181
|
-
constructor(pool) {
|
|
1182
|
-
this.pool = pool;
|
|
1183
|
-
this.alerts = [];
|
|
1184
|
-
this.thresholds = {
|
|
1185
|
-
failureRate: 0.3, // 30% de falhas
|
|
1186
|
-
avgResponseTime: 5000, // 5 segundos
|
|
1187
|
-
};
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
async monitor() {
|
|
1191
|
-
setInterval(() => {
|
|
1192
|
-
const stats = this.pool.getStats();
|
|
1193
|
-
|
|
1194
|
-
// Verificar taxa de falha
|
|
1195
|
-
const failureRate = stats.failures / (stats.successes + stats.failures);
|
|
1196
|
-
if (failureRate > this.thresholds.failureRate) {
|
|
1197
|
-
this.alert('High failure rate detected', {
|
|
1198
|
-
failureRate,
|
|
1199
|
-
threshold: this.thresholds.failureRate,
|
|
1200
|
-
});
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
// Verificar tempo de resposta
|
|
1204
|
-
if (stats.avgResponseTime > this.thresholds.avgResponseTime) {
|
|
1205
|
-
this.alert('High response time detected', {
|
|
1206
|
-
responseTime: stats.avgResponseTime,
|
|
1207
|
-
threshold: this.thresholds.avgResponseTime,
|
|
1208
|
-
});
|
|
1209
|
-
}
|
|
1210
|
-
}, 60000); // Verificar a cada minuto
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
alert(message, data) {
|
|
1214
|
-
console.error(`[PROXY ALERT] ${message}`, data);
|
|
1215
|
-
this.alerts.push({ message, data, timestamp: new Date() });
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
```
|
|
1219
|
-
|
|
1220
|
-
### 8.4 Combinar com Rotação de Fingerprint
|
|
1221
|
-
|
|
1222
|
-
```javascript
|
|
1223
|
-
import { PlaywrightCrawler, ProxyConfiguration } from 'crawlee';
|
|
1224
|
-
|
|
1225
|
-
class FingerprintProxyRotator {
|
|
1226
|
-
constructor(proxies) {
|
|
1227
|
-
this.proxies = proxies;
|
|
1228
|
-
this.fingerprintProxyMap = new Map();
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
getProxyForFingerprint(fingerprint) {
|
|
1232
|
-
// Mapear fingerprint para proxy específico
|
|
1233
|
-
if (!this.fingerprintProxyMap.has(fingerprint)) {
|
|
1234
|
-
const proxy = this.proxies[this.fingerprintProxyMap.size % this.proxies.length];
|
|
1235
|
-
this.fingerprintProxyMap.set(fingerprint, proxy);
|
|
1236
|
-
}
|
|
1237
|
-
return this.fingerprintProxyMap.get(fingerprint);
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
// Usar com Crawlee
|
|
1242
|
-
const rotator = new FingerprintProxyRotator(proxies);
|
|
1243
|
-
|
|
1244
|
-
const crawler = new PlaywrightCrawler({
|
|
1245
|
-
browserPoolOptions: {
|
|
1246
|
-
useFingerprints: true,
|
|
1247
|
-
},
|
|
1248
|
-
proxyConfiguration: new ProxyConfiguration({
|
|
1249
|
-
newUrlFunction: (sessionId) => {
|
|
1250
|
-
// sessionId contém informação do fingerprint
|
|
1251
|
-
return rotator.getProxyForFingerprint(sessionId);
|
|
1252
|
-
},
|
|
1253
|
-
}),
|
|
1254
|
-
});
|
|
1255
|
-
```
|
|
1256
|
-
|
|
1257
|
-
---
|
|
1258
|
-
|
|
1259
|
-
## 9. Exemplos de Implementação
|
|
1260
|
-
|
|
1261
|
-
### 9.1 Exemplo Completo: Proxy Pool com Health Checking
|
|
1262
|
-
|
|
1263
|
-
```javascript
|
|
1264
|
-
import { PlaywrightCrawler, ProxyConfiguration } from 'crawlee';
|
|
1265
|
-
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
1266
|
-
import { SocksProxyAgent } from 'socks-proxy-agent';
|
|
1267
|
-
|
|
1268
|
-
class ProductionProxyPool {
|
|
1269
|
-
constructor(proxies, options = {}) {
|
|
1270
|
-
this.proxies = new Map();
|
|
1271
|
-
this.graveyard = new Map();
|
|
1272
|
-
this.maxFailures = options.maxFailures || 3;
|
|
1273
|
-
this.reviveTimer = options.reviveTimer || 300000;
|
|
1274
|
-
this.healthCheckInterval = options.healthCheckInterval || 60000;
|
|
1275
|
-
this.currentIndex = 0;
|
|
1276
|
-
|
|
1277
|
-
// Inicializar proxies
|
|
1278
|
-
for (const proxy of proxies) {
|
|
1279
|
-
this.proxies.set(proxy, {
|
|
1280
|
-
failures: 0,
|
|
1281
|
-
successes: 0,
|
|
1282
|
-
lastUsed: null,
|
|
1283
|
-
lastError: null,
|
|
1284
|
-
status: 'healthy',
|
|
1285
|
-
responseTime: 0,
|
|
1286
|
-
});
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
// Iniciar health check periódico
|
|
1290
|
-
this.startHealthCheck();
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
startHealthCheck() {
|
|
1294
|
-
setInterval(() => this.performHealthCheck(), this.healthCheckInterval);
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
async performHealthCheck() {
|
|
1298
|
-
console.log('Performing health check...');
|
|
1299
|
-
|
|
1300
|
-
for (const [proxy, stat] of this.proxies) {
|
|
1301
|
-
if (stat.status !== 'healthy') continue;
|
|
1302
|
-
|
|
1303
|
-
try {
|
|
1304
|
-
const agent = this.createAgent(proxy);
|
|
1305
|
-
const startTime = Date.now();
|
|
1306
|
-
|
|
1307
|
-
await fetch('http://httpbin.org/ip', {
|
|
1308
|
-
signal: AbortSignal.timeout(5000),
|
|
1309
|
-
dispatcher: agent,
|
|
1310
|
-
});
|
|
1311
|
-
|
|
1312
|
-
const responseTime = Date.now() - startTime;
|
|
1313
|
-
stat.responseTime = responseTime;
|
|
1314
|
-
stat.status = 'healthy';
|
|
1315
|
-
} catch (error) {
|
|
1316
|
-
stat.failures++;
|
|
1317
|
-
if (stat.failures >= this.maxFailures) {
|
|
1318
|
-
stat.status = 'dead';
|
|
1319
|
-
this.graveyard.set(proxy, { ...stat, buriedAt: Date.now() });
|
|
1320
|
-
this.proxies.delete(proxy);
|
|
1321
|
-
console.log(`Proxy buried: ${proxy}`);
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
// Reviver proxies
|
|
1327
|
-
this.reviveProxies();
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
createAgent(proxy) {
|
|
1331
|
-
if (proxy.startsWith('socks')) {
|
|
1332
|
-
return new SocksProxyAgent(proxy);
|
|
1333
|
-
}
|
|
1334
|
-
return new HttpsProxyAgent(proxy);
|
|
1335
|
-
}
|
|
1336
|
-
|
|
1337
|
-
reviveProxies() {
|
|
1338
|
-
const now = Date.now();
|
|
1339
|
-
for (const [proxy, stat] of this.graveyard) {
|
|
1340
|
-
if (now - stat.buriedAt >= this.reviveTimer) {
|
|
1341
|
-
this.proxies.set(proxy, {
|
|
1342
|
-
failures: 0,
|
|
1343
|
-
successes: 0,
|
|
1344
|
-
lastUsed: null,
|
|
1345
|
-
lastError: null,
|
|
1346
|
-
status: 'healthy',
|
|
1347
|
-
responseTime: 0,
|
|
1348
|
-
});
|
|
1349
|
-
this.graveyard.delete(proxy);
|
|
1350
|
-
console.log(`Proxy revived: ${proxy}`);
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
getNextProxy() {
|
|
1356
|
-
const healthyProxies = Array.from(this.proxies.entries())
|
|
1357
|
-
.filter(([_, stat]) => stat.status === 'healthy')
|
|
1358
|
-
.sort((a, b) => a[1].responseTime - b[1].responseTime);
|
|
1359
|
-
|
|
1360
|
-
if (healthyProxies.length === 0) {
|
|
1361
|
-
throw new Error('No healthy proxies available');
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
const proxy = healthyProxies[0][0];
|
|
1365
|
-
const stat = this.proxies.get(proxy);
|
|
1366
|
-
stat.lastUsed = Date.now();
|
|
1367
|
-
|
|
1368
|
-
return proxy;
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
reportSuccess(proxy) {
|
|
1372
|
-
const stat = this.proxies.get(proxy);
|
|
1373
|
-
if (stat) {
|
|
1374
|
-
stat.successes++;
|
|
1375
|
-
stat.failures = Math.max(0, stat.failures - 1);
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
reportFailure(proxy, error) {
|
|
1380
|
-
const stat = this.proxies.get(proxy);
|
|
1381
|
-
if (stat) {
|
|
1382
|
-
stat.failures++;
|
|
1383
|
-
stat.lastError = error;
|
|
1384
|
-
if (stat.failures >= this.maxFailures) {
|
|
1385
|
-
stat.status = 'dead';
|
|
1386
|
-
this.graveyard.set(proxy, { ...stat, buriedAt: Date.now() });
|
|
1387
|
-
this.proxies.delete(proxy);
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
getStats() {
|
|
1393
|
-
const healthy = Array.from(this.proxies.values()).filter(s => s.status === 'healthy').length;
|
|
1394
|
-
return {
|
|
1395
|
-
healthy,
|
|
1396
|
-
dead: this.graveyard.size,
|
|
1397
|
-
total: this.proxies.size + this.graveyard.size,
|
|
1398
|
-
};
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
// Uso principal
|
|
1403
|
-
const pool = new ProductionProxyPool([
|
|
1404
|
-
'http://user:pass@proxy1.com:8080',
|
|
1405
|
-
'http://user:pass@proxy2.com:8080',
|
|
1406
|
-
'socks5://user:pass@proxy3.com:1080',
|
|
1407
|
-
], {
|
|
1408
|
-
maxFailures: 3,
|
|
1409
|
-
reviveTimer: 300000,
|
|
1410
|
-
healthCheckInterval: 60000,
|
|
1411
|
-
});
|
|
1412
|
-
|
|
1413
|
-
const crawler = new PlaywrightCrawler({
|
|
1414
|
-
proxyConfiguration: new ProxyConfiguration({
|
|
1415
|
-
newUrlFunction: () => pool.getNextProxy(),
|
|
1416
|
-
}),
|
|
1417
|
-
requestHandler: async ({ request, page, proxyInfo }) => {
|
|
1418
|
-
try {
|
|
1419
|
-
await page.goto(request.url, { timeout: 30000 });
|
|
1420
|
-
pool.reportSuccess(proxyInfo.url);
|
|
1421
|
-
return { url: request.url, title: await page.title() };
|
|
1422
|
-
} catch (error) {
|
|
1423
|
-
pool.reportFailure(proxyInfo.url, error.message);
|
|
1424
|
-
throw error;
|
|
1425
|
-
}
|
|
1426
|
-
},
|
|
1427
|
-
maxConcurrency: 5,
|
|
1428
|
-
retryOnBlocked: true,
|
|
1429
|
-
});
|
|
1430
|
-
|
|
1431
|
-
await crawler.run(['https://example.com']);
|
|
1432
|
-
console.log('Pool stats:', pool.getStats());
|
|
1433
|
-
```
|
|
1434
|
-
|
|
1435
|
-
### 9.2 Exemplo: Session-Based Proxy com Crawlee
|
|
1436
|
-
|
|
1437
|
-
```javascript
|
|
1438
|
-
import { PlaywrightCrawler, SessionPool, ProxyConfiguration } from 'crawlee';
|
|
1439
|
-
|
|
1440
|
-
class SessionProxyManager {
|
|
1441
|
-
constructor(proxies) {
|
|
1442
|
-
this.proxies = proxies;
|
|
1443
|
-
this.sessionProxies = new Map();
|
|
1444
|
-
}
|
|
1445
|
-
|
|
1446
|
-
getProxyForSession(sessionId) {
|
|
1447
|
-
if (!this.sessionProxies.has(sessionId)) {
|
|
1448
|
-
const proxy = this.proxies[this.sessionProxies.size % this.proxies.length];
|
|
1449
|
-
this.sessionProxies.set(sessionId, proxy);
|
|
1450
|
-
}
|
|
1451
|
-
return this.sessionProxies.get(sessionId);
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
const manager = new SessionProxyManager([
|
|
1456
|
-
'http://proxy1.com:8080',
|
|
1457
|
-
'http://proxy2.com:8080',
|
|
1458
|
-
'http://proxy3.com:8080',
|
|
1459
|
-
]);
|
|
1460
|
-
|
|
1461
|
-
const crawler = new PlaywrightCrawler({
|
|
1462
|
-
useSessionPool: true,
|
|
1463
|
-
sessionOptions: {
|
|
1464
|
-
maxAgeSecs: 3600,
|
|
1465
|
-
maxUsageCount: 50,
|
|
1466
|
-
},
|
|
1467
|
-
proxyConfiguration: new ProxyConfiguration({
|
|
1468
|
-
newUrlFunction: (sessionId) => manager.getProxyForSession(sessionId),
|
|
1469
|
-
}),
|
|
1470
|
-
requestHandler: async ({ request, page, session }) => {
|
|
1471
|
-
console.log(`Session: ${session.id}, Proxy: ${manager.getProxyForSession(session.id)}`);
|
|
1472
|
-
|
|
1473
|
-
await page.goto(request.url);
|
|
1474
|
-
const title = await page.title();
|
|
1475
|
-
|
|
1476
|
-
session.retireOnBlocked(); // Retirar sessão se bloqueada
|
|
1477
|
-
|
|
1478
|
-
return { url: request.url, title, sessionId: session.id };
|
|
1479
|
-
},
|
|
1480
|
-
});
|
|
1481
|
-
|
|
1482
|
-
await crawler.run(['https://example.com']);
|
|
1483
|
-
```
|
|
1484
|
-
|
|
1485
|
-
---
|
|
1486
|
-
|
|
1487
|
-
## Referências
|
|
1488
|
-
|
|
1489
|
-
1. Crawlee ProxyConfiguration - https://crawlee.dev/docs/api/proxy-configuration
|
|
1490
|
-
2. https-proxy-agent - https://github.com/TooTallNate/node-https-proxy-agent
|
|
1491
|
-
3. socks-proxy-agent - https://github.com/TooTallNate/node-socks-proxy-agent
|
|
1492
|
-
4. socks - https://github.com/JoshGlazebrook/socks
|
|
1493
|
-
5. proxy-chain - https://github.com/apify/proxy-chain
|
|
1494
|
-
6. rezo - https://github.com/rezo-proxy/manager
|
|
1495
|
-
7. proxy-rotator-js - https://github.com/nicedoc/proxy-rotator
|