@skrillex1224/playwright-toolkit 2.1.166 → 2.1.168
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/dist/browser.js +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +450 -794
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +447 -792
- package/dist/index.js.map +4 -4
- package/dist/proxy-meter.js +549 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -93,10 +93,10 @@ var createActorInfo = (info) => {
|
|
|
93
93
|
xurl
|
|
94
94
|
};
|
|
95
95
|
};
|
|
96
|
-
const buildLandingUrl = ({ protocol: protocol2, domain: domain2, path:
|
|
96
|
+
const buildLandingUrl = ({ protocol: protocol2, domain: domain2, path: path3 }) => {
|
|
97
97
|
const safeProtocol = String(protocol2).trim();
|
|
98
98
|
const safeDomain = normalizeDomain(domain2);
|
|
99
|
-
const safePath = normalizePath(
|
|
99
|
+
const safePath = normalizePath(path3);
|
|
100
100
|
return `${safeProtocol}://${safeDomain}${safePath}`;
|
|
101
101
|
};
|
|
102
102
|
const buildIcon = ({ key }) => {
|
|
@@ -104,13 +104,13 @@ var createActorInfo = (info) => {
|
|
|
104
104
|
};
|
|
105
105
|
const protocol = info.protocol || "https";
|
|
106
106
|
const domain = normalizeDomain(info.domain);
|
|
107
|
-
const
|
|
107
|
+
const path2 = normalizePath(info.path);
|
|
108
108
|
const share = normalizeShare2(info.share);
|
|
109
109
|
return {
|
|
110
110
|
...info,
|
|
111
111
|
protocol,
|
|
112
112
|
domain,
|
|
113
|
-
path,
|
|
113
|
+
path: path2,
|
|
114
114
|
share,
|
|
115
115
|
get icon() {
|
|
116
116
|
if (info.icon) return info.icon;
|
|
@@ -124,7 +124,7 @@ var createActorInfo = (info) => {
|
|
|
124
124
|
var ActorInfo = {
|
|
125
125
|
qbot: createActorInfo({
|
|
126
126
|
key: "qbot",
|
|
127
|
-
name: "\u641C
|
|
127
|
+
name: "QQ\u6D4F\u89C8\u5668AI\u641C",
|
|
128
128
|
domain: "sogou.com",
|
|
129
129
|
path: "/web",
|
|
130
130
|
share: {
|
|
@@ -546,20 +546,361 @@ var CrawlerError = class _CrawlerError extends Error {
|
|
|
546
546
|
// src/apify-kit.js
|
|
547
547
|
import { serializeError as serializeError2 } from "serialize-error";
|
|
548
548
|
|
|
549
|
-
// src/
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
549
|
+
// src/proxy-meter-runtime.js
|
|
550
|
+
import { spawn, spawnSync } from "child_process";
|
|
551
|
+
import { existsSync, mkdirSync, readFileSync, rmSync } from "fs";
|
|
552
|
+
import { tmpdir } from "os";
|
|
553
|
+
import path from "path";
|
|
554
|
+
import { fileURLToPath } from "url";
|
|
555
|
+
var logger2 = createInternalLogger("ProxyMeter");
|
|
556
|
+
var MAX_TOP_DOMAINS = 20;
|
|
557
|
+
var FLUSH_INTERVAL_MS = 2e3;
|
|
558
|
+
var DEFAULT_DEBUG_MAX_EVENTS = 400;
|
|
559
|
+
var runtime = null;
|
|
560
|
+
var cleanupInstalled = false;
|
|
561
|
+
var observedDomainResourceTypes = /* @__PURE__ */ new Map();
|
|
562
|
+
var toSafeInt = (value) => {
|
|
563
|
+
const num = Number(value);
|
|
564
|
+
if (!Number.isFinite(num) || num <= 0) return 0;
|
|
565
|
+
return Math.round(num);
|
|
553
566
|
};
|
|
554
|
-
var
|
|
555
|
-
|
|
567
|
+
var toSafeFloat = (value) => {
|
|
568
|
+
const num = Number(value);
|
|
569
|
+
if (!Number.isFinite(num)) return 0;
|
|
570
|
+
return num;
|
|
571
|
+
};
|
|
572
|
+
var normalizeResourceType = (value) => {
|
|
573
|
+
const type = String(value || "").trim().toLowerCase();
|
|
574
|
+
if (!type) return "other";
|
|
575
|
+
return type;
|
|
576
|
+
};
|
|
577
|
+
var resolveHostname = (requestUrl) => {
|
|
578
|
+
const raw = String(requestUrl || "").trim();
|
|
579
|
+
if (!raw) return "";
|
|
580
|
+
try {
|
|
581
|
+
return String(new URL(raw).hostname || "").trim().toLowerCase();
|
|
582
|
+
} catch {
|
|
583
|
+
return "";
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
var recordDomainResourceType = (domain, resourceType) => {
|
|
587
|
+
const host = String(domain || "").trim().toLowerCase();
|
|
588
|
+
if (!host) return;
|
|
589
|
+
const type = normalizeResourceType(resourceType);
|
|
590
|
+
let byType = observedDomainResourceTypes.get(host);
|
|
591
|
+
if (!byType) {
|
|
592
|
+
byType = /* @__PURE__ */ new Map();
|
|
593
|
+
observedDomainResourceTypes.set(host, byType);
|
|
594
|
+
}
|
|
595
|
+
byType.set(type, (byType.get(type) || 0) + 1);
|
|
596
|
+
};
|
|
597
|
+
var resolveResourceTypeMeta = (domain) => {
|
|
598
|
+
const host = String(domain || "").trim().toLowerCase();
|
|
599
|
+
if (!host) return { resourceType: "", resourceTypeCounts: void 0 };
|
|
600
|
+
const byType = observedDomainResourceTypes.get(host);
|
|
601
|
+
if (!byType || byType.size === 0) {
|
|
602
|
+
return { resourceType: "", resourceTypeCounts: void 0 };
|
|
603
|
+
}
|
|
604
|
+
const entries = Array.from(byType.entries()).filter(([type, count]) => type && Number(count) > 0).sort((a, b) => {
|
|
605
|
+
if (Number(b[1]) !== Number(a[1])) return Number(b[1]) - Number(a[1]);
|
|
606
|
+
return String(a[0]).localeCompare(String(b[0]));
|
|
607
|
+
});
|
|
608
|
+
if (entries.length === 0) {
|
|
609
|
+
return { resourceType: "", resourceTypeCounts: void 0 };
|
|
610
|
+
}
|
|
611
|
+
return {
|
|
612
|
+
resourceType: entries[0][0],
|
|
613
|
+
resourceTypeCounts: Object.fromEntries(entries.map(([type, count]) => [type, toSafeInt(count)]))
|
|
614
|
+
};
|
|
615
|
+
};
|
|
616
|
+
var resolveScriptPath = () => {
|
|
617
|
+
const baseDir = typeof __dirname !== "undefined" ? __dirname : path.dirname(fileURLToPath(import.meta.url));
|
|
618
|
+
return path.join(baseDir, "proxy-meter.js");
|
|
619
|
+
};
|
|
620
|
+
var pickFreePort = () => {
|
|
621
|
+
const script = [
|
|
622
|
+
'const net=require("net");',
|
|
623
|
+
"const server=net.createServer();",
|
|
624
|
+
'server.listen(0,"127.0.0.1",()=>{',
|
|
625
|
+
"const port=server.address().port;",
|
|
626
|
+
"server.close(()=>{console.log(port);});",
|
|
627
|
+
"});"
|
|
628
|
+
].join("");
|
|
629
|
+
const result = spawnSync(process.execPath, ["-e", script], { encoding: "utf8" });
|
|
630
|
+
const port = Number(String(result.stdout || "").trim());
|
|
631
|
+
if (result.status === 0 && Number.isFinite(port) && port > 0) {
|
|
632
|
+
return port;
|
|
633
|
+
}
|
|
634
|
+
return 2e4 + Math.floor(Math.random() * 2e4);
|
|
635
|
+
};
|
|
636
|
+
var resolveLogDir = () => {
|
|
637
|
+
const storageDir = process.env.APIFY_STORAGE_DIR || process.env.APIFY_LOCAL_STORAGE_DIR || "";
|
|
638
|
+
if (storageDir) {
|
|
639
|
+
return path.join(storageDir, "proxy-meter");
|
|
640
|
+
}
|
|
641
|
+
return path.join(tmpdir(), "proxy-meter");
|
|
642
|
+
};
|
|
643
|
+
var ensureLogPath = () => {
|
|
644
|
+
const baseDir = resolveLogDir();
|
|
645
|
+
if (!existsSync(baseDir)) {
|
|
646
|
+
try {
|
|
647
|
+
mkdirSync(baseDir, { recursive: true });
|
|
648
|
+
} catch {
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
const runId = String(process.env.APIFY_ACTOR_RUN_ID || "").trim();
|
|
652
|
+
const suffix = `${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
653
|
+
const label = runId ? `proxy-meter-${runId}-${suffix}.json` : `proxy-meter-${process.pid}-${suffix}.json`;
|
|
654
|
+
return path.join(baseDir, label);
|
|
655
|
+
};
|
|
656
|
+
var readSnapshot = (logPath) => {
|
|
657
|
+
if (!logPath || !existsSync(logPath)) return null;
|
|
658
|
+
try {
|
|
659
|
+
const raw = readFileSync(logPath, "utf8");
|
|
660
|
+
if (!raw) return null;
|
|
661
|
+
return JSON.parse(raw);
|
|
662
|
+
} catch {
|
|
556
663
|
return null;
|
|
557
664
|
}
|
|
558
|
-
|
|
665
|
+
};
|
|
666
|
+
var normalizeDomainRows = (hosts) => {
|
|
667
|
+
const rows = [];
|
|
668
|
+
let requestCount = 0;
|
|
669
|
+
let connectCount = 0;
|
|
670
|
+
for (const [domain, stat] of Object.entries(hosts || {})) {
|
|
671
|
+
if (!stat || typeof stat !== "object") continue;
|
|
672
|
+
const inBytes = toSafeInt(stat.inBytes);
|
|
673
|
+
const outBytes = toSafeInt(stat.outBytes);
|
|
674
|
+
const requests = toSafeInt(stat.requests);
|
|
675
|
+
const connections = toSafeInt(stat.connections);
|
|
676
|
+
const totalBytes = inBytes + outBytes;
|
|
677
|
+
requestCount += requests;
|
|
678
|
+
connectCount += connections;
|
|
679
|
+
if (totalBytes <= 0 && requests <= 0 && connections <= 0) continue;
|
|
680
|
+
const resourceTypeMeta = resolveResourceTypeMeta(domain);
|
|
681
|
+
rows.push({
|
|
682
|
+
domain,
|
|
683
|
+
inBytes,
|
|
684
|
+
outBytes,
|
|
685
|
+
totalBytes,
|
|
686
|
+
requests,
|
|
687
|
+
connections,
|
|
688
|
+
resourceType: resourceTypeMeta.resourceType || void 0,
|
|
689
|
+
resourceTypeCounts: resourceTypeMeta.resourceTypeCounts || void 0
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
rows.sort((a, b) => {
|
|
693
|
+
if (b.totalBytes !== a.totalBytes) return b.totalBytes - a.totalBytes;
|
|
694
|
+
if (b.requests !== a.requests) return b.requests - a.requests;
|
|
695
|
+
return String(a.domain).localeCompare(String(b.domain));
|
|
696
|
+
});
|
|
697
|
+
return {
|
|
698
|
+
topDomains: rows.slice(0, MAX_TOP_DOMAINS),
|
|
699
|
+
requestCount,
|
|
700
|
+
connectCount
|
|
701
|
+
};
|
|
702
|
+
};
|
|
703
|
+
var normalizeDebugRows = (rows, type) => {
|
|
704
|
+
if (!Array.isArray(rows) || rows.length === 0) return void 0;
|
|
705
|
+
const normalized = rows.map((row) => {
|
|
706
|
+
if (!row || typeof row !== "object") return null;
|
|
707
|
+
return {
|
|
708
|
+
domain: String(row.domain || "").trim(),
|
|
709
|
+
status: String(row.status || "").trim(),
|
|
710
|
+
count: toSafeInt(row.count),
|
|
711
|
+
failedCount: toSafeInt(row.failedCount),
|
|
712
|
+
inBytes: toSafeInt(row.inBytes),
|
|
713
|
+
outBytes: toSafeInt(row.outBytes),
|
|
714
|
+
totalBytes: toSafeInt(row.totalBytes),
|
|
715
|
+
avgDurationMs: toSafeFloat(row.avgDurationMs),
|
|
716
|
+
reconnectCount: toSafeInt(row.reconnectCount),
|
|
717
|
+
largeResponseCount: toSafeInt(row.largeResponseCount),
|
|
718
|
+
failureRatePct: toSafeFloat(row.failureRatePct),
|
|
719
|
+
type
|
|
720
|
+
};
|
|
721
|
+
}).filter((row) => row && row.domain && row.count > 0);
|
|
722
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
723
|
+
};
|
|
724
|
+
var normalizeDebugEvent = (row) => {
|
|
725
|
+
if (!row || typeof row !== "object") return null;
|
|
726
|
+
const host = String(row.host || "").trim();
|
|
727
|
+
if (!host) return null;
|
|
728
|
+
return {
|
|
729
|
+
ts: String(row.ts || ""),
|
|
730
|
+
runId: String(row.runId || ""),
|
|
731
|
+
channel: String(row.channel || ""),
|
|
732
|
+
host,
|
|
733
|
+
method: String(row.method || ""),
|
|
734
|
+
path: String(row.path || ""),
|
|
735
|
+
statusCode: toSafeInt(row.statusCode),
|
|
736
|
+
durationMs: toSafeInt(row.durationMs),
|
|
737
|
+
inBytes: toSafeInt(row.inBytes),
|
|
738
|
+
outBytes: toSafeInt(row.outBytes),
|
|
739
|
+
totalBytes: toSafeInt(row.totalBytes),
|
|
740
|
+
error: String(row.error || "")
|
|
741
|
+
};
|
|
742
|
+
};
|
|
743
|
+
var normalizeDebugSummary = (debug) => {
|
|
744
|
+
if (!debug || typeof debug !== "object" || !debug.summary || typeof debug.summary !== "object") {
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
const summary = debug.summary;
|
|
748
|
+
const domainStatus = normalizeDebugRows(summary.domainStatus, "domain_status");
|
|
749
|
+
const topFailureDomains = normalizeDebugRows(summary.topFailureDomains, "top_failure");
|
|
750
|
+
const topLargeDomains = normalizeDebugRows(summary.topLargeDomains, "top_large");
|
|
751
|
+
const topReconnectDomains = normalizeDebugRows(summary.topReconnectDomains, "top_reconnect");
|
|
752
|
+
return {
|
|
753
|
+
enabled: Boolean(debug.enabled),
|
|
754
|
+
sampledEvents: toSafeInt(debug.sampledEvents),
|
|
755
|
+
droppedEvents: toSafeInt(debug.droppedEvents),
|
|
756
|
+
totalEvents: toSafeInt(debug.totalEvents),
|
|
757
|
+
largeResponseThresholdBytes: toSafeInt(summary.largeResponseThresholdBytes),
|
|
758
|
+
requestCount: toSafeInt(summary.requestCount),
|
|
759
|
+
failedCount: toSafeInt(summary.failedCount),
|
|
760
|
+
failureRatePct: toSafeFloat(summary.failureRatePct),
|
|
761
|
+
largeResponseCount: toSafeInt(summary.largeResponseCount),
|
|
762
|
+
reconnectCount: toSafeInt(summary.reconnectCount),
|
|
763
|
+
domainStatus,
|
|
764
|
+
topFailureDomains,
|
|
765
|
+
topLargeDomains,
|
|
766
|
+
topReconnectDomains
|
|
767
|
+
};
|
|
768
|
+
};
|
|
769
|
+
var normalizeSnapshot = (raw) => {
|
|
770
|
+
if (!raw || typeof raw !== "object") return null;
|
|
771
|
+
const totalIn = toSafeInt(raw.totalInBytes);
|
|
772
|
+
const totalOut = toSafeInt(raw.totalOutBytes);
|
|
773
|
+
const domains = normalizeDomainRows(raw.hosts && typeof raw.hosts === "object" ? raw.hosts : {});
|
|
774
|
+
const normalized = {
|
|
775
|
+
meter: "proxy-meter-v1",
|
|
776
|
+
totalBytes: totalIn + totalOut,
|
|
777
|
+
uploadBytes: totalOut,
|
|
778
|
+
downloadBytes: totalIn,
|
|
779
|
+
requestCount: domains.requestCount,
|
|
780
|
+
connectCount: domains.connectCount,
|
|
781
|
+
topDomains: domains.topDomains
|
|
782
|
+
};
|
|
783
|
+
const debug = raw.debug && typeof raw.debug === "object" ? raw.debug : null;
|
|
784
|
+
const summary = normalizeDebugSummary(debug);
|
|
785
|
+
const events = Array.isArray(debug?.events) ? debug.events.map(normalizeDebugEvent).filter(Boolean) : [];
|
|
786
|
+
if (summary) {
|
|
787
|
+
normalized.trafficDebugSummary = summary;
|
|
788
|
+
}
|
|
789
|
+
if (events.length > 0) {
|
|
790
|
+
normalized.trafficDebugEvents = events;
|
|
791
|
+
}
|
|
792
|
+
const hasSignal = normalized.totalBytes > 0 || normalized.uploadBytes > 0 || normalized.downloadBytes > 0 || normalized.requestCount > 0 || normalized.connectCount > 0 || normalized.topDomains && normalized.topDomains.length > 0 || Boolean(summary) || events.length > 0;
|
|
793
|
+
if (!hasSignal) return null;
|
|
794
|
+
return normalized;
|
|
795
|
+
};
|
|
796
|
+
var registerCleanup = () => {
|
|
797
|
+
if (cleanupInstalled) return;
|
|
798
|
+
cleanupInstalled = true;
|
|
799
|
+
const shutdown = () => {
|
|
800
|
+
if (!runtime || !runtime.proc) return;
|
|
801
|
+
try {
|
|
802
|
+
runtime.proc.kill("SIGTERM");
|
|
803
|
+
} catch {
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
process.once("exit", shutdown);
|
|
807
|
+
process.once("SIGINT", shutdown);
|
|
808
|
+
process.once("SIGTERM", shutdown);
|
|
809
|
+
};
|
|
810
|
+
var startProxyMeter = (options = {}) => {
|
|
811
|
+
const upstreamUrl = String(options.proxyUrl || "").trim();
|
|
812
|
+
if (!upstreamUrl) return null;
|
|
813
|
+
if (runtime && runtime.proc) {
|
|
814
|
+
try {
|
|
815
|
+
runtime.proc.kill("SIGTERM");
|
|
816
|
+
} catch {
|
|
817
|
+
}
|
|
818
|
+
runtime = null;
|
|
819
|
+
}
|
|
820
|
+
observedDomainResourceTypes = /* @__PURE__ */ new Map();
|
|
821
|
+
const port = pickFreePort();
|
|
822
|
+
const logPath = ensureLogPath();
|
|
823
|
+
const scriptPath = resolveScriptPath();
|
|
824
|
+
const debugMode = Boolean(options.debugMode);
|
|
825
|
+
const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);
|
|
826
|
+
const env = {
|
|
827
|
+
...process.env,
|
|
828
|
+
PROXY_METER_PORT: String(port),
|
|
829
|
+
PROXY_METER_LOG: logPath,
|
|
830
|
+
PROXY_METER_UPSTREAM: upstreamUrl,
|
|
831
|
+
PROXY_METER_FLUSH_MS: String(FLUSH_INTERVAL_MS),
|
|
832
|
+
PROXY_METER_DEBUG: debugMode ? "1" : "0",
|
|
833
|
+
PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents)
|
|
834
|
+
};
|
|
835
|
+
const child = spawn(process.execPath, [scriptPath], {
|
|
836
|
+
env,
|
|
837
|
+
stdio: ["ignore", "ignore", "ignore"]
|
|
838
|
+
});
|
|
839
|
+
child.once("exit", (code) => {
|
|
840
|
+
if (code && code !== 0) {
|
|
841
|
+
logger2.warn(`[proxy-meter] exited with code ${code}`);
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
runtime = {
|
|
845
|
+
proc: child,
|
|
846
|
+
port,
|
|
847
|
+
logPath,
|
|
848
|
+
startedAt: Date.now()
|
|
849
|
+
};
|
|
850
|
+
registerCleanup();
|
|
851
|
+
return { server: `http://127.0.0.1:${port}` };
|
|
852
|
+
};
|
|
853
|
+
var recordProxyMeterResourceType = (requestUrl, resourceType) => {
|
|
854
|
+
if (!runtime) return;
|
|
855
|
+
const host = resolveHostname(requestUrl);
|
|
856
|
+
if (!host) return;
|
|
857
|
+
recordDomainResourceType(host, resourceType);
|
|
858
|
+
};
|
|
859
|
+
var stopProxyMeter = async () => {
|
|
860
|
+
if (!runtime) return null;
|
|
861
|
+
const { proc, logPath } = runtime;
|
|
862
|
+
if (!proc || proc.killed) {
|
|
863
|
+
runtime = null;
|
|
864
|
+
return logPath || null;
|
|
865
|
+
}
|
|
866
|
+
await new Promise((resolve) => {
|
|
867
|
+
const timeout = setTimeout(() => {
|
|
868
|
+
try {
|
|
869
|
+
proc.kill("SIGKILL");
|
|
870
|
+
} catch {
|
|
871
|
+
}
|
|
872
|
+
resolve();
|
|
873
|
+
}, 2e3);
|
|
874
|
+
proc.once("exit", () => {
|
|
875
|
+
clearTimeout(timeout);
|
|
876
|
+
resolve();
|
|
877
|
+
});
|
|
878
|
+
try {
|
|
879
|
+
proc.kill("SIGTERM");
|
|
880
|
+
} catch {
|
|
881
|
+
resolve();
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
runtime = null;
|
|
885
|
+
return logPath || null;
|
|
886
|
+
};
|
|
887
|
+
var getProxyMeterSnapshot = async (options = {}) => {
|
|
888
|
+
if (!runtime) return null;
|
|
889
|
+
const finalize = Boolean(options.finalize);
|
|
890
|
+
const logPath = finalize ? await stopProxyMeter() : runtime.logPath;
|
|
891
|
+
const raw = readSnapshot(logPath);
|
|
892
|
+
const snapshot = normalizeSnapshot(raw);
|
|
893
|
+
if (finalize && logPath) {
|
|
894
|
+
try {
|
|
895
|
+
rmSync(logPath, { force: true });
|
|
896
|
+
} catch {
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
return snapshot;
|
|
559
900
|
};
|
|
560
901
|
|
|
561
902
|
// src/apify-kit.js
|
|
562
|
-
var
|
|
903
|
+
var logger3 = createInternalLogger("ApifyKit");
|
|
563
904
|
async function createApifyKit() {
|
|
564
905
|
let apify = null;
|
|
565
906
|
try {
|
|
@@ -587,29 +928,29 @@ async function createApifyKit() {
|
|
|
587
928
|
const { times: retryTimes = 0, mode: retryMode = "direct", before: beforeRetry } = retry;
|
|
588
929
|
const executeAction = async (attemptNumber) => {
|
|
589
930
|
const attemptLabel = attemptNumber > 0 ? ` (\u91CD\u8BD5 #${attemptNumber})` : "";
|
|
590
|
-
|
|
931
|
+
logger3.start(`[Step] ${step}${attemptLabel}`);
|
|
591
932
|
try {
|
|
592
933
|
const result = await actionFn();
|
|
593
|
-
|
|
934
|
+
logger3.success(`[Step] ${step}${attemptLabel}`);
|
|
594
935
|
return { success: true, result };
|
|
595
936
|
} catch (error) {
|
|
596
|
-
|
|
937
|
+
logger3.fail(`[Step] ${step}${attemptLabel}`, error);
|
|
597
938
|
return { success: false, error };
|
|
598
939
|
}
|
|
599
940
|
};
|
|
600
941
|
const prepareForRetry = async (attemptNumber) => {
|
|
601
942
|
if (typeof beforeRetry === "function") {
|
|
602
|
-
|
|
943
|
+
logger3.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
|
|
603
944
|
await beforeRetry(page, attemptNumber);
|
|
604
|
-
|
|
945
|
+
logger3.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);
|
|
605
946
|
} else if (retryMode === "refresh") {
|
|
606
|
-
|
|
947
|
+
logger3.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
|
|
607
948
|
await page.reload({ waitUntil: "commit" });
|
|
608
|
-
|
|
949
|
+
logger3.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);
|
|
609
950
|
} else {
|
|
610
|
-
|
|
951
|
+
logger3.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
|
|
611
952
|
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
612
|
-
|
|
953
|
+
logger3.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);
|
|
613
954
|
}
|
|
614
955
|
};
|
|
615
956
|
let lastResult = await executeAction(0);
|
|
@@ -617,11 +958,11 @@ async function createApifyKit() {
|
|
|
617
958
|
return lastResult.result;
|
|
618
959
|
}
|
|
619
960
|
for (let attempt = 1; attempt <= retryTimes; attempt++) {
|
|
620
|
-
|
|
961
|
+
logger3.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);
|
|
621
962
|
try {
|
|
622
963
|
await prepareForRetry(attempt);
|
|
623
964
|
} catch (prepareError) {
|
|
624
|
-
|
|
965
|
+
logger3.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);
|
|
625
966
|
continue;
|
|
626
967
|
}
|
|
627
968
|
lastResult = await executeAction(attempt);
|
|
@@ -642,7 +983,7 @@ async function createApifyKit() {
|
|
|
642
983
|
base64 = `data:image/jpeg;base64,${buffer.toString("base64")}`;
|
|
643
984
|
}
|
|
644
985
|
} catch (snapErr) {
|
|
645
|
-
|
|
986
|
+
logger3.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);
|
|
646
987
|
}
|
|
647
988
|
await this.pushFailed(finalError, {
|
|
648
989
|
step,
|
|
@@ -676,7 +1017,7 @@ async function createApifyKit() {
|
|
|
676
1017
|
* @param {Object} data - 要推送的数据对象
|
|
677
1018
|
*/
|
|
678
1019
|
async pushSuccess(data) {
|
|
679
|
-
const traffic =
|
|
1020
|
+
const traffic = await getProxyMeterSnapshot({ finalize: true });
|
|
680
1021
|
await Actor2.pushData({
|
|
681
1022
|
// 固定为0
|
|
682
1023
|
code: Code.Success,
|
|
@@ -685,7 +1026,7 @@ async function createApifyKit() {
|
|
|
685
1026
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
686
1027
|
data
|
|
687
1028
|
});
|
|
688
|
-
|
|
1029
|
+
logger3.success("pushSuccess", "Data pushed");
|
|
689
1030
|
},
|
|
690
1031
|
/**
|
|
691
1032
|
* 推送失败数据的通用方法(私有方法,仅供runStep内部使用)
|
|
@@ -698,7 +1039,7 @@ async function createApifyKit() {
|
|
|
698
1039
|
const isCrawlerError = CrawlerError.isCrawlerError(error);
|
|
699
1040
|
const code = isCrawlerError ? error.code : Code.UnknownError;
|
|
700
1041
|
const context = isCrawlerError ? error.context : {};
|
|
701
|
-
const traffic =
|
|
1042
|
+
const traffic = await getProxyMeterSnapshot({ finalize: true });
|
|
702
1043
|
await Actor2.pushData({
|
|
703
1044
|
// 如果是 CrawlerError,使用其 code,否则使用默认 Failed code
|
|
704
1045
|
code,
|
|
@@ -709,7 +1050,7 @@ async function createApifyKit() {
|
|
|
709
1050
|
context,
|
|
710
1051
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
711
1052
|
});
|
|
712
|
-
|
|
1053
|
+
logger3.success("pushFailed", "Error data pushed");
|
|
713
1054
|
}
|
|
714
1055
|
};
|
|
715
1056
|
}
|
|
@@ -725,7 +1066,7 @@ var ApifyKit = {
|
|
|
725
1066
|
};
|
|
726
1067
|
|
|
727
1068
|
// src/internals/utils.js
|
|
728
|
-
var
|
|
1069
|
+
var logger4 = createInternalLogger("InternalUtils");
|
|
729
1070
|
var parseCookies = (cookieString, domain) => {
|
|
730
1071
|
const cookies = [];
|
|
731
1072
|
const pairs = cookieString.split(";").map((c) => c.trim());
|
|
@@ -743,7 +1084,7 @@ var parseCookies = (cookieString, domain) => {
|
|
|
743
1084
|
cookies.push(cookie);
|
|
744
1085
|
}
|
|
745
1086
|
}
|
|
746
|
-
|
|
1087
|
+
logger4.success("parseCookies", `parsed ${cookies.length} cookies`);
|
|
747
1088
|
return cookies;
|
|
748
1089
|
};
|
|
749
1090
|
|
|
@@ -786,7 +1127,7 @@ var Utils = {
|
|
|
786
1127
|
};
|
|
787
1128
|
|
|
788
1129
|
// src/anti-cheat.js
|
|
789
|
-
var
|
|
1130
|
+
var logger5 = createInternalLogger("AntiCheat");
|
|
790
1131
|
var BASE_CONFIG = Object.freeze({
|
|
791
1132
|
locale: "zh-CN",
|
|
792
1133
|
acceptLanguage: "zh-CN,zh;q=0.9",
|
|
@@ -848,7 +1189,7 @@ var AntiCheat = {
|
|
|
848
1189
|
// src/humanize.js
|
|
849
1190
|
import delay from "delay";
|
|
850
1191
|
import { createCursor } from "ghost-cursor-playwright";
|
|
851
|
-
var
|
|
1192
|
+
var logger6 = createInternalLogger("Humanize");
|
|
852
1193
|
var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
|
|
853
1194
|
function $GetCursor(page) {
|
|
854
1195
|
const cursor = $CursorWeakMap.get(page);
|
|
@@ -876,13 +1217,13 @@ var Humanize = {
|
|
|
876
1217
|
*/
|
|
877
1218
|
async initializeCursor(page) {
|
|
878
1219
|
if ($CursorWeakMap.has(page)) {
|
|
879
|
-
|
|
1220
|
+
logger6.debug("initializeCursor: cursor already exists, skipping");
|
|
880
1221
|
return;
|
|
881
1222
|
}
|
|
882
|
-
|
|
1223
|
+
logger6.start("initializeCursor", "creating cursor");
|
|
883
1224
|
const cursor = await createCursor(page);
|
|
884
1225
|
$CursorWeakMap.set(page, cursor);
|
|
885
|
-
|
|
1226
|
+
logger6.success("initializeCursor", "cursor initialized");
|
|
886
1227
|
},
|
|
887
1228
|
/**
|
|
888
1229
|
* 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
|
|
@@ -892,17 +1233,17 @@ var Humanize = {
|
|
|
892
1233
|
*/
|
|
893
1234
|
async humanMove(page, target) {
|
|
894
1235
|
const cursor = $GetCursor(page);
|
|
895
|
-
|
|
1236
|
+
logger6.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
|
|
896
1237
|
try {
|
|
897
1238
|
if (typeof target === "string") {
|
|
898
1239
|
const element = await page.$(target);
|
|
899
1240
|
if (!element) {
|
|
900
|
-
|
|
1241
|
+
logger6.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
|
|
901
1242
|
return false;
|
|
902
1243
|
}
|
|
903
1244
|
const box = await element.boundingBox();
|
|
904
1245
|
if (!box) {
|
|
905
|
-
|
|
1246
|
+
logger6.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
|
|
906
1247
|
return false;
|
|
907
1248
|
}
|
|
908
1249
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
|
|
@@ -918,10 +1259,10 @@ var Humanize = {
|
|
|
918
1259
|
await cursor.actions.move({ x, y });
|
|
919
1260
|
}
|
|
920
1261
|
}
|
|
921
|
-
|
|
1262
|
+
logger6.success("humanMove");
|
|
922
1263
|
return true;
|
|
923
1264
|
} catch (error) {
|
|
924
|
-
|
|
1265
|
+
logger6.fail("humanMove", error);
|
|
925
1266
|
throw error;
|
|
926
1267
|
}
|
|
927
1268
|
},
|
|
@@ -945,12 +1286,12 @@ var Humanize = {
|
|
|
945
1286
|
maxDurationMs = maxSteps * 220 + 800
|
|
946
1287
|
} = options;
|
|
947
1288
|
const targetDesc = typeof target === "string" ? target : "ElementHandle";
|
|
948
|
-
|
|
1289
|
+
logger6.start("humanScroll", `target=${targetDesc}`);
|
|
949
1290
|
let element;
|
|
950
1291
|
if (typeof target === "string") {
|
|
951
1292
|
element = await page.$(target);
|
|
952
1293
|
if (!element) {
|
|
953
|
-
|
|
1294
|
+
logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
|
|
954
1295
|
return { element: null, didScroll: false };
|
|
955
1296
|
}
|
|
956
1297
|
} else {
|
|
@@ -1025,26 +1366,26 @@ var Humanize = {
|
|
|
1025
1366
|
try {
|
|
1026
1367
|
for (let i = 0; i < maxSteps; i++) {
|
|
1027
1368
|
if (Date.now() - startTime > maxDurationMs) {
|
|
1028
|
-
|
|
1369
|
+
logger6.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
|
|
1029
1370
|
return { element, didScroll };
|
|
1030
1371
|
}
|
|
1031
1372
|
const status = await checkVisibility();
|
|
1032
1373
|
if (status.code === "VISIBLE") {
|
|
1033
1374
|
if (status.isFixed) {
|
|
1034
|
-
|
|
1375
|
+
logger6.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
1035
1376
|
} else {
|
|
1036
|
-
|
|
1377
|
+
logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
|
|
1037
1378
|
}
|
|
1038
|
-
|
|
1379
|
+
logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
1039
1380
|
return { element, didScroll };
|
|
1040
1381
|
}
|
|
1041
|
-
|
|
1382
|
+
logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
|
|
1042
1383
|
if (status.code === "OBSTRUCTED" && status.obstruction) {
|
|
1043
|
-
|
|
1384
|
+
logger6.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
|
|
1044
1385
|
}
|
|
1045
1386
|
const scrollRect = await getScrollableRect();
|
|
1046
1387
|
if (!scrollRect && status.isFixed) {
|
|
1047
|
-
|
|
1388
|
+
logger6.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
1048
1389
|
return { element, didScroll };
|
|
1049
1390
|
}
|
|
1050
1391
|
const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
|
|
@@ -1080,10 +1421,10 @@ var Humanize = {
|
|
|
1080
1421
|
didScroll = true;
|
|
1081
1422
|
await delay(this.jitterMs(20 + Math.random() * 40, 0.2));
|
|
1082
1423
|
}
|
|
1083
|
-
|
|
1424
|
+
logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
|
|
1084
1425
|
return { element, didScroll };
|
|
1085
1426
|
} catch (error) {
|
|
1086
|
-
|
|
1427
|
+
logger6.fail("humanScroll", error);
|
|
1087
1428
|
throw error;
|
|
1088
1429
|
}
|
|
1089
1430
|
},
|
|
@@ -1101,7 +1442,7 @@ var Humanize = {
|
|
|
1101
1442
|
const cursor = $GetCursor(page);
|
|
1102
1443
|
const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
|
|
1103
1444
|
const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
|
|
1104
|
-
|
|
1445
|
+
logger6.start("humanClick", `target=${targetDesc}`);
|
|
1105
1446
|
const restoreOnce = async () => {
|
|
1106
1447
|
if (restoreOnce.restored) return;
|
|
1107
1448
|
restoreOnce.restored = true;
|
|
@@ -1110,14 +1451,14 @@ var Humanize = {
|
|
|
1110
1451
|
await delay(this.jitterMs(1e3));
|
|
1111
1452
|
await restoreOnce.do();
|
|
1112
1453
|
} catch (restoreError) {
|
|
1113
|
-
|
|
1454
|
+
logger6.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
|
|
1114
1455
|
}
|
|
1115
1456
|
};
|
|
1116
1457
|
try {
|
|
1117
1458
|
if (target == null) {
|
|
1118
1459
|
await delay(this.jitterMs(reactionDelay, 0.4));
|
|
1119
1460
|
await cursor.actions.click();
|
|
1120
|
-
|
|
1461
|
+
logger6.success("humanClick", "Clicked current position");
|
|
1121
1462
|
return true;
|
|
1122
1463
|
}
|
|
1123
1464
|
let element;
|
|
@@ -1127,7 +1468,7 @@ var Humanize = {
|
|
|
1127
1468
|
if (throwOnMissing) {
|
|
1128
1469
|
throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
|
|
1129
1470
|
}
|
|
1130
|
-
|
|
1471
|
+
logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
|
|
1131
1472
|
return false;
|
|
1132
1473
|
}
|
|
1133
1474
|
} else {
|
|
@@ -1143,7 +1484,7 @@ var Humanize = {
|
|
|
1143
1484
|
if (throwOnMissing) {
|
|
1144
1485
|
throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
1145
1486
|
}
|
|
1146
|
-
|
|
1487
|
+
logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
|
|
1147
1488
|
return false;
|
|
1148
1489
|
}
|
|
1149
1490
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
|
|
@@ -1152,11 +1493,11 @@ var Humanize = {
|
|
|
1152
1493
|
await delay(this.jitterMs(reactionDelay, 0.4));
|
|
1153
1494
|
await cursor.actions.click();
|
|
1154
1495
|
await restoreOnce();
|
|
1155
|
-
|
|
1496
|
+
logger6.success("humanClick");
|
|
1156
1497
|
return true;
|
|
1157
1498
|
} catch (error) {
|
|
1158
1499
|
await restoreOnce();
|
|
1159
|
-
|
|
1500
|
+
logger6.fail("humanClick", error);
|
|
1160
1501
|
throw error;
|
|
1161
1502
|
}
|
|
1162
1503
|
},
|
|
@@ -1167,9 +1508,9 @@ var Humanize = {
|
|
|
1167
1508
|
*/
|
|
1168
1509
|
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
1169
1510
|
const ms = this.jitterMs(baseMs, jitterPercent);
|
|
1170
|
-
|
|
1511
|
+
logger6.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
|
|
1171
1512
|
await delay(ms);
|
|
1172
|
-
|
|
1513
|
+
logger6.success("randomSleep");
|
|
1173
1514
|
},
|
|
1174
1515
|
/**
|
|
1175
1516
|
* 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
|
|
@@ -1179,7 +1520,7 @@ var Humanize = {
|
|
|
1179
1520
|
async simulateGaze(page, baseDurationMs = 2500) {
|
|
1180
1521
|
const cursor = $GetCursor(page);
|
|
1181
1522
|
const durationMs = this.jitterMs(baseDurationMs, 0.4);
|
|
1182
|
-
|
|
1523
|
+
logger6.start("simulateGaze", `duration=${durationMs}ms`);
|
|
1183
1524
|
const startTime = Date.now();
|
|
1184
1525
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
1185
1526
|
while (Date.now() - startTime < durationMs) {
|
|
@@ -1188,7 +1529,7 @@ var Humanize = {
|
|
|
1188
1529
|
await cursor.actions.move({ x, y });
|
|
1189
1530
|
await delay(this.jitterMs(600, 0.5));
|
|
1190
1531
|
}
|
|
1191
|
-
|
|
1532
|
+
logger6.success("simulateGaze");
|
|
1192
1533
|
},
|
|
1193
1534
|
/**
|
|
1194
1535
|
* 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
|
|
@@ -1201,7 +1542,7 @@ var Humanize = {
|
|
|
1201
1542
|
* @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
|
|
1202
1543
|
*/
|
|
1203
1544
|
async humanType(page, selector, text, options = {}) {
|
|
1204
|
-
|
|
1545
|
+
logger6.start("humanType", `selector=${selector}, textLen=${text.length}`);
|
|
1205
1546
|
const {
|
|
1206
1547
|
baseDelay = 180,
|
|
1207
1548
|
pauseProbability = 0.08,
|
|
@@ -1225,13 +1566,13 @@ var Humanize = {
|
|
|
1225
1566
|
await delay(charDelay);
|
|
1226
1567
|
if (Math.random() < pauseProbability && i < text.length - 1) {
|
|
1227
1568
|
const pauseTime = this.jitterMs(pauseBase, 0.5);
|
|
1228
|
-
|
|
1569
|
+
logger6.debug(`\u505C\u987F ${pauseTime}ms...`);
|
|
1229
1570
|
await delay(pauseTime);
|
|
1230
1571
|
}
|
|
1231
1572
|
}
|
|
1232
|
-
|
|
1573
|
+
logger6.success("humanType");
|
|
1233
1574
|
} catch (error) {
|
|
1234
|
-
|
|
1575
|
+
logger6.fail("humanType", error);
|
|
1235
1576
|
throw error;
|
|
1236
1577
|
}
|
|
1237
1578
|
},
|
|
@@ -1241,22 +1582,22 @@ var Humanize = {
|
|
|
1241
1582
|
* @param {string} selector - 输入框选择器
|
|
1242
1583
|
*/
|
|
1243
1584
|
async humanClear(page, selector) {
|
|
1244
|
-
|
|
1585
|
+
logger6.start("humanClear", `selector=${selector}`);
|
|
1245
1586
|
try {
|
|
1246
1587
|
const locator = page.locator(selector);
|
|
1247
1588
|
await locator.click();
|
|
1248
1589
|
await delay(this.jitterMs(200, 0.4));
|
|
1249
1590
|
const currentValue = await locator.inputValue();
|
|
1250
1591
|
if (!currentValue || currentValue.length === 0) {
|
|
1251
|
-
|
|
1592
|
+
logger6.success("humanClear", "already empty");
|
|
1252
1593
|
return;
|
|
1253
1594
|
}
|
|
1254
1595
|
await page.keyboard.press("Meta+A");
|
|
1255
1596
|
await delay(this.jitterMs(100, 0.4));
|
|
1256
1597
|
await page.keyboard.press("Backspace");
|
|
1257
|
-
|
|
1598
|
+
logger6.success("humanClear");
|
|
1258
1599
|
} catch (error) {
|
|
1259
|
-
|
|
1600
|
+
logger6.fail("humanClear", error);
|
|
1260
1601
|
throw error;
|
|
1261
1602
|
}
|
|
1262
1603
|
},
|
|
@@ -1268,7 +1609,7 @@ var Humanize = {
|
|
|
1268
1609
|
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
1269
1610
|
const cursor = $GetCursor(page);
|
|
1270
1611
|
const durationMs = this.jitterMs(baseDuration, 0.4);
|
|
1271
|
-
|
|
1612
|
+
logger6.start("warmUpBrowsing", `duration=${durationMs}ms`);
|
|
1272
1613
|
const startTime = Date.now();
|
|
1273
1614
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
1274
1615
|
try {
|
|
@@ -1287,9 +1628,9 @@ var Humanize = {
|
|
|
1287
1628
|
await delay(this.jitterMs(800, 0.5));
|
|
1288
1629
|
}
|
|
1289
1630
|
}
|
|
1290
|
-
|
|
1631
|
+
logger6.success("warmUpBrowsing");
|
|
1291
1632
|
} catch (error) {
|
|
1292
|
-
|
|
1633
|
+
logger6.fail("warmUpBrowsing", error);
|
|
1293
1634
|
throw error;
|
|
1294
1635
|
}
|
|
1295
1636
|
},
|
|
@@ -1303,7 +1644,7 @@ var Humanize = {
|
|
|
1303
1644
|
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
1304
1645
|
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
1305
1646
|
const actualDistance = this.jitterMs(distance, 0.15);
|
|
1306
|
-
|
|
1647
|
+
logger6.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
|
|
1307
1648
|
const sign = direction === "down" ? 1 : -1;
|
|
1308
1649
|
const stepDistance = actualDistance / steps;
|
|
1309
1650
|
try {
|
|
@@ -1315,9 +1656,9 @@ var Humanize = {
|
|
|
1315
1656
|
const baseDelay = 60 + i * 25;
|
|
1316
1657
|
await delay(this.jitterMs(baseDelay, 0.3));
|
|
1317
1658
|
}
|
|
1318
|
-
|
|
1659
|
+
logger6.success("naturalScroll");
|
|
1319
1660
|
} catch (error) {
|
|
1320
|
-
|
|
1661
|
+
logger6.fail("naturalScroll", error);
|
|
1321
1662
|
throw error;
|
|
1322
1663
|
}
|
|
1323
1664
|
}
|
|
@@ -1366,693 +1707,10 @@ var findMatchedByPassRule = (rules = [], requestUrl = "") => {
|
|
|
1366
1707
|
hostname
|
|
1367
1708
|
};
|
|
1368
1709
|
};
|
|
1369
|
-
var resolveRouteByProxy = ({
|
|
1370
|
-
requestUrl = "",
|
|
1371
|
-
enableProxy = false,
|
|
1372
|
-
byPassRules = []
|
|
1373
|
-
}) => {
|
|
1374
|
-
if (!enableProxy) {
|
|
1375
|
-
return { route: "direct", matchedRule: null, hostname: "" };
|
|
1376
|
-
}
|
|
1377
|
-
const matched = findMatchedByPassRule(byPassRules, requestUrl);
|
|
1378
|
-
if (!matched) {
|
|
1379
|
-
return { route: "proxy", matchedRule: null, hostname: "" };
|
|
1380
|
-
}
|
|
1381
|
-
if (matched.rule) {
|
|
1382
|
-
return { route: "direct", matchedRule: matched.rule, hostname: matched.hostname };
|
|
1383
|
-
}
|
|
1384
|
-
return { route: "proxy", matchedRule: null, hostname: matched.hostname };
|
|
1385
|
-
};
|
|
1386
|
-
|
|
1387
|
-
// src/traffic-meter.js
|
|
1388
|
-
var logger6 = createInternalLogger("TrafficMeter");
|
|
1389
|
-
var encoder = new TextEncoder();
|
|
1390
|
-
var MAX_DOMAIN_BUCKETS = 160;
|
|
1391
|
-
var MAX_REASON_BUCKETS = 64;
|
|
1392
|
-
var MAX_TOP_ITEMS = 12;
|
|
1393
|
-
var MAX_HINT_ITEMS = 8;
|
|
1394
|
-
var UNKNOWN_DOMAIN = "(unknown)";
|
|
1395
|
-
var OTHER_DOMAINS = "(other-domains)";
|
|
1396
|
-
var OTHER_REASONS = "(other-reasons)";
|
|
1397
|
-
var STATIC_RESOURCE_TYPES = /* @__PURE__ */ new Set([
|
|
1398
|
-
"script",
|
|
1399
|
-
"stylesheet",
|
|
1400
|
-
"image",
|
|
1401
|
-
"font",
|
|
1402
|
-
"media",
|
|
1403
|
-
"manifest"
|
|
1404
|
-
]);
|
|
1405
|
-
var BACKEND_RESOURCE_TYPES = /* @__PURE__ */ new Set([
|
|
1406
|
-
"xhr",
|
|
1407
|
-
"fetch",
|
|
1408
|
-
"websocket",
|
|
1409
|
-
"eventsource"
|
|
1410
|
-
]);
|
|
1411
|
-
var toSafeNumber = (value) => {
|
|
1412
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return 0;
|
|
1413
|
-
return Math.round(value);
|
|
1414
|
-
};
|
|
1415
|
-
var byteLength = (value) => {
|
|
1416
|
-
const text = String(value || "");
|
|
1417
|
-
if (!text) return 0;
|
|
1418
|
-
try {
|
|
1419
|
-
return encoder.encode(text).length;
|
|
1420
|
-
} catch {
|
|
1421
|
-
return text.length;
|
|
1422
|
-
}
|
|
1423
|
-
};
|
|
1424
|
-
var normalizeHeaderValue = (value) => {
|
|
1425
|
-
if (Array.isArray(value)) return value.join(",");
|
|
1426
|
-
if (value === null || value === void 0) return "";
|
|
1427
|
-
return String(value);
|
|
1428
|
-
};
|
|
1429
|
-
var estimateRequestBytes = (request = {}) => {
|
|
1430
|
-
const method = String(request.method || "GET");
|
|
1431
|
-
const url = String(request.url || "");
|
|
1432
|
-
let total = byteLength(`${method} ${url} HTTP/1.1\r
|
|
1433
|
-
`);
|
|
1434
|
-
const headers = request.headers && typeof request.headers === "object" ? request.headers : {};
|
|
1435
|
-
Object.entries(headers).forEach(([key, value]) => {
|
|
1436
|
-
total += byteLength(`${key}: ${normalizeHeaderValue(value)}\r
|
|
1437
|
-
`);
|
|
1438
|
-
});
|
|
1439
|
-
total += 2;
|
|
1440
|
-
if (typeof request.postData === "string" && request.postData) {
|
|
1441
|
-
total += byteLength(request.postData);
|
|
1442
|
-
}
|
|
1443
|
-
return total;
|
|
1444
|
-
};
|
|
1445
|
-
var createTrafficState = () => ({
|
|
1446
|
-
totalRequests: 0,
|
|
1447
|
-
proxyRequests: 0,
|
|
1448
|
-
directRequests: 0,
|
|
1449
|
-
totalUploadBytes: 0,
|
|
1450
|
-
proxyUploadBytes: 0,
|
|
1451
|
-
directUploadBytes: 0,
|
|
1452
|
-
totalDownloadBytes: 0,
|
|
1453
|
-
proxyDownloadBytes: 0,
|
|
1454
|
-
directDownloadBytes: 0,
|
|
1455
|
-
totalFailedRequests: 0,
|
|
1456
|
-
proxyFailedRequests: 0,
|
|
1457
|
-
directFailedRequests: 0,
|
|
1458
|
-
totalCanceledRequests: 0,
|
|
1459
|
-
proxyCanceledRequests: 0,
|
|
1460
|
-
directCanceledRequests: 0,
|
|
1461
|
-
orphanDataReceivedBytes: 0,
|
|
1462
|
-
orphanProxyDataReceivedBytes: 0,
|
|
1463
|
-
orphanFinishDeltaBytes: 0,
|
|
1464
|
-
orphanProxyFinishDeltaBytes: 0,
|
|
1465
|
-
domainStats: /* @__PURE__ */ new Map(),
|
|
1466
|
-
typeStats: /* @__PURE__ */ new Map(),
|
|
1467
|
-
failedReasonStats: /* @__PURE__ */ new Map()
|
|
1468
|
-
});
|
|
1469
|
-
var ensureRoute = (route) => route === "proxy" ? "proxy" : "direct";
|
|
1470
|
-
var normalizeResourceType = (value) => {
|
|
1471
|
-
const type = String(value || "").trim().toLowerCase();
|
|
1472
|
-
if (!type) return "other";
|
|
1473
|
-
if (type === "ws") return "websocket";
|
|
1474
|
-
return type;
|
|
1475
|
-
};
|
|
1476
|
-
var parseHostname = (url = "") => {
|
|
1477
|
-
try {
|
|
1478
|
-
const hostname = new URL(String(url || "")).hostname.toLowerCase();
|
|
1479
|
-
return hostname || "";
|
|
1480
|
-
} catch {
|
|
1481
|
-
return "";
|
|
1482
|
-
}
|
|
1483
|
-
};
|
|
1484
|
-
var normalizeDomainKey = (domain = "") => {
|
|
1485
|
-
const key = String(domain || "").trim().toLowerCase();
|
|
1486
|
-
return key || UNKNOWN_DOMAIN;
|
|
1487
|
-
};
|
|
1488
|
-
var isStaticType = (resourceType = "") => STATIC_RESOURCE_TYPES.has(normalizeResourceType(resourceType));
|
|
1489
|
-
var isBackendType = (resourceType = "") => BACKEND_RESOURCE_TYPES.has(normalizeResourceType(resourceType));
|
|
1490
|
-
var createDomainBucket = (domain) => ({
|
|
1491
|
-
domain,
|
|
1492
|
-
requests: 0,
|
|
1493
|
-
proxyRequests: 0,
|
|
1494
|
-
directRequests: 0,
|
|
1495
|
-
uploadBytes: 0,
|
|
1496
|
-
downloadBytes: 0,
|
|
1497
|
-
totalBytes: 0,
|
|
1498
|
-
proxyBytes: 0,
|
|
1499
|
-
directBytes: 0,
|
|
1500
|
-
failedRequests: 0,
|
|
1501
|
-
canceledRequests: 0,
|
|
1502
|
-
staticBytes: 0,
|
|
1503
|
-
backendBytes: 0
|
|
1504
|
-
});
|
|
1505
|
-
var createTypeBucket = (resourceType) => ({
|
|
1506
|
-
resourceType,
|
|
1507
|
-
requests: 0,
|
|
1508
|
-
proxyRequests: 0,
|
|
1509
|
-
directRequests: 0,
|
|
1510
|
-
uploadBytes: 0,
|
|
1511
|
-
downloadBytes: 0,
|
|
1512
|
-
totalBytes: 0,
|
|
1513
|
-
proxyBytes: 0,
|
|
1514
|
-
directBytes: 0,
|
|
1515
|
-
failedRequests: 0,
|
|
1516
|
-
canceledRequests: 0
|
|
1517
|
-
});
|
|
1518
|
-
var createReasonBucket = (reason) => ({
|
|
1519
|
-
reason,
|
|
1520
|
-
count: 0,
|
|
1521
|
-
canceledCount: 0,
|
|
1522
|
-
proxyCount: 0,
|
|
1523
|
-
directCount: 0
|
|
1524
|
-
});
|
|
1525
|
-
var formatBytes = (bytes = 0) => {
|
|
1526
|
-
const value = toSafeNumber(bytes);
|
|
1527
|
-
if (value <= 0) return "0B";
|
|
1528
|
-
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
1529
|
-
let size = value;
|
|
1530
|
-
let unit = 0;
|
|
1531
|
-
while (size >= 1024 && unit < units.length - 1) {
|
|
1532
|
-
size /= 1024;
|
|
1533
|
-
unit += 1;
|
|
1534
|
-
}
|
|
1535
|
-
const precision = size >= 100 || unit === 0 ? 0 : 2;
|
|
1536
|
-
return `${size.toFixed(precision)}${units[unit]}`;
|
|
1537
|
-
};
|
|
1538
|
-
var addRequests = (state, route, count = 1) => {
|
|
1539
|
-
const c = toSafeNumber(count);
|
|
1540
|
-
if (c <= 0) return;
|
|
1541
|
-
const normalizedRoute = ensureRoute(route);
|
|
1542
|
-
state.totalRequests += c;
|
|
1543
|
-
if (normalizedRoute === "proxy") {
|
|
1544
|
-
state.proxyRequests += c;
|
|
1545
|
-
return;
|
|
1546
|
-
}
|
|
1547
|
-
state.directRequests += c;
|
|
1548
|
-
};
|
|
1549
|
-
var addUploadBytes = (state, route, bytes = 0) => {
|
|
1550
|
-
const b = toSafeNumber(bytes);
|
|
1551
|
-
if (b <= 0) return;
|
|
1552
|
-
const normalizedRoute = ensureRoute(route);
|
|
1553
|
-
state.totalUploadBytes += b;
|
|
1554
|
-
if (normalizedRoute === "proxy") {
|
|
1555
|
-
state.proxyUploadBytes += b;
|
|
1556
|
-
return;
|
|
1557
|
-
}
|
|
1558
|
-
state.directUploadBytes += b;
|
|
1559
|
-
};
|
|
1560
|
-
var addDownloadBytes = (state, route, bytes = 0) => {
|
|
1561
|
-
const b = toSafeNumber(bytes);
|
|
1562
|
-
if (b <= 0) return;
|
|
1563
|
-
const normalizedRoute = ensureRoute(route);
|
|
1564
|
-
state.totalDownloadBytes += b;
|
|
1565
|
-
if (normalizedRoute === "proxy") {
|
|
1566
|
-
state.proxyDownloadBytes += b;
|
|
1567
|
-
return;
|
|
1568
|
-
}
|
|
1569
|
-
state.directDownloadBytes += b;
|
|
1570
|
-
};
|
|
1571
|
-
var incrementBucketRequests = (bucket, route) => {
|
|
1572
|
-
if (!bucket) return;
|
|
1573
|
-
bucket.requests += 1;
|
|
1574
|
-
if (ensureRoute(route) === "proxy") {
|
|
1575
|
-
bucket.proxyRequests += 1;
|
|
1576
|
-
return;
|
|
1577
|
-
}
|
|
1578
|
-
bucket.directRequests += 1;
|
|
1579
|
-
};
|
|
1580
|
-
var incrementBucketBytes = (bucket, route, bytes = 0, direction = "download", resourceType = "other") => {
|
|
1581
|
-
if (!bucket) return;
|
|
1582
|
-
const b = toSafeNumber(bytes);
|
|
1583
|
-
if (b <= 0) return;
|
|
1584
|
-
if (direction === "upload") {
|
|
1585
|
-
bucket.uploadBytes += b;
|
|
1586
|
-
} else {
|
|
1587
|
-
bucket.downloadBytes += b;
|
|
1588
|
-
}
|
|
1589
|
-
bucket.totalBytes += b;
|
|
1590
|
-
if (ensureRoute(route) === "proxy") {
|
|
1591
|
-
bucket.proxyBytes += b;
|
|
1592
|
-
} else {
|
|
1593
|
-
bucket.directBytes += b;
|
|
1594
|
-
}
|
|
1595
|
-
if (bucket.domain !== void 0) {
|
|
1596
|
-
if (isStaticType(resourceType)) {
|
|
1597
|
-
bucket.staticBytes += b;
|
|
1598
|
-
} else if (isBackendType(resourceType)) {
|
|
1599
|
-
bucket.backendBytes += b;
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
};
|
|
1603
|
-
var incrementBucketFailed = (bucket, canceled = false) => {
|
|
1604
|
-
if (!bucket) return;
|
|
1605
|
-
bucket.failedRequests += 1;
|
|
1606
|
-
if (canceled) {
|
|
1607
|
-
bucket.canceledRequests += 1;
|
|
1608
|
-
}
|
|
1609
|
-
};
|
|
1610
|
-
var ensureReasonText = (reason) => {
|
|
1611
|
-
const normalized = String(reason || "").trim().toLowerCase();
|
|
1612
|
-
return normalized || "unknown";
|
|
1613
|
-
};
|
|
1614
|
-
var pickDomainBucket = (state, domain = "") => {
|
|
1615
|
-
const domainKey = normalizeDomainKey(domain);
|
|
1616
|
-
const knownBucket = state.domainStats.get(domainKey);
|
|
1617
|
-
if (knownBucket) return knownBucket;
|
|
1618
|
-
if (state.domainStats.size < MAX_DOMAIN_BUCKETS) {
|
|
1619
|
-
const bucket2 = createDomainBucket(domainKey);
|
|
1620
|
-
state.domainStats.set(domainKey, bucket2);
|
|
1621
|
-
return bucket2;
|
|
1622
|
-
}
|
|
1623
|
-
const overflow = state.domainStats.get(OTHER_DOMAINS);
|
|
1624
|
-
if (overflow) return overflow;
|
|
1625
|
-
const bucket = createDomainBucket(OTHER_DOMAINS);
|
|
1626
|
-
state.domainStats.set(OTHER_DOMAINS, bucket);
|
|
1627
|
-
return bucket;
|
|
1628
|
-
};
|
|
1629
|
-
var pickTypeBucket = (state, resourceType = "other") => {
|
|
1630
|
-
const typeKey = normalizeResourceType(resourceType);
|
|
1631
|
-
const knownBucket = state.typeStats.get(typeKey);
|
|
1632
|
-
if (knownBucket) return knownBucket;
|
|
1633
|
-
const bucket = createTypeBucket(typeKey);
|
|
1634
|
-
state.typeStats.set(typeKey, bucket);
|
|
1635
|
-
return bucket;
|
|
1636
|
-
};
|
|
1637
|
-
var pickReasonBucket = (state, reason = "") => {
|
|
1638
|
-
const reasonKey = ensureReasonText(reason);
|
|
1639
|
-
const knownBucket = state.failedReasonStats.get(reasonKey);
|
|
1640
|
-
if (knownBucket) return knownBucket;
|
|
1641
|
-
if (state.failedReasonStats.size < MAX_REASON_BUCKETS) {
|
|
1642
|
-
const bucket2 = createReasonBucket(reasonKey);
|
|
1643
|
-
state.failedReasonStats.set(reasonKey, bucket2);
|
|
1644
|
-
return bucket2;
|
|
1645
|
-
}
|
|
1646
|
-
const overflow = state.failedReasonStats.get(OTHER_REASONS);
|
|
1647
|
-
if (overflow) return overflow;
|
|
1648
|
-
const bucket = createReasonBucket(OTHER_REASONS);
|
|
1649
|
-
state.failedReasonStats.set(OTHER_REASONS, bucket);
|
|
1650
|
-
return bucket;
|
|
1651
|
-
};
|
|
1652
|
-
var addRequestProfile = (state, route, domain, resourceType, uploadBytes = 0) => {
|
|
1653
|
-
const domainBucket = pickDomainBucket(state, domain);
|
|
1654
|
-
const typeBucket = pickTypeBucket(state, resourceType);
|
|
1655
|
-
incrementBucketRequests(domainBucket, route);
|
|
1656
|
-
incrementBucketRequests(typeBucket, route);
|
|
1657
|
-
incrementBucketBytes(domainBucket, route, uploadBytes, "upload", resourceType);
|
|
1658
|
-
incrementBucketBytes(typeBucket, route, uploadBytes, "upload", resourceType);
|
|
1659
|
-
};
|
|
1660
|
-
var addUploadProfile = (state, route, domain, resourceType, uploadBytes = 0) => {
|
|
1661
|
-
const domainBucket = pickDomainBucket(state, domain);
|
|
1662
|
-
const typeBucket = pickTypeBucket(state, resourceType);
|
|
1663
|
-
incrementBucketBytes(domainBucket, route, uploadBytes, "upload", resourceType);
|
|
1664
|
-
incrementBucketBytes(typeBucket, route, uploadBytes, "upload", resourceType);
|
|
1665
|
-
};
|
|
1666
|
-
var addDownloadProfile = (state, route, domain, resourceType, downloadBytes = 0) => {
|
|
1667
|
-
const domainBucket = pickDomainBucket(state, domain);
|
|
1668
|
-
const typeBucket = pickTypeBucket(state, resourceType);
|
|
1669
|
-
incrementBucketBytes(domainBucket, route, downloadBytes, "download", resourceType);
|
|
1670
|
-
incrementBucketBytes(typeBucket, route, downloadBytes, "download", resourceType);
|
|
1671
|
-
};
|
|
1672
|
-
var addFailedProfile = (state, route, domain, resourceType, reason = "unknown", canceled = false) => {
|
|
1673
|
-
const domainBucket = pickDomainBucket(state, domain);
|
|
1674
|
-
const typeBucket = pickTypeBucket(state, resourceType);
|
|
1675
|
-
const reasonBucket = pickReasonBucket(state, reason);
|
|
1676
|
-
incrementBucketFailed(domainBucket, canceled);
|
|
1677
|
-
incrementBucketFailed(typeBucket, canceled);
|
|
1678
|
-
reasonBucket.count += 1;
|
|
1679
|
-
if (ensureRoute(route) === "proxy") {
|
|
1680
|
-
reasonBucket.proxyCount += 1;
|
|
1681
|
-
} else {
|
|
1682
|
-
reasonBucket.directCount += 1;
|
|
1683
|
-
}
|
|
1684
|
-
if (canceled) {
|
|
1685
|
-
reasonBucket.canceledCount += 1;
|
|
1686
|
-
}
|
|
1687
|
-
};
|
|
1688
|
-
var toRoundedRatio = (numerator, denominator) => {
|
|
1689
|
-
if (denominator <= 0) return 0;
|
|
1690
|
-
return Number((numerator / denominator * 100).toFixed(2));
|
|
1691
|
-
};
|
|
1692
|
-
var sortByBytesAndRequests = (left, right) => {
|
|
1693
|
-
if (right.totalBytes !== left.totalBytes) return right.totalBytes - left.totalBytes;
|
|
1694
|
-
if (right.requests !== left.requests) return right.requests - left.requests;
|
|
1695
|
-
return String(left.domain || left.resourceType || "").localeCompare(String(right.domain || right.resourceType || ""));
|
|
1696
|
-
};
|
|
1697
|
-
var buildTopDomains = (state) => {
|
|
1698
|
-
return Array.from(state.domainStats.values()).filter((item) => item && item.totalBytes > 0).sort(sortByBytesAndRequests).slice(0, MAX_TOP_ITEMS).map((item) => ({
|
|
1699
|
-
domain: item.domain,
|
|
1700
|
-
requests: item.requests,
|
|
1701
|
-
proxyRequests: item.proxyRequests,
|
|
1702
|
-
directRequests: item.directRequests,
|
|
1703
|
-
uploadBytes: item.uploadBytes,
|
|
1704
|
-
downloadBytes: item.downloadBytes,
|
|
1705
|
-
totalBytes: item.totalBytes,
|
|
1706
|
-
proxyBytes: item.proxyBytes,
|
|
1707
|
-
directBytes: item.directBytes,
|
|
1708
|
-
failedRequests: item.failedRequests,
|
|
1709
|
-
canceledRequests: item.canceledRequests,
|
|
1710
|
-
staticBytes: item.staticBytes,
|
|
1711
|
-
backendBytes: item.backendBytes
|
|
1712
|
-
}));
|
|
1713
|
-
};
|
|
1714
|
-
var buildTopResourceTypes = (state) => {
|
|
1715
|
-
return Array.from(state.typeStats.values()).filter((item) => item && (item.totalBytes > 0 || item.requests > 0)).sort(sortByBytesAndRequests).slice(0, MAX_TOP_ITEMS).map((item) => ({
|
|
1716
|
-
resourceType: item.resourceType,
|
|
1717
|
-
requests: item.requests,
|
|
1718
|
-
proxyRequests: item.proxyRequests,
|
|
1719
|
-
directRequests: item.directRequests,
|
|
1720
|
-
uploadBytes: item.uploadBytes,
|
|
1721
|
-
downloadBytes: item.downloadBytes,
|
|
1722
|
-
totalBytes: item.totalBytes,
|
|
1723
|
-
proxyBytes: item.proxyBytes,
|
|
1724
|
-
directBytes: item.directBytes,
|
|
1725
|
-
failedRequests: item.failedRequests,
|
|
1726
|
-
canceledRequests: item.canceledRequests
|
|
1727
|
-
}));
|
|
1728
|
-
};
|
|
1729
|
-
var buildFailedReasons = (state) => {
|
|
1730
|
-
return Array.from(state.failedReasonStats.values()).filter((item) => item && item.count > 0).sort((left, right) => {
|
|
1731
|
-
if (right.count !== left.count) return right.count - left.count;
|
|
1732
|
-
return String(left.reason || "").localeCompare(String(right.reason || ""));
|
|
1733
|
-
}).slice(0, MAX_TOP_ITEMS).map((item) => ({
|
|
1734
|
-
reason: item.reason,
|
|
1735
|
-
count: item.count,
|
|
1736
|
-
canceledCount: item.canceledCount,
|
|
1737
|
-
proxyCount: item.proxyCount,
|
|
1738
|
-
directCount: item.directCount
|
|
1739
|
-
}));
|
|
1740
|
-
};
|
|
1741
|
-
var buildProxyByPassHints = (state) => {
|
|
1742
|
-
return Array.from(state.domainStats.values()).filter((item) => item && item.domain !== UNKNOWN_DOMAIN && item.domain !== OTHER_DOMAINS).filter((item) => item.proxyBytes >= 128 * 1024 && item.proxyRequests >= 2 && item.totalBytes > 0).filter((item) => item.staticBytes > item.backendBytes && toRoundedRatio(item.staticBytes, item.totalBytes) >= 80).sort((left, right) => {
|
|
1743
|
-
if (right.proxyBytes !== left.proxyBytes) return right.proxyBytes - left.proxyBytes;
|
|
1744
|
-
return right.proxyRequests - left.proxyRequests;
|
|
1745
|
-
}).slice(0, MAX_HINT_ITEMS).map((item) => ({
|
|
1746
|
-
domain: item.domain,
|
|
1747
|
-
proxyBytes: item.proxyBytes,
|
|
1748
|
-
proxyRequests: item.proxyRequests,
|
|
1749
|
-
totalBytes: item.totalBytes,
|
|
1750
|
-
staticBytes: item.staticBytes,
|
|
1751
|
-
backendBytes: item.backendBytes,
|
|
1752
|
-
staticRatioPct: toRoundedRatio(item.staticBytes, item.totalBytes)
|
|
1753
|
-
}));
|
|
1754
|
-
};
|
|
1755
|
-
var createTrafficMeter = ({
|
|
1756
|
-
enableProxy = false,
|
|
1757
|
-
byPassRules = [],
|
|
1758
|
-
debugMode = false
|
|
1759
|
-
} = {}) => {
|
|
1760
|
-
const state = createTrafficState();
|
|
1761
|
-
const requestMap = /* @__PURE__ */ new Map();
|
|
1762
|
-
const orphanReceivedMap = /* @__PURE__ */ new Map();
|
|
1763
|
-
const wsRouteMap = /* @__PURE__ */ new Map();
|
|
1764
|
-
const attachedPages = /* @__PURE__ */ new WeakSet();
|
|
1765
|
-
const attachedContexts = /* @__PURE__ */ new WeakSet();
|
|
1766
|
-
const resolveRoute = (url = "") => {
|
|
1767
|
-
return resolveRouteByProxy({
|
|
1768
|
-
requestUrl: url,
|
|
1769
|
-
enableProxy,
|
|
1770
|
-
byPassRules
|
|
1771
|
-
}).route;
|
|
1772
|
-
};
|
|
1773
|
-
const fallbackRoute = () => enableProxy ? "proxy" : "direct";
|
|
1774
|
-
const debugLog = (message) => {
|
|
1775
|
-
if (!debugMode) return;
|
|
1776
|
-
logger6.info(`[\u9010\u8BF7\u6C42\u8C03\u8BD5] ${message}`);
|
|
1777
|
-
};
|
|
1778
|
-
const addFailed = (route, canceled = false) => {
|
|
1779
|
-
const normalizedRoute = ensureRoute(route);
|
|
1780
|
-
state.totalFailedRequests += 1;
|
|
1781
|
-
if (normalizedRoute === "proxy") {
|
|
1782
|
-
state.proxyFailedRequests += 1;
|
|
1783
|
-
} else {
|
|
1784
|
-
state.directFailedRequests += 1;
|
|
1785
|
-
}
|
|
1786
|
-
if (!canceled) return;
|
|
1787
|
-
state.totalCanceledRequests += 1;
|
|
1788
|
-
if (normalizedRoute === "proxy") {
|
|
1789
|
-
state.proxyCanceledRequests += 1;
|
|
1790
|
-
} else {
|
|
1791
|
-
state.directCanceledRequests += 1;
|
|
1792
|
-
}
|
|
1793
|
-
};
|
|
1794
|
-
const finalizeByEncodedLength = (requestId, encodedDataLength, source = "finished") => {
|
|
1795
|
-
const safeRequestId = String(requestId || "");
|
|
1796
|
-
if (!safeRequestId) return;
|
|
1797
|
-
const requestState = requestMap.get(safeRequestId);
|
|
1798
|
-
const orphanReceived = toSafeNumber(orphanReceivedMap.get(safeRequestId));
|
|
1799
|
-
const encoded = toSafeNumber(encodedDataLength);
|
|
1800
|
-
if (requestState) {
|
|
1801
|
-
const routed2 = ensureRoute(requestState.route);
|
|
1802
|
-
const downloaded = toSafeNumber(requestState.downloadBytes);
|
|
1803
|
-
const delta2 = Math.max(0, encoded - downloaded);
|
|
1804
|
-
if (delta2 > 0) {
|
|
1805
|
-
addDownloadBytes(state, routed2, delta2);
|
|
1806
|
-
addDownloadProfile(state, routed2, requestState.domain, requestState.resourceType, delta2);
|
|
1807
|
-
requestState.downloadBytes = downloaded + delta2;
|
|
1808
|
-
}
|
|
1809
|
-
const uploadBytes = toSafeNumber(requestState.uploadBytes);
|
|
1810
|
-
const total = uploadBytes + toSafeNumber(requestState.downloadBytes);
|
|
1811
|
-
debugLog(
|
|
1812
|
-
`final id=${safeRequestId} source=${source} status=ok route=${routed2} type=${requestState.resourceType || "other"} upload=${formatBytes(uploadBytes)} (${uploadBytes}) download=${formatBytes(requestState.downloadBytes)} (${requestState.downloadBytes}) total=${formatBytes(total)} (${total}) url=${requestState.url || "-"}`
|
|
1813
|
-
);
|
|
1814
|
-
requestMap.delete(safeRequestId);
|
|
1815
|
-
orphanReceivedMap.delete(safeRequestId);
|
|
1816
|
-
return;
|
|
1817
|
-
}
|
|
1818
|
-
const routed = fallbackRoute();
|
|
1819
|
-
const delta = Math.max(0, encoded - orphanReceived);
|
|
1820
|
-
if (delta > 0) {
|
|
1821
|
-
addDownloadBytes(state, routed, delta);
|
|
1822
|
-
addDownloadProfile(state, routed, UNKNOWN_DOMAIN, "other", delta);
|
|
1823
|
-
}
|
|
1824
|
-
state.orphanFinishDeltaBytes += delta;
|
|
1825
|
-
if (routed === "proxy") {
|
|
1826
|
-
state.orphanProxyFinishDeltaBytes += delta;
|
|
1827
|
-
}
|
|
1828
|
-
debugLog(
|
|
1829
|
-
`final id=${safeRequestId} source=${source} status=orphan route=${routed} encoded=${formatBytes(encoded)} (${encoded}) delta=${formatBytes(delta)} (${delta})`
|
|
1830
|
-
);
|
|
1831
|
-
orphanReceivedMap.delete(safeRequestId);
|
|
1832
|
-
};
|
|
1833
|
-
const recordRequest = (params = {}) => {
|
|
1834
|
-
const requestId = String(params.requestId || "");
|
|
1835
|
-
const request = params.request && typeof params.request === "object" ? params.request : {};
|
|
1836
|
-
const url = String(request.url || "");
|
|
1837
|
-
const route = resolveRoute(url);
|
|
1838
|
-
const resourceType = normalizeResourceType(params.type || request.type || "other");
|
|
1839
|
-
const domain = normalizeDomainKey(parseHostname(url));
|
|
1840
|
-
if (requestId && requestMap.has(requestId)) {
|
|
1841
|
-
const redirectResponse = params.redirectResponse && typeof params.redirectResponse === "object" ? params.redirectResponse : null;
|
|
1842
|
-
finalizeByEncodedLength(
|
|
1843
|
-
requestId,
|
|
1844
|
-
redirectResponse ? redirectResponse.encodedDataLength : 0,
|
|
1845
|
-
"redirect"
|
|
1846
|
-
);
|
|
1847
|
-
}
|
|
1848
|
-
addRequests(state, route, 1);
|
|
1849
|
-
const uploadBytes = estimateRequestBytes(request);
|
|
1850
|
-
addUploadBytes(state, route, uploadBytes);
|
|
1851
|
-
addRequestProfile(state, route, domain, resourceType, uploadBytes);
|
|
1852
|
-
if (requestId) {
|
|
1853
|
-
requestMap.set(requestId, {
|
|
1854
|
-
route: ensureRoute(route),
|
|
1855
|
-
resourceType,
|
|
1856
|
-
domain,
|
|
1857
|
-
url,
|
|
1858
|
-
uploadBytes,
|
|
1859
|
-
downloadBytes: 0
|
|
1860
|
-
});
|
|
1861
|
-
}
|
|
1862
|
-
debugLog(
|
|
1863
|
-
`request id=${requestId || "-"} route=${route} type=${resourceType} upload=${formatBytes(uploadBytes)} (${uploadBytes}) method=${String(request.method || "GET")} url=${url || "-"}`
|
|
1864
|
-
);
|
|
1865
|
-
};
|
|
1866
|
-
const recordDataReceived = (params = {}) => {
|
|
1867
|
-
const requestId = String(params.requestId || "");
|
|
1868
|
-
const bytes = toSafeNumber(params.encodedDataLength);
|
|
1869
|
-
if (bytes <= 0) return;
|
|
1870
|
-
if (!requestId) {
|
|
1871
|
-
const routed2 = fallbackRoute();
|
|
1872
|
-
addDownloadBytes(state, routed2, bytes);
|
|
1873
|
-
addDownloadProfile(state, routed2, UNKNOWN_DOMAIN, "other", bytes);
|
|
1874
|
-
state.orphanDataReceivedBytes += bytes;
|
|
1875
|
-
if (routed2 === "proxy") {
|
|
1876
|
-
state.orphanProxyDataReceivedBytes += bytes;
|
|
1877
|
-
}
|
|
1878
|
-
return;
|
|
1879
|
-
}
|
|
1880
|
-
const requestState = requestMap.get(requestId);
|
|
1881
|
-
if (requestState) {
|
|
1882
|
-
requestState.downloadBytes = toSafeNumber(requestState.downloadBytes) + bytes;
|
|
1883
|
-
addDownloadBytes(state, requestState.route, bytes);
|
|
1884
|
-
addDownloadProfile(state, requestState.route, requestState.domain, requestState.resourceType, bytes);
|
|
1885
|
-
return;
|
|
1886
|
-
}
|
|
1887
|
-
const prev = toSafeNumber(orphanReceivedMap.get(requestId));
|
|
1888
|
-
orphanReceivedMap.set(requestId, prev + bytes);
|
|
1889
|
-
const routed = fallbackRoute();
|
|
1890
|
-
addDownloadBytes(state, routed, bytes);
|
|
1891
|
-
addDownloadProfile(state, routed, UNKNOWN_DOMAIN, "other", bytes);
|
|
1892
|
-
state.orphanDataReceivedBytes += bytes;
|
|
1893
|
-
if (routed === "proxy") {
|
|
1894
|
-
state.orphanProxyDataReceivedBytes += bytes;
|
|
1895
|
-
}
|
|
1896
|
-
};
|
|
1897
|
-
const recordLoadingFinished = (params = {}) => {
|
|
1898
|
-
finalizeByEncodedLength(params.requestId, params.encodedDataLength, "loadingFinished");
|
|
1899
|
-
};
|
|
1900
|
-
const recordRequestFailed = (params = {}) => {
|
|
1901
|
-
const requestId = String(params.requestId || "");
|
|
1902
|
-
const requestState = requestId ? requestMap.get(requestId) : null;
|
|
1903
|
-
const canceled = Boolean(params.canceled);
|
|
1904
|
-
const reason = ensureReasonText(params.errorText);
|
|
1905
|
-
const routed = ensureRoute(requestState?.route || fallbackRoute());
|
|
1906
|
-
const resourceType = normalizeResourceType(requestState?.resourceType || "other");
|
|
1907
|
-
const domain = normalizeDomainKey(requestState?.domain || "");
|
|
1908
|
-
if (requestState) {
|
|
1909
|
-
addFailed(routed, canceled);
|
|
1910
|
-
addFailedProfile(state, routed, domain, resourceType, reason, canceled);
|
|
1911
|
-
const uploadBytes = toSafeNumber(requestState.uploadBytes);
|
|
1912
|
-
const downloadBytes = toSafeNumber(requestState.downloadBytes);
|
|
1913
|
-
const totalBytes = uploadBytes + downloadBytes;
|
|
1914
|
-
debugLog(
|
|
1915
|
-
`final id=${requestId || "-"} source=loadingFailed status=failed route=${routed} type=${requestState.resourceType || "other"} upload=${formatBytes(uploadBytes)} (${uploadBytes}) download=${formatBytes(downloadBytes)} (${downloadBytes}) total=${formatBytes(totalBytes)} (${totalBytes}) canceled=${canceled} reason=${reason} url=${requestState.url || "-"}`
|
|
1916
|
-
);
|
|
1917
|
-
} else {
|
|
1918
|
-
const orphanDownload = toSafeNumber(orphanReceivedMap.get(requestId));
|
|
1919
|
-
addFailed(routed, canceled);
|
|
1920
|
-
addFailedProfile(state, routed, UNKNOWN_DOMAIN, "other", reason, canceled);
|
|
1921
|
-
debugLog(
|
|
1922
|
-
`final id=${requestId || "-"} source=loadingFailed status=orphan-failed route=${routed} upload=0B (0) download=${formatBytes(orphanDownload)} (${orphanDownload}) total=${formatBytes(orphanDownload)} (${orphanDownload}) canceled=${canceled} reason=${reason} url=-`
|
|
1923
|
-
);
|
|
1924
|
-
}
|
|
1925
|
-
if (requestId) {
|
|
1926
|
-
requestMap.delete(requestId);
|
|
1927
|
-
orphanReceivedMap.delete(requestId);
|
|
1928
|
-
}
|
|
1929
|
-
};
|
|
1930
|
-
const bindWebSocketRoute = (params = {}) => {
|
|
1931
|
-
const requestId = String(params.requestId || "");
|
|
1932
|
-
if (!requestId) return;
|
|
1933
|
-
const url = String(params.url || "");
|
|
1934
|
-
const route = resolveRoute(url);
|
|
1935
|
-
wsRouteMap.set(requestId, { route, url, domain: normalizeDomainKey(parseHostname(url)) });
|
|
1936
|
-
};
|
|
1937
|
-
const clearWebSocketRoute = (params = {}) => {
|
|
1938
|
-
const requestId = String(params.requestId || "");
|
|
1939
|
-
if (!requestId) return;
|
|
1940
|
-
wsRouteMap.delete(requestId);
|
|
1941
|
-
};
|
|
1942
|
-
const getWebSocketMeta = (requestId = "") => {
|
|
1943
|
-
if (!requestId) return { route: fallbackRoute(), url: "", domain: UNKNOWN_DOMAIN };
|
|
1944
|
-
const meta = wsRouteMap.get(requestId);
|
|
1945
|
-
if (!meta || typeof meta !== "object") {
|
|
1946
|
-
return { route: fallbackRoute(), url: "", domain: UNKNOWN_DOMAIN };
|
|
1947
|
-
}
|
|
1948
|
-
return {
|
|
1949
|
-
route: ensureRoute(meta.route),
|
|
1950
|
-
url: String(meta.url || ""),
|
|
1951
|
-
domain: normalizeDomainKey(meta.domain)
|
|
1952
|
-
};
|
|
1953
|
-
};
|
|
1954
|
-
const recordWebSocketFrameSent = (params = {}) => {
|
|
1955
|
-
const requestId = String(params.requestId || "");
|
|
1956
|
-
const { route, url, domain } = getWebSocketMeta(requestId);
|
|
1957
|
-
const payload = params.response && typeof params.response === "object" ? params.response.payloadData : "";
|
|
1958
|
-
const bytes = byteLength(payload || "");
|
|
1959
|
-
addUploadBytes(state, route, bytes);
|
|
1960
|
-
addUploadProfile(state, route, domain, "websocket", bytes);
|
|
1961
|
-
debugLog(`ws-send id=${requestId || "-"} route=${route} bytes=${formatBytes(bytes)} (${bytes}) url=${url || "-"}`);
|
|
1962
|
-
};
|
|
1963
|
-
const recordWebSocketFrameReceived = (params = {}) => {
|
|
1964
|
-
const requestId = String(params.requestId || "");
|
|
1965
|
-
const { route, url, domain } = getWebSocketMeta(requestId);
|
|
1966
|
-
const payload = params.response && typeof params.response === "object" ? params.response.payloadData : "";
|
|
1967
|
-
const bytes = byteLength(payload || "");
|
|
1968
|
-
addDownloadBytes(state, route, bytes);
|
|
1969
|
-
addDownloadProfile(state, route, domain, "websocket", bytes);
|
|
1970
|
-
debugLog(`ws-recv id=${requestId || "-"} route=${route} bytes=${formatBytes(bytes)} (${bytes}) url=${url || "-"}`);
|
|
1971
|
-
};
|
|
1972
|
-
const attachPage = async (page) => {
|
|
1973
|
-
if (!page || typeof page.context !== "function") return;
|
|
1974
|
-
if (attachedPages.has(page)) return;
|
|
1975
|
-
attachedPages.add(page);
|
|
1976
|
-
try {
|
|
1977
|
-
const context = page.context();
|
|
1978
|
-
if (!context || typeof context.newCDPSession !== "function") {
|
|
1979
|
-
return;
|
|
1980
|
-
}
|
|
1981
|
-
if (!attachedContexts.has(context) && typeof context.on === "function") {
|
|
1982
|
-
attachedContexts.add(context);
|
|
1983
|
-
context.on("page", (nextPage) => {
|
|
1984
|
-
if (!nextPage) return;
|
|
1985
|
-
attachPage(nextPage).catch((error) => {
|
|
1986
|
-
logger6.warn(`\u5B50\u9875\u9762 CDP \u76D1\u542C\u6CE8\u518C\u5931\u8D25: ${error?.message || error}`);
|
|
1987
|
-
});
|
|
1988
|
-
});
|
|
1989
|
-
}
|
|
1990
|
-
const session = await context.newCDPSession(page);
|
|
1991
|
-
await session.send("Network.enable");
|
|
1992
|
-
session.on("Network.requestWillBeSent", recordRequest);
|
|
1993
|
-
session.on("Network.dataReceived", recordDataReceived);
|
|
1994
|
-
session.on("Network.loadingFinished", recordLoadingFinished);
|
|
1995
|
-
session.on("Network.loadingFailed", recordRequestFailed);
|
|
1996
|
-
session.on("Network.webSocketCreated", bindWebSocketRoute);
|
|
1997
|
-
session.on("Network.webSocketClosed", clearWebSocketRoute);
|
|
1998
|
-
session.on("Network.webSocketFrameSent", recordWebSocketFrameSent);
|
|
1999
|
-
session.on("Network.webSocketFrameReceived", recordWebSocketFrameReceived);
|
|
2000
|
-
debugLog("CDP \u76D1\u542C\u5DF2\u6CE8\u518C");
|
|
2001
|
-
} catch (error) {
|
|
2002
|
-
logger6.warn(`CDP \u76D1\u542C\u6CE8\u518C\u5931\u8D25: ${error?.message || error}`);
|
|
2003
|
-
}
|
|
2004
|
-
};
|
|
2005
|
-
const snapshot = () => {
|
|
2006
|
-
const totalBytes = state.totalUploadBytes + state.totalDownloadBytes;
|
|
2007
|
-
const proxyBytes = state.proxyUploadBytes + state.proxyDownloadBytes;
|
|
2008
|
-
const directBytes = state.directUploadBytes + state.directDownloadBytes;
|
|
2009
|
-
return {
|
|
2010
|
-
meter: "cdp-data-received-v3",
|
|
2011
|
-
totalRequests: state.totalRequests,
|
|
2012
|
-
proxyRequests: state.proxyRequests,
|
|
2013
|
-
directRequests: state.directRequests,
|
|
2014
|
-
totalUploadBytes: state.totalUploadBytes,
|
|
2015
|
-
proxyUploadBytes: state.proxyUploadBytes,
|
|
2016
|
-
directUploadBytes: state.directUploadBytes,
|
|
2017
|
-
totalDownloadBytes: state.totalDownloadBytes,
|
|
2018
|
-
proxyDownloadBytes: state.proxyDownloadBytes,
|
|
2019
|
-
directDownloadBytes: state.directDownloadBytes,
|
|
2020
|
-
totalBytes,
|
|
2021
|
-
proxyBytes,
|
|
2022
|
-
directBytes,
|
|
2023
|
-
totalFailedRequests: state.totalFailedRequests,
|
|
2024
|
-
proxyFailedRequests: state.proxyFailedRequests,
|
|
2025
|
-
directFailedRequests: state.directFailedRequests,
|
|
2026
|
-
totalCanceledRequests: state.totalCanceledRequests,
|
|
2027
|
-
proxyCanceledRequests: state.proxyCanceledRequests,
|
|
2028
|
-
directCanceledRequests: state.directCanceledRequests,
|
|
2029
|
-
orphanDataReceivedBytes: state.orphanDataReceivedBytes,
|
|
2030
|
-
orphanProxyDataReceivedBytes: state.orphanProxyDataReceivedBytes,
|
|
2031
|
-
orphanFinishDeltaBytes: state.orphanFinishDeltaBytes,
|
|
2032
|
-
orphanProxyFinishDeltaBytes: state.orphanProxyFinishDeltaBytes,
|
|
2033
|
-
openRequestCount: requestMap.size,
|
|
2034
|
-
orphanOpenCount: orphanReceivedMap.size,
|
|
2035
|
-
topDomains: buildTopDomains(state),
|
|
2036
|
-
topResourceTypes: buildTopResourceTypes(state),
|
|
2037
|
-
failedReasons: buildFailedReasons(state),
|
|
2038
|
-
proxyBypassHints: buildProxyByPassHints(state)
|
|
2039
|
-
};
|
|
2040
|
-
};
|
|
2041
|
-
const reset = () => {
|
|
2042
|
-
Object.assign(state, createTrafficState());
|
|
2043
|
-
requestMap.clear();
|
|
2044
|
-
orphanReceivedMap.clear();
|
|
2045
|
-
wsRouteMap.clear();
|
|
2046
|
-
};
|
|
2047
|
-
return {
|
|
2048
|
-
attachPage,
|
|
2049
|
-
snapshot,
|
|
2050
|
-
reset
|
|
2051
|
-
};
|
|
2052
|
-
};
|
|
2053
1710
|
|
|
2054
1711
|
// src/launch.js
|
|
2055
1712
|
var logger7 = createInternalLogger("Launch");
|
|
1713
|
+
var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
|
|
2056
1714
|
var DEFAULT_CRAWLER_BASE_OPTIONS = Object.freeze({
|
|
2057
1715
|
maxConcurrency: 1,
|
|
2058
1716
|
maxRequestRetries: 0,
|
|
@@ -2064,24 +1722,10 @@ var resolveProxyLaunchOptions = (proxyConfiguration = {}) => {
|
|
|
2064
1722
|
const proxyUrl = String(config.proxy_url || "").trim();
|
|
2065
1723
|
const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
|
|
2066
1724
|
if (!enableProxy || !proxyUrl) {
|
|
2067
|
-
return {
|
|
1725
|
+
return { byPassDomains: [], enableProxy, proxyUrl };
|
|
2068
1726
|
}
|
|
2069
1727
|
const byPassDomains = normalizeByPassDomains(config.by_pass_domains);
|
|
2070
|
-
|
|
2071
|
-
parsedProxyUrl = new URL(proxyUrl);
|
|
2072
|
-
const launchProxy = {
|
|
2073
|
-
server: `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`
|
|
2074
|
-
};
|
|
2075
|
-
if (parsedProxyUrl.username) {
|
|
2076
|
-
launchProxy.username = decodeURIComponent(parsedProxyUrl.username);
|
|
2077
|
-
}
|
|
2078
|
-
if (parsedProxyUrl.password) {
|
|
2079
|
-
launchProxy.password = decodeURIComponent(parsedProxyUrl.password);
|
|
2080
|
-
}
|
|
2081
|
-
if (byPassDomains.length > 0) {
|
|
2082
|
-
launchProxy.bypass = byPassDomains.join(",");
|
|
2083
|
-
}
|
|
2084
|
-
return { launchProxy, byPassDomains, enableProxy, proxyUrl };
|
|
1728
|
+
return { byPassDomains, enableProxy, proxyUrl };
|
|
2085
1729
|
};
|
|
2086
1730
|
var Launch = {
|
|
2087
1731
|
getPlaywrightCrawlerOptions(options = {}) {
|
|
@@ -2097,14 +1741,13 @@ var Launch = {
|
|
|
2097
1741
|
preNavigationHooks = [],
|
|
2098
1742
|
postNavigationHooks = []
|
|
2099
1743
|
} = normalizedOptions;
|
|
2100
|
-
const {
|
|
1744
|
+
const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
|
|
2101
1745
|
const byPassRules = buildByPassDomainRules(byPassDomains);
|
|
2102
|
-
const
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
}
|
|
2107
|
-
setTrafficMeter(trafficMeter2);
|
|
1746
|
+
const proxyMeter = enableProxy && proxyUrl ? startProxyMeter({ proxyUrl, debugMode }) : null;
|
|
1747
|
+
const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
|
|
1748
|
+
if (launchProxy && byPassDomains.length > 0) {
|
|
1749
|
+
launchProxy.bypass = byPassDomains.join(",");
|
|
1750
|
+
}
|
|
2108
1751
|
const launchOptions = {
|
|
2109
1752
|
args: [
|
|
2110
1753
|
...AntiCheat.getLaunchArgs(),
|
|
@@ -2117,8 +1760,14 @@ var Launch = {
|
|
|
2117
1760
|
}
|
|
2118
1761
|
const enableByPassLogger = Boolean(logOptions && logOptions.enable);
|
|
2119
1762
|
if (enableByPassLogger && launchProxy) {
|
|
1763
|
+
let upstreamLabel = "";
|
|
1764
|
+
try {
|
|
1765
|
+
const parsedProxyUrl = new URL(proxyUrl);
|
|
1766
|
+
upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
|
|
1767
|
+
} catch {
|
|
1768
|
+
}
|
|
2120
1769
|
logger7.info(
|
|
2121
|
-
`[\u4EE3\u7406\u5DF2\u542F\u7528] \
|
|
1770
|
+
`[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
|
|
2122
1771
|
);
|
|
2123
1772
|
logger7.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
|
|
2124
1773
|
} else if (enableByPassLogger && enableProxy && !launchProxy) {
|
|
@@ -2138,17 +1787,23 @@ var Launch = {
|
|
|
2138
1787
|
const recommendedGotoOptions = {
|
|
2139
1788
|
waitUntil: "commit"
|
|
2140
1789
|
};
|
|
2141
|
-
if (page
|
|
2142
|
-
|
|
1790
|
+
if (!page || typeof page.on !== "function") {
|
|
1791
|
+
return recommendedGotoOptions;
|
|
2143
1792
|
}
|
|
2144
|
-
if (
|
|
1793
|
+
if (page[REQUEST_HOOK_FLAG]) {
|
|
2145
1794
|
return recommendedGotoOptions;
|
|
2146
1795
|
}
|
|
1796
|
+
page[REQUEST_HOOK_FLAG] = true;
|
|
2147
1797
|
const requestHandler = (req) => {
|
|
2148
1798
|
const requestUrl = req.url();
|
|
1799
|
+
const resourceType = req.resourceType();
|
|
1800
|
+
if (launchProxy) {
|
|
1801
|
+
recordProxyMeterResourceType(requestUrl, resourceType);
|
|
1802
|
+
}
|
|
1803
|
+
if (!enableByPassLogger || byPassDomains.length === 0) return;
|
|
2149
1804
|
const matched = findMatchedByPassRule(byPassRules, requestUrl);
|
|
2150
1805
|
if (!matched || !matched.rule) return;
|
|
2151
|
-
logger7.info(`[\u76F4\u8FDE\u547D\u4E2D] \u89C4\u5219=${matched.rule.pattern} \u57DF\u540D=${matched.hostname} \u8D44\u6E90\u7C7B\u578B=${
|
|
1806
|
+
logger7.info(`[\u76F4\u8FDE\u547D\u4E2D] \u89C4\u5219=${matched.rule.pattern} \u57DF\u540D=${matched.hostname} \u8D44\u6E90\u7C7B\u578B=${resourceType} \u65B9\u6CD5=${req.method()} \u5730\u5740=${requestUrl}`);
|
|
2152
1807
|
};
|
|
2153
1808
|
page.on("request", requestHandler);
|
|
2154
1809
|
return recommendedGotoOptions;
|
|
@@ -2833,10 +2488,10 @@ var Mutation = {
|
|
|
2833
2488
|
let text = "";
|
|
2834
2489
|
let html = "";
|
|
2835
2490
|
let source = "main";
|
|
2836
|
-
let
|
|
2491
|
+
let path2 = `${selector}[${index}]`;
|
|
2837
2492
|
if (isIframe) {
|
|
2838
2493
|
source = "iframe";
|
|
2839
|
-
|
|
2494
|
+
path2 = `${selector}[${index}]::iframe(${safeFrameId(node)})`;
|
|
2840
2495
|
try {
|
|
2841
2496
|
const frameDoc = node.contentDocument;
|
|
2842
2497
|
const frameRoot = frameDoc?.body || frameDoc?.documentElement;
|
|
@@ -2854,7 +2509,7 @@ var Mutation = {
|
|
|
2854
2509
|
items.push({
|
|
2855
2510
|
selector,
|
|
2856
2511
|
source,
|
|
2857
|
-
path,
|
|
2512
|
+
path: path2,
|
|
2858
2513
|
text,
|
|
2859
2514
|
html,
|
|
2860
2515
|
snapshot
|