dasdasd
This commit is contained in:
parent
5c74ad349c
commit
bfd6c9ef3d
@ -74,49 +74,94 @@ class WindsurfRegister {
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用方法:点击按钮并等待页面跳转
|
||||
* @param {Function} checkPageChanged - 检查页面是否已跳转的函数,返回Promise<boolean>
|
||||
* @param {number} maxAttempts - 最多尝试次数
|
||||
* @param {string} actionName - 操作名称(用于日志)
|
||||
* @returns {Promise<boolean>} - 是否成功跳转
|
||||
* 通用方法:等待按钮激活并点击,然后等待页面内容变化
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {string} options.buttonText - 按钮文本(用于识别,如'Continue')
|
||||
* @param {Function} options.checkContentChanged - 检查页面内容是否已变化的函数,返回Promise<boolean>
|
||||
* @param {number} options.waitButtonTimeout - 等待按钮激活的超时时间(毫秒),默认30000
|
||||
* @param {number} options.waitContentTimeout - 等待内容变化的超时时间(毫秒),默认15000
|
||||
* @param {string} options.actionName - 操作名称(用于日志)
|
||||
* @returns {Promise<boolean>} - 是否成功完成
|
||||
*/
|
||||
async clickButtonAndWaitForPageChange(checkPageChanged, maxAttempts = 5, actionName = '点击按钮') {
|
||||
let pageChanged = false;
|
||||
let attempts = 0;
|
||||
async clickButtonAndWaitForPageChange(options) {
|
||||
const {
|
||||
buttonText = 'Continue',
|
||||
checkContentChanged,
|
||||
waitButtonTimeout = 30000,
|
||||
waitContentTimeout = 15000,
|
||||
actionName = '点击按钮'
|
||||
} = options;
|
||||
|
||||
while (!pageChanged && attempts < maxAttempts) {
|
||||
attempts++;
|
||||
try {
|
||||
// 阶段1: 等待按钮变为可点击状态(enabled)
|
||||
logger.info(this.siteName, ` → 等待"${buttonText}"按钮激活...`);
|
||||
|
||||
// 查找未禁用的按钮
|
||||
const button = await this.page.$('button:not([disabled])');
|
||||
if (button) {
|
||||
const text = await this.page.evaluate(el => el.textContent.trim(), button);
|
||||
logger.info(this.siteName, ` → 第${attempts}次${actionName}"${text}"...`);
|
||||
await button.click();
|
||||
await this.human.randomDelay(2000, 3000);
|
||||
const buttonStartTime = Date.now();
|
||||
let buttonEnabled = false;
|
||||
|
||||
// 使用自定义检查函数判断页面是否跳转
|
||||
const changed = await checkPageChanged();
|
||||
while (Date.now() - buttonStartTime < waitButtonTimeout) {
|
||||
buttonEnabled = await this.page.evaluate((btnText) => {
|
||||
const buttons = Array.from(document.querySelectorAll('button'));
|
||||
const targetButton = buttons.find(btn =>
|
||||
btn.textContent.trim() === btnText && !btn.disabled
|
||||
);
|
||||
return !!targetButton;
|
||||
}, buttonText);
|
||||
|
||||
if (changed) {
|
||||
pageChanged = true;
|
||||
logger.success(this.siteName, ` → ✓ 页面已跳转`);
|
||||
if (buttonEnabled) {
|
||||
const elapsed = ((Date.now() - buttonStartTime) / 1000).toFixed(1);
|
||||
logger.success(this.siteName, ` → ✓ 按钮已激活 (耗时: ${elapsed}秒)`);
|
||||
break;
|
||||
}
|
||||
|
||||
logger.warn(this.siteName, ` → 页面未跳转,${attempts}/${maxAttempts}`);
|
||||
await this.human.randomDelay(2000, 3000);
|
||||
} else {
|
||||
logger.warn(this.siteName, ` → 未找到可点击的按钮`);
|
||||
break;
|
||||
// 每5秒输出一次进度
|
||||
const elapsed = Date.now() - buttonStartTime;
|
||||
if (elapsed > 0 && elapsed % 5000 === 0) {
|
||||
logger.info(this.siteName, ` → 等待按钮激活中... 已用时 ${(elapsed/1000).toFixed(0)}秒`);
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
}
|
||||
}
|
||||
|
||||
if (!pageChanged) {
|
||||
logger.error(this.siteName, ` → ${maxAttempts}次尝试后页面仍未跳转`);
|
||||
}
|
||||
if (!buttonEnabled) {
|
||||
logger.error(this.siteName, ` → ⚠️ 等待${waitButtonTimeout/1000}秒后按钮仍未激活`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return pageChanged;
|
||||
// 阶段2: 点击按钮
|
||||
logger.info(this.siteName, ` → ${actionName}...`);
|
||||
await this.human.humanClick(this.page, `button:not([disabled])`);
|
||||
await this.human.randomDelay(1000, 2000);
|
||||
|
||||
// 阶段3: 等待页面内容变化
|
||||
logger.info(this.siteName, ` → 等待页面内容变化...`);
|
||||
|
||||
const contentStartTime = Date.now();
|
||||
let contentChanged = false;
|
||||
|
||||
while (Date.now() - contentStartTime < waitContentTimeout) {
|
||||
contentChanged = await checkContentChanged();
|
||||
|
||||
if (contentChanged) {
|
||||
const elapsed = ((Date.now() - contentStartTime) / 1000).toFixed(1);
|
||||
logger.success(this.siteName, ` → ✓ 页面内容已变化 (耗时: ${elapsed}秒)`);
|
||||
break;
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
}
|
||||
|
||||
if (!contentChanged) {
|
||||
logger.warn(this.siteName, ` → ⚠️ 等待${waitContentTimeout/1000}秒后页面内容未变化`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (error) {
|
||||
logger.error(this.siteName, ` → ${actionName}失败: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,30 +305,25 @@ class WindsurfRegister {
|
||||
}
|
||||
|
||||
// 点击Continue按钮并等待跳转到密码页面
|
||||
logger.info(this.siteName, ' → 点击Continue按钮...');
|
||||
const success = await this.clickButtonAndWaitForPageChange({
|
||||
buttonText: 'Continue',
|
||||
checkContentChanged: async () => {
|
||||
// 检查是否有密码输入框(表示已进入下一步)
|
||||
return await this.page.evaluate(() => {
|
||||
return !!document.querySelector('#password');
|
||||
});
|
||||
},
|
||||
waitButtonTimeout: 30000,
|
||||
waitContentTimeout: 15000,
|
||||
actionName: '点击Continue进入密码设置页面'
|
||||
});
|
||||
|
||||
// 等待按钮激活
|
||||
await this.page.waitForSelector('button:not([disabled])', { timeout: 10000 });
|
||||
logger.info(this.siteName, ' → 按钮已激活');
|
||||
|
||||
// 使用通用方法处理页面跳转
|
||||
const checkPageChanged = async () => {
|
||||
// 检查是否有密码输入框
|
||||
const hasPasswordField = await this.page.evaluate(() => {
|
||||
return !!document.querySelector('#password');
|
||||
});
|
||||
|
||||
// 检查URL是否改变
|
||||
const currentUrl = this.page.url();
|
||||
const urlChanged = currentUrl !== this.siteUrl;
|
||||
|
||||
return hasPasswordField || urlChanged;
|
||||
};
|
||||
|
||||
await this.clickButtonAndWaitForPageChange(checkPageChanged, 5, '点击Continue');
|
||||
if (!success) {
|
||||
throw new Error('步骤1:未能成功进入密码设置页面');
|
||||
}
|
||||
|
||||
// 额外等待确保页面稳定
|
||||
await this.human.randomDelay(2000, 3000);
|
||||
await this.human.randomDelay(1000, 2000);
|
||||
|
||||
this.currentStep = 1;
|
||||
logger.success(this.siteName, `步骤 1 完成`);
|
||||
@ -909,28 +949,24 @@ class WindsurfRegister {
|
||||
}
|
||||
logger.success(this.siteName, ' → 验证码已填写完成');
|
||||
|
||||
// 等待按钮激活(填完验证码后按钮会自动启用)
|
||||
logger.info(this.siteName, ' → 等待按钮激活...');
|
||||
await this.human.randomDelay(2000, 3000);
|
||||
// 点击"Create account"按钮并等待页面内容变化
|
||||
const success = await this.clickButtonAndWaitForPageChange({
|
||||
buttonText: 'Create account',
|
||||
checkContentChanged: async () => {
|
||||
// 检查验证码输入框是否已消失(表示已进入下一步)
|
||||
return await this.page.evaluate(() => {
|
||||
return !document.querySelector('input[type="text"]');
|
||||
});
|
||||
},
|
||||
waitButtonTimeout: 30000,
|
||||
waitContentTimeout: 15000,
|
||||
actionName: '点击Create account进入下一步'
|
||||
});
|
||||
|
||||
// 等待按钮激活
|
||||
try {
|
||||
await this.page.waitForSelector('button:not([disabled])', { timeout: 10000 });
|
||||
logger.success(this.siteName, ' → 按钮已激活');
|
||||
} catch (e) {
|
||||
logger.warn(this.siteName, ` → 按钮等待超时: ${e.message}`);
|
||||
if (!success) {
|
||||
throw new Error('步骤3:未能成功创建账号');
|
||||
}
|
||||
|
||||
// 点击按钮并等待页面跳转
|
||||
const checkPageChanged = async () => {
|
||||
// 检查是否离开了验证码页面(URL改变或页面元素改变)
|
||||
const currentUrl = this.page.url();
|
||||
return !currentUrl.includes('/register') ||
|
||||
await this.page.$('input[type="text"]').then(el => !el).catch(() => true);
|
||||
};
|
||||
|
||||
await this.clickButtonAndWaitForPageChange(checkPageChanged, 3, '点击Create account');
|
||||
|
||||
this.currentStep = 3;
|
||||
logger.success(this.siteName, `步骤 3 完成`);
|
||||
|
||||
@ -957,26 +993,54 @@ class WindsurfRegister {
|
||||
logger.info(this.siteName, `[步骤 4/${this.getTotalSteps()}] 跳过问卷`);
|
||||
|
||||
try {
|
||||
// 等待页面加载
|
||||
// 初始等待页面加载
|
||||
await this.human.readPage(2, 3);
|
||||
|
||||
// 查找并点击"Skip this step"按钮
|
||||
logger.info(this.siteName, ' → 查找"Skip this step"按钮...');
|
||||
logger.info(this.siteName, ' → 持续查找"Skip this step"按钮...');
|
||||
|
||||
// 方式1: 通过button文本查找
|
||||
const buttons = await this.page.$$('button');
|
||||
const startTime = Date.now();
|
||||
const maxWait = 60000; // 最多等待60秒
|
||||
let elapsed = 0;
|
||||
let skipButton = null;
|
||||
let buttonFound = false;
|
||||
|
||||
for (const button of buttons) {
|
||||
const text = await this.page.evaluate(el => el.textContent?.trim(), button);
|
||||
if (text && text.toLowerCase().includes('skip')) {
|
||||
skipButton = button;
|
||||
logger.info(this.siteName, ` → 找到按钮: "${text}"`);
|
||||
break;
|
||||
// 轮询查找按钮
|
||||
while (elapsed < maxWait && !buttonFound) {
|
||||
try {
|
||||
// 查找所有按钮
|
||||
const buttons = await this.page.$$('button');
|
||||
|
||||
for (const button of buttons) {
|
||||
const text = await this.page.evaluate(el => el.textContent?.trim(), button);
|
||||
if (text && text.toLowerCase().includes('skip')) {
|
||||
skipButton = button;
|
||||
buttonFound = true;
|
||||
logger.success(this.siteName, ` → ✓ 找到按钮: "${text}" (耗时: ${((Date.now() - startTime) / 1000).toFixed(1)}秒)`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (buttonFound) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 每5秒输出一次进度
|
||||
if (elapsed > 0 && elapsed % 5000 === 0) {
|
||||
logger.info(this.siteName, ` → 等待按钮出现... 已用时 ${elapsed/1000}秒`);
|
||||
}
|
||||
|
||||
// 等待2秒后继续查找
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
elapsed = Date.now() - startTime;
|
||||
|
||||
} catch (error) {
|
||||
logger.warn(this.siteName, ` → 查找按钮时出错: ${error.message},继续尝试...`);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
elapsed = Date.now() - startTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (skipButton) {
|
||||
if (skipButton && buttonFound) {
|
||||
logger.info(this.siteName, ' → 点击"Skip this step"按钮...');
|
||||
await skipButton.click();
|
||||
|
||||
@ -985,8 +1049,10 @@ class WindsurfRegister {
|
||||
|
||||
this.currentStep = 4;
|
||||
logger.success(this.siteName, `步骤 4 完成`);
|
||||
} else {
|
||||
logger.warn(this.siteName, ' → 未找到Skip按钮,可能已跳过此页面');
|
||||
} else if (elapsed >= maxWait) {
|
||||
logger.warn(this.siteName, ` → ⚠️ 等待${maxWait/1000}秒后仍未找到Skip按钮`);
|
||||
logger.warn(this.siteName, ' → 可能原因:页面已自动跳过或页面结构已变化');
|
||||
logger.info(this.siteName, ' → 尝试继续执行下一步...');
|
||||
this.currentStep = 4;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user