@skrillex1224/playwright-toolkit 2.1.195 → 2.1.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -255
- package/browser.d.ts +8 -8
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +286 -27
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +286 -27
- package/dist/index.js.map +3 -3
- package/dist/internals/proxy-meter.js +549 -549
- package/index.d.ts +657 -628
- package/package.json +66 -66
package/dist/index.js
CHANGED
|
@@ -393,6 +393,9 @@ function createInternalLogger(moduleName, explicitLogger) {
|
|
|
393
393
|
const message = error instanceof Error ? error.message : error;
|
|
394
394
|
baseLogger.error(`${methodName} \u5931\u8D25: ${message}`);
|
|
395
395
|
},
|
|
396
|
+
error(message) {
|
|
397
|
+
baseLogger.error(message);
|
|
398
|
+
},
|
|
396
399
|
debug(message) {
|
|
397
400
|
baseLogger.debug(message);
|
|
398
401
|
},
|
|
@@ -2924,13 +2927,41 @@ var LiveView = {
|
|
|
2924
2927
|
// src/captcha-monitor.js
|
|
2925
2928
|
import { v4 as uuidv4 } from "uuid";
|
|
2926
2929
|
var logger9 = createInternalLogger("Captcha");
|
|
2930
|
+
var DEFAULT_BYTEDANCE_CAPTCHA_TOKEN = "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI";
|
|
2931
|
+
var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
|
|
2932
|
+
token: DEFAULT_BYTEDANCE_CAPTCHA_TOKEN,
|
|
2933
|
+
apiUrl: "https://api.jfbym.com/api/YmServer/customApi",
|
|
2934
|
+
apiType: "31234",
|
|
2935
|
+
maxRetries: 3,
|
|
2936
|
+
containerSelector: "#captcha_container",
|
|
2937
|
+
iframeSelector: 'iframe[src*="verifycenter"]',
|
|
2938
|
+
iframeFallbackSelector: "iframe",
|
|
2939
|
+
sourceImageSelector: "div.canvas-container",
|
|
2940
|
+
dropTargetContainerSelector: "#captcha_verify_image div",
|
|
2941
|
+
dropTargetTexts: ["\u62D6\u62FD\u5230\u8FD9\u91CC"],
|
|
2942
|
+
refreshTexts: ["\u5237\u65B0"],
|
|
2943
|
+
submitTexts: ["\u63D0\u4EA4"],
|
|
2944
|
+
recognitionSuccessCode: 1e4,
|
|
2945
|
+
containerVisibleTimeoutMs: 2e3,
|
|
2946
|
+
iframeVisibleTimeoutMs: 12e3,
|
|
2947
|
+
iframeFallbackVisibleTimeoutMs: 4e3,
|
|
2948
|
+
contentFrameResolveRetries: 5,
|
|
2949
|
+
contentFrameResolveDelayMs: 500,
|
|
2950
|
+
actionVisibleTimeoutMs: 1500,
|
|
2951
|
+
sourceImageVisibleTimeoutMs: 3e3,
|
|
2952
|
+
recognitionDelayMs: 2e3,
|
|
2953
|
+
refreshWaitMs: 3e3,
|
|
2954
|
+
submitWaitMs: 3e3,
|
|
2955
|
+
retryDelayBaseMs: 2e3,
|
|
2956
|
+
retryDelayStepMs: 1e3
|
|
2957
|
+
});
|
|
2927
2958
|
function useCaptchaMonitor(page, options) {
|
|
2928
2959
|
const { domSelector, urlPattern, onDetected } = options;
|
|
2929
2960
|
if (!domSelector && !urlPattern) {
|
|
2930
|
-
throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern
|
|
2961
|
+
throw new Error("[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern\u3002");
|
|
2931
2962
|
}
|
|
2932
2963
|
if (!onDetected || typeof onDetected !== "function") {
|
|
2933
|
-
throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\
|
|
2964
|
+
throw new Error("[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u51FD\u6570\u3002");
|
|
2934
2965
|
}
|
|
2935
2966
|
let isStopped = false;
|
|
2936
2967
|
let isHandling = false;
|
|
@@ -2951,28 +2982,22 @@ function useCaptchaMonitor(page, options) {
|
|
|
2951
2982
|
const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, "_")}`;
|
|
2952
2983
|
page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
|
|
2953
2984
|
});
|
|
2954
|
-
page.addInitScript(({ selector, callbackName, cleanerName:
|
|
2985
|
+
page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
|
|
2955
2986
|
(() => {
|
|
2956
2987
|
let observer = null;
|
|
2957
2988
|
const checkAndReport = () => {
|
|
2958
2989
|
const element = document.querySelector(selector);
|
|
2959
|
-
if (element) {
|
|
2960
|
-
|
|
2961
|
-
window[callbackName]();
|
|
2962
|
-
}
|
|
2963
|
-
return true;
|
|
2990
|
+
if (!element) {
|
|
2991
|
+
return false;
|
|
2964
2992
|
}
|
|
2965
|
-
|
|
2993
|
+
if (window[callbackName]) {
|
|
2994
|
+
window[callbackName]();
|
|
2995
|
+
}
|
|
2996
|
+
return true;
|
|
2966
2997
|
};
|
|
2967
2998
|
checkAndReport();
|
|
2968
2999
|
observer = new MutationObserver((mutations) => {
|
|
2969
|
-
|
|
2970
|
-
for (const mutation of mutations) {
|
|
2971
|
-
if (mutation.addedNodes.length > 0) {
|
|
2972
|
-
shouldCheck = true;
|
|
2973
|
-
break;
|
|
2974
|
-
}
|
|
2975
|
-
}
|
|
3000
|
+
const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
|
|
2976
3001
|
if (shouldCheck && observer) {
|
|
2977
3002
|
checkAndReport();
|
|
2978
3003
|
}
|
|
@@ -2988,7 +3013,7 @@ function useCaptchaMonitor(page, options) {
|
|
|
2988
3013
|
} else {
|
|
2989
3014
|
mountObserver();
|
|
2990
3015
|
}
|
|
2991
|
-
window[
|
|
3016
|
+
window[cleanupName] = () => {
|
|
2992
3017
|
if (observer) {
|
|
2993
3018
|
observer.disconnect();
|
|
2994
3019
|
observer = null;
|
|
@@ -2996,7 +3021,7 @@ function useCaptchaMonitor(page, options) {
|
|
|
2996
3021
|
};
|
|
2997
3022
|
})();
|
|
2998
3023
|
}, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
|
|
2999
|
-
logger9.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528
|
|
3024
|
+
logger9.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
|
|
3000
3025
|
cleanupFns.push(async () => {
|
|
3001
3026
|
try {
|
|
3002
3027
|
await page.evaluate((name) => {
|
|
@@ -3005,28 +3030,29 @@ function useCaptchaMonitor(page, options) {
|
|
|
3005
3030
|
delete window[name];
|
|
3006
3031
|
}
|
|
3007
3032
|
}, cleanerName);
|
|
3008
|
-
} catch
|
|
3033
|
+
} catch {
|
|
3009
3034
|
}
|
|
3010
3035
|
});
|
|
3011
3036
|
}
|
|
3012
3037
|
if (urlPattern) {
|
|
3013
3038
|
frameHandler = async (frame) => {
|
|
3014
|
-
if (frame
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3039
|
+
if (frame !== page.mainFrame()) {
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
3042
|
+
const currentUrl = page.url();
|
|
3043
|
+
if (currentUrl.includes(urlPattern)) {
|
|
3044
|
+
await triggerDetected();
|
|
3019
3045
|
}
|
|
3020
3046
|
};
|
|
3021
3047
|
page.on("framenavigated", frameHandler);
|
|
3022
|
-
logger9.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528
|
|
3048
|
+
logger9.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
|
|
3023
3049
|
cleanupFns.push(async () => {
|
|
3024
3050
|
page.off("framenavigated", frameHandler);
|
|
3025
3051
|
});
|
|
3026
3052
|
}
|
|
3027
3053
|
return {
|
|
3028
3054
|
stop: async () => {
|
|
3029
|
-
logger9.info("
|
|
3055
|
+
logger9.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
|
|
3030
3056
|
for (const fn of cleanupFns) {
|
|
3031
3057
|
await fn();
|
|
3032
3058
|
}
|
|
@@ -3034,8 +3060,241 @@ function useCaptchaMonitor(page, options) {
|
|
|
3034
3060
|
}
|
|
3035
3061
|
};
|
|
3036
3062
|
}
|
|
3063
|
+
var callCaptchaRecognitionApi = async (imageBase64, { apiUrl, apiType, token }) => {
|
|
3064
|
+
const response = await fetch(apiUrl, {
|
|
3065
|
+
method: "POST",
|
|
3066
|
+
headers: {
|
|
3067
|
+
"Content-Type": "application/json"
|
|
3068
|
+
},
|
|
3069
|
+
body: JSON.stringify({
|
|
3070
|
+
type: apiType,
|
|
3071
|
+
image: imageBase64,
|
|
3072
|
+
token
|
|
3073
|
+
})
|
|
3074
|
+
});
|
|
3075
|
+
if (!response.ok) {
|
|
3076
|
+
throw new Error(`Captcha API request failed with status ${response.status}`);
|
|
3077
|
+
}
|
|
3078
|
+
return await response.json();
|
|
3079
|
+
};
|
|
3080
|
+
var extractCaptchaSerialNumbers = (apiResponse) => {
|
|
3081
|
+
const serialNumbers = apiResponse?.data?.data?.serial_number;
|
|
3082
|
+
if (!Array.isArray(serialNumbers)) {
|
|
3083
|
+
return [];
|
|
3084
|
+
}
|
|
3085
|
+
return serialNumbers.map((value) => Number(value)).filter((value) => Number.isInteger(value) && value >= 0);
|
|
3086
|
+
};
|
|
3087
|
+
var waitForVisible = async (locator, timeout) => {
|
|
3088
|
+
try {
|
|
3089
|
+
await locator.waitFor({
|
|
3090
|
+
state: "visible",
|
|
3091
|
+
timeout
|
|
3092
|
+
});
|
|
3093
|
+
return true;
|
|
3094
|
+
} catch {
|
|
3095
|
+
return false;
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
3098
|
+
var resolveContentFrame = async (page, iframeLocator, options) => {
|
|
3099
|
+
for (let attempt = 1; attempt <= options.contentFrameResolveRetries; attempt++) {
|
|
3100
|
+
const iframeHandle = await iframeLocator.elementHandle();
|
|
3101
|
+
const frame = await iframeHandle?.contentFrame();
|
|
3102
|
+
if (frame) {
|
|
3103
|
+
return frame;
|
|
3104
|
+
}
|
|
3105
|
+
if (attempt < options.contentFrameResolveRetries) {
|
|
3106
|
+
await page.waitForTimeout(options.contentFrameResolveDelayMs);
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
return null;
|
|
3110
|
+
};
|
|
3111
|
+
var getVerifycenterCaptchaContext = async (page, options) => {
|
|
3112
|
+
const captchaContainer = page.locator(options.containerSelector).first();
|
|
3113
|
+
const isContainerVisible = await waitForVisible(
|
|
3114
|
+
captchaContainer,
|
|
3115
|
+
options.containerVisibleTimeoutMs
|
|
3116
|
+
);
|
|
3117
|
+
if (!isContainerVisible) {
|
|
3118
|
+
return null;
|
|
3119
|
+
}
|
|
3120
|
+
logger9.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
|
|
3121
|
+
let iframeLocator = page.locator(options.iframeSelector).first();
|
|
3122
|
+
let isIframeVisible = await waitForVisible(
|
|
3123
|
+
iframeLocator,
|
|
3124
|
+
options.iframeVisibleTimeoutMs
|
|
3125
|
+
);
|
|
3126
|
+
if (!isIframeVisible) {
|
|
3127
|
+
logger9.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
|
|
3128
|
+
iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
|
|
3129
|
+
isIframeVisible = await waitForVisible(
|
|
3130
|
+
iframeLocator,
|
|
3131
|
+
options.iframeFallbackVisibleTimeoutMs
|
|
3132
|
+
);
|
|
3133
|
+
}
|
|
3134
|
+
if (!isIframeVisible) {
|
|
3135
|
+
throw new Error("verifycenter iframe not found inside captcha container.");
|
|
3136
|
+
}
|
|
3137
|
+
logger9.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
|
|
3138
|
+
const frame = await resolveContentFrame(page, iframeLocator, options);
|
|
3139
|
+
if (!frame) {
|
|
3140
|
+
throw new Error("Failed to resolve verifycenter iframe content frame.");
|
|
3141
|
+
}
|
|
3142
|
+
return { iframeLocator, frame };
|
|
3143
|
+
};
|
|
3144
|
+
var clickCaptchaAction = async (frame, texts, options) => {
|
|
3145
|
+
for (const text of texts) {
|
|
3146
|
+
const candidates = [
|
|
3147
|
+
frame.getByText(text, { exact: false }).first(),
|
|
3148
|
+
frame.locator(`text=${text}`).first()
|
|
3149
|
+
];
|
|
3150
|
+
for (const candidate of candidates) {
|
|
3151
|
+
const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
|
|
3152
|
+
if (!isVisible) {
|
|
3153
|
+
continue;
|
|
3154
|
+
}
|
|
3155
|
+
await candidate.click();
|
|
3156
|
+
return true;
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
return false;
|
|
3160
|
+
};
|
|
3161
|
+
var findCaptchaDropTarget = async (frame, options) => {
|
|
3162
|
+
for (const text of options.dropTargetTexts) {
|
|
3163
|
+
const candidates = [
|
|
3164
|
+
frame.locator(options.dropTargetContainerSelector).filter({ hasText: text }).first(),
|
|
3165
|
+
frame.getByText(text, { exact: false }).first()
|
|
3166
|
+
];
|
|
3167
|
+
for (const candidate of candidates) {
|
|
3168
|
+
const isVisible = await waitForVisible(candidate, options.actionVisibleTimeoutMs);
|
|
3169
|
+
if (isVisible) {
|
|
3170
|
+
return candidate;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
return null;
|
|
3175
|
+
};
|
|
3176
|
+
var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
|
|
3177
|
+
const sourceBox = await sourceLocator.boundingBox();
|
|
3178
|
+
const targetBox = await targetLocator.boundingBox();
|
|
3179
|
+
if (!sourceBox || !targetBox) {
|
|
3180
|
+
throw new Error("Unable to resolve captcha drag coordinates.");
|
|
3181
|
+
}
|
|
3182
|
+
const startX = sourceBox.x + sourceBox.width / 2;
|
|
3183
|
+
const startY = sourceBox.y + sourceBox.height / 2;
|
|
3184
|
+
const endX = targetBox.x + targetBox.width / 2;
|
|
3185
|
+
const endY = targetBox.y + targetBox.height / 2;
|
|
3186
|
+
const steps = 10;
|
|
3187
|
+
const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
|
|
3188
|
+
const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
|
|
3189
|
+
await page.mouse.move(startX, startY, { steps: 8 });
|
|
3190
|
+
await page.waitForTimeout(250);
|
|
3191
|
+
await page.mouse.down();
|
|
3192
|
+
await page.waitForTimeout(350);
|
|
3193
|
+
await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
|
|
3194
|
+
await page.waitForTimeout(250);
|
|
3195
|
+
for (let step = 1; step <= steps; step++) {
|
|
3196
|
+
const progress = step / steps;
|
|
3197
|
+
const easedProgress = 1 - (1 - progress) * (1 - progress);
|
|
3198
|
+
const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
|
|
3199
|
+
const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
|
|
3200
|
+
await page.mouse.move(currentX, currentY, { steps: 2 });
|
|
3201
|
+
await page.waitForTimeout(90);
|
|
3202
|
+
}
|
|
3203
|
+
await page.waitForTimeout(100);
|
|
3204
|
+
await page.mouse.up();
|
|
3205
|
+
await page.waitForTimeout(100);
|
|
3206
|
+
};
|
|
3207
|
+
var refreshCaptcha = async (page, frame, options) => {
|
|
3208
|
+
const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
|
|
3209
|
+
if (!clicked) {
|
|
3210
|
+
logger9.warn("Refresh button not found.");
|
|
3211
|
+
return false;
|
|
3212
|
+
}
|
|
3213
|
+
await page.waitForTimeout(options.refreshWaitMs);
|
|
3214
|
+
return true;
|
|
3215
|
+
};
|
|
3216
|
+
async function solveBytedanceCaptcha(page, options = {}) {
|
|
3217
|
+
const config = {
|
|
3218
|
+
...DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS,
|
|
3219
|
+
...options
|
|
3220
|
+
};
|
|
3221
|
+
if (!config.token) {
|
|
3222
|
+
logger9.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
|
|
3223
|
+
return false;
|
|
3224
|
+
}
|
|
3225
|
+
for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
|
|
3226
|
+
logger9.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
|
|
3227
|
+
try {
|
|
3228
|
+
const captchaContext = await getVerifycenterCaptchaContext(page, config);
|
|
3229
|
+
if (!captchaContext) {
|
|
3230
|
+
logger9.info("Captcha container is not visible anymore.");
|
|
3231
|
+
return true;
|
|
3232
|
+
}
|
|
3233
|
+
const { iframeLocator, frame } = captchaContext;
|
|
3234
|
+
await page.waitForTimeout(config.recognitionDelayMs);
|
|
3235
|
+
const screenshotBuffer = await iframeLocator.screenshot();
|
|
3236
|
+
const apiResponse = await callCaptchaRecognitionApi(
|
|
3237
|
+
screenshotBuffer.toString("base64"),
|
|
3238
|
+
config
|
|
3239
|
+
);
|
|
3240
|
+
const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
|
|
3241
|
+
if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
|
|
3242
|
+
logger9.warn(
|
|
3243
|
+
`\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
|
|
3244
|
+
);
|
|
3245
|
+
await refreshCaptcha(page, frame, config);
|
|
3246
|
+
continue;
|
|
3247
|
+
}
|
|
3248
|
+
logger9.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
|
|
3249
|
+
const dropTarget = await findCaptchaDropTarget(frame, config);
|
|
3250
|
+
if (!dropTarget) {
|
|
3251
|
+
logger9.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
|
|
3252
|
+
await refreshCaptcha(page, frame, config);
|
|
3253
|
+
continue;
|
|
3254
|
+
}
|
|
3255
|
+
const sourceImages = frame.locator(config.sourceImageSelector);
|
|
3256
|
+
const imageCount = await sourceImages.count();
|
|
3257
|
+
for (const rawIndex of serialNumbers) {
|
|
3258
|
+
let imageIndex = rawIndex;
|
|
3259
|
+
if (imageIndex >= imageCount && imageIndex > 0 && imageIndex - 1 < imageCount) {
|
|
3260
|
+
imageIndex -= 1;
|
|
3261
|
+
}
|
|
3262
|
+
if (imageIndex < 0 || imageIndex >= imageCount) {
|
|
3263
|
+
throw new Error(`Captcha image index ${rawIndex} is out of range. count=${imageCount}`);
|
|
3264
|
+
}
|
|
3265
|
+
const sourceImage = sourceImages.nth(imageIndex);
|
|
3266
|
+
await sourceImage.waitFor({
|
|
3267
|
+
state: "visible",
|
|
3268
|
+
timeout: config.sourceImageVisibleTimeoutMs
|
|
3269
|
+
});
|
|
3270
|
+
await dragCaptchaWithMouse(page, sourceImage, dropTarget);
|
|
3271
|
+
}
|
|
3272
|
+
const submitted = await clickCaptchaAction(frame, config.submitTexts, config).catch(() => false);
|
|
3273
|
+
if (!submitted) {
|
|
3274
|
+
logger9.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
|
|
3275
|
+
}
|
|
3276
|
+
await page.waitForTimeout(config.submitWaitMs);
|
|
3277
|
+
const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
|
|
3278
|
+
if (!stillVisible) {
|
|
3279
|
+
logger9.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
|
|
3280
|
+
return true;
|
|
3281
|
+
}
|
|
3282
|
+
logger9.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
|
|
3283
|
+
await page.waitForTimeout(2e3);
|
|
3284
|
+
await refreshCaptcha(page, frame, config);
|
|
3285
|
+
} catch (error) {
|
|
3286
|
+
logger9.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
3287
|
+
}
|
|
3288
|
+
if (attempt < config.maxRetries) {
|
|
3289
|
+
await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
logger9.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
|
|
3293
|
+
return false;
|
|
3294
|
+
}
|
|
3037
3295
|
var Captcha = {
|
|
3038
|
-
useCaptchaMonitor
|
|
3296
|
+
useCaptchaMonitor,
|
|
3297
|
+
solveBytedanceCaptcha
|
|
3039
3298
|
};
|
|
3040
3299
|
|
|
3041
3300
|
// src/mutation.js
|