205 lines
6.5 KiB
JavaScript
205 lines
6.5 KiB
JavaScript
/**
|
|
* 微博登录助手 - 步骤1: 获取验证码
|
|
*/
|
|
|
|
const puppeteer = require('puppeteer-core');
|
|
const { getLaunchOptions } = require('../config/browser');
|
|
const fs = require('fs');
|
|
|
|
const PHONE = process.argv[2] || '18688929976';
|
|
const SCREENSHOT_DIR = '/tmp/weibo_login';
|
|
|
|
// 延迟函数
|
|
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
// 确保截图目录存在
|
|
if (!fs.existsSync(SCREENSHOT_DIR)) {
|
|
fs.mkdirSync(SCREENSHOT_DIR, { recursive: true });
|
|
}
|
|
|
|
async function weiboLoginStep1() {
|
|
console.log('🌐 正在打开微博登录页面...');
|
|
|
|
const browser = await puppeteer.launch({
|
|
...getLaunchOptions(),
|
|
headless: true,
|
|
});
|
|
|
|
try {
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width: 1280, height: 900 });
|
|
|
|
// 打开微博
|
|
await page.goto('https://weibo.com', {
|
|
waitUntil: 'networkidle2',
|
|
timeout: 60000,
|
|
});
|
|
|
|
console.log('✅ 页面加载完成');
|
|
await delay(3000);
|
|
|
|
// 保存初始页面截图
|
|
await page.screenshot({ path: `${SCREENSHOT_DIR}/01_initial.png` });
|
|
console.log('📸 初始页面已截图');
|
|
|
|
// 检查是否有登录框,如果没有可能需要点击登录按钮
|
|
const loginBtn = await page.$('a[href*="login"], .login, [node-type="loginBtn"], .W_btn_g');
|
|
if (loginBtn) {
|
|
const text = await page.evaluate(el => el.textContent, loginBtn);
|
|
console.log(`🔘 发现登录按钮: "${text?.trim()}",点击中...`);
|
|
await loginBtn.click();
|
|
await delay(3000);
|
|
await page.screenshot({ path: `${SCREENSHOT_DIR}/02_login_modal.png` });
|
|
}
|
|
|
|
// 查找手机号输入框
|
|
console.log('📱 查找手机号输入框...');
|
|
const phoneSelectors = [
|
|
'input[name="username"]',
|
|
'input[name="phone"]',
|
|
'input[placeholder*="手机号"]',
|
|
'input[placeholder*="邮箱"]',
|
|
'input[type="tel"]',
|
|
'input[type="text"]',
|
|
'#loginname',
|
|
'.W_input',
|
|
'input[node-type="username"]',
|
|
'input[action-type="text_copy"]',
|
|
];
|
|
|
|
let phoneInput = null;
|
|
let usedSelector = '';
|
|
for (const sel of phoneSelectors) {
|
|
const inputs = await page.$$(sel);
|
|
for (const input of inputs) {
|
|
const type = await page.evaluate(el => el.type, input);
|
|
const placeholder = await page.evaluate(el => el.placeholder, input);
|
|
console.log(` 检查: ${sel} (type=${type}, placeholder=${placeholder})`);
|
|
if (!phoneInput) {
|
|
phoneInput = input;
|
|
usedSelector = sel;
|
|
}
|
|
}
|
|
if (phoneInput) break;
|
|
}
|
|
|
|
if (!phoneInput) {
|
|
console.log('⚠️ 尝试获取所有输入框...');
|
|
const allInputs = await page.$$('input');
|
|
console.log(` 找到 ${allInputs.length} 个输入框`);
|
|
if (allInputs.length > 0) {
|
|
phoneInput = allInputs[0];
|
|
}
|
|
}
|
|
|
|
if (!phoneInput) {
|
|
throw new Error('未找到输入框');
|
|
}
|
|
|
|
console.log(`✅ 找到输入框: ${usedSelector}`);
|
|
|
|
// 清空并输入手机号
|
|
await phoneInput.click({ clickCount: 3 }); // 全选
|
|
await phoneInput.type(PHONE, { delay: 50 });
|
|
console.log(`✅ 手机号已输入: ${PHONE}`);
|
|
|
|
await page.screenshot({ path: `${SCREENSHOT_DIR}/03_phone_entered.png` });
|
|
|
|
// 查找"获取验证码"按钮
|
|
console.log('🔍 查找"获取验证码"按钮...');
|
|
const codeBtnSelectors = [
|
|
'a[action-type="get_code"]',
|
|
'a[node-type="btn_code"]',
|
|
'.W_btn_g',
|
|
'.get_code',
|
|
'a:has-text("获取")',
|
|
'a:has-text("验证码")',
|
|
'button:has-text("获取")',
|
|
'button:has-text("验证码")',
|
|
];
|
|
|
|
let codeBtn = null;
|
|
for (const sel of codeBtnSelectors) {
|
|
try {
|
|
codeBtn = await page.$(sel);
|
|
if (codeBtn) {
|
|
const text = await page.evaluate(el => el.textContent, codeBtn);
|
|
console.log(` 找到按钮: "${text?.trim()}" (${sel})`);
|
|
break;
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
|
|
// 如果没找到,尝试查找所有按钮/链接
|
|
if (!codeBtn) {
|
|
console.log(' 尝试查找所有按钮...');
|
|
const allBtns = await page.$$('a, button');
|
|
for (const btn of allBtns) {
|
|
const text = await page.evaluate(el => el.textContent, btn);
|
|
if (text && (text.includes('获取') || text.includes('验证码') || text.includes('code'))) {
|
|
console.log(` 候选: "${text.trim()}"`);
|
|
if (!codeBtn && text.includes('获取')) {
|
|
codeBtn = btn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (codeBtn) {
|
|
const btnText = await page.evaluate(el => el.textContent, codeBtn);
|
|
console.log(`\n🖱️ 点击按钮: "${btnText?.trim()}"`);
|
|
await codeBtn.click();
|
|
console.log('✅ 已点击"获取验证码"');
|
|
|
|
// 等待几秒钟,让短信发送
|
|
await delay(5000);
|
|
await page.screenshot({ path: `${SCREENSHOT_DIR}/04_code_requested.png` });
|
|
|
|
// 检查是否有提示信息
|
|
const tips = await page.$$eval('.W_layer, .W_tips, .tip, .error, .info', els =>
|
|
els.map(el => el.textContent?.trim()).filter(Boolean)
|
|
);
|
|
if (tips.length > 0) {
|
|
console.log('\n💬 页面提示:', tips.slice(0, 3));
|
|
}
|
|
|
|
} else {
|
|
console.log('⚠️ 未找到验证码按钮,请查看截图手动确认');
|
|
}
|
|
|
|
// 保存当前页面HTML用于分析
|
|
const html = await page.content();
|
|
fs.writeFileSync(`${SCREENSHOT_DIR}/page.html`, html);
|
|
|
|
console.log('\n' + '='.repeat(60));
|
|
console.log('📋 步骤1完成,当前状态:');
|
|
console.log(` 手机号: ${PHONE}`);
|
|
console.log(` 验证码: ⏳ 等待发送...`);
|
|
console.log('\n📸 截图文件:');
|
|
fs.readdirSync(SCREENSHOT_DIR).forEach(f => {
|
|
console.log(` - ${SCREENSHOT_DIR}/${f}`);
|
|
});
|
|
console.log('\n📱 请检查手机,收到验证码后告诉我');
|
|
console.log('格式: 验证码 123456');
|
|
console.log('='.repeat(60));
|
|
|
|
// 保存浏览器状态,等待下一步
|
|
await page.screenshot({ path: `${SCREENSHOT_DIR}/05_waiting_code.png` });
|
|
|
|
// 保持浏览器实例供后续使用(通过文件记录WSEndpoint)
|
|
const wsEndpoint = browser.wsEndpoint();
|
|
fs.writeFileSync(`${SCREENSHOT_DIR}/browser_ws.txt`, wsEndpoint);
|
|
console.log('\n⏳ 浏览器保持连接,等待下一步...');
|
|
|
|
// 保持运行
|
|
await new Promise(() => {});
|
|
|
|
} catch (error) {
|
|
console.error('❌ 操作失败:', error.message);
|
|
await browser.close();
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
weiboLoginStep1().catch(console.error);
|