2026-08-27 03:06:51 +00:00
|
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 登录二维码获取器 v1.0(2026-08-27)
|
|
|
|
|
|
* 用法:node login-qrcode.js <port> <输出png路径>
|
|
|
|
|
|
*
|
|
|
|
|
|
* 流程:连CDP → 找登录页tab(没有则刷新推荐页触发跳转)→ 截取二维码区域的图片
|
|
|
|
|
|
* 智联登录页二维码是 canvas 或 img 动态渲染,直接整页截图最稳(剪裁左半部分登录卡片区)。
|
|
|
|
|
|
*/
|
|
|
|
|
|
const path = require('path');
|
|
|
|
|
|
function tryRequire(names) {
|
|
|
|
|
|
for (const n of names) { try { return require(n); } catch (_) {} }
|
|
|
|
|
|
throw new Error('无法加载 playwright-core');
|
|
|
|
|
|
}
|
|
|
|
|
|
const { chromium } = tryRequire([process.env.PWCORE_PATH, 'playwright-core'].filter(Boolean));
|
|
|
|
|
|
|
|
|
|
|
|
const PORT = process.argv[2] || '9222';
|
|
|
|
|
|
const OUT = process.argv[3] || `/tmp/zhaopin-login-qr-${PORT}.png`;
|
|
|
|
|
|
|
|
|
|
|
|
(async () => {
|
|
|
|
|
|
const b = await chromium.connectOverCDP(`http://127.0.0.1:${PORT}`);
|
|
|
|
|
|
let p = b.contexts()[0]?.pages().find(x => /passport\.zhaopin\.com/.test(x.url()));
|
2026-10-19 02:07:45 +00:00
|
|
|
|
|
|
|
|
|
|
// v1.1(2026-10-15):登录态预检——不在登录页且推荐页有卡片 = 已登录,无需发码
|
2026-08-27 03:06:51 +00:00
|
|
|
|
if (!p) {
|
2026-10-19 02:07:45 +00:00
|
|
|
|
const rec = b.contexts()[0]?.pages().find(x => /rd\d?\.zhaopin\.com/.test(x.url()));
|
|
|
|
|
|
if (rec) {
|
|
|
|
|
|
const logged = await rec.evaluate(() =>
|
|
|
|
|
|
!location.href.includes('passport') && document.querySelectorAll('.recommend-item').length > 0
|
|
|
|
|
|
).catch(() => false);
|
|
|
|
|
|
if (logged) { console.log('ALREADY_LOGGED_IN'); process.exit(0); } // 特殊退出码0+标记:已登录
|
|
|
|
|
|
}
|
2026-08-27 03:06:51 +00:00
|
|
|
|
// 找推荐页tab刷新,触发跳转到登录页
|
2026-10-19 02:07:45 +00:00
|
|
|
|
p = rec || b.contexts()[0]?.pages()[0];
|
2026-08-27 03:06:51 +00:00
|
|
|
|
if (!p) { console.error('NO_PAGE'); process.exit(1); }
|
|
|
|
|
|
await p.reload({ waitUntil: 'domcontentloaded', timeout: 60000 }).catch(() => {});
|
|
|
|
|
|
await new Promise(r => setTimeout(r, 4000));
|
|
|
|
|
|
// 刷新后可能跳到登录页
|
|
|
|
|
|
if (!/passport\.zhaopin\.com/.test(p.url())) {
|
|
|
|
|
|
await p.goto('https://passport.zhaopin.com/org/login', { waitUntil: 'domcontentloaded', timeout: 60000 }).catch(() => {});
|
|
|
|
|
|
await new Promise(r => setTimeout(r, 4000));
|
|
|
|
|
|
}
|
2026-08-27 03:13:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
// 已在登录页:强制 reload 拿新二维码(页面上停留的旧码可能已过期)
|
|
|
|
|
|
await p.reload({ waitUntil: 'domcontentloaded', timeout: 60000 }).catch(() => {});
|
|
|
|
|
|
await new Promise(r => setTimeout(r, 4000));
|
2026-08-27 03:06:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
console.log('PAGE:', p.url().slice(0, 90));
|
|
|
|
|
|
|
2026-10-19 02:07:45 +00:00
|
|
|
|
// v1.1:确认真的在登录页(防止误把推荐页/其他页面截图当二维码发出去)
|
|
|
|
|
|
if (!/passport\.zhaopin\.com/.test(p.url())) {
|
|
|
|
|
|
console.error('NOT_LOGIN_PAGE'); process.exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-27 03:06:51 +00:00
|
|
|
|
// 等二维码出现(canvas 或 img.qr / 二维码容器,多选择器兜底)
|
|
|
|
|
|
const qrSel = [
|
|
|
|
|
|
'canvas', // 智联登录二维码多为 canvas 绘制
|
|
|
|
|
|
'img[src*="qr"]',
|
|
|
|
|
|
'.qrcode', '.qr-code', '.login-qr', '[class*="qr" i]',
|
|
|
|
|
|
'.zp-qr', '#qr', '[id*="qr" i]',
|
|
|
|
|
|
];
|
|
|
|
|
|
let el = null;
|
|
|
|
|
|
for (let i = 0; i < 10 && !el; i++) {
|
|
|
|
|
|
for (const s of qrSel) {
|
|
|
|
|
|
el = await p.$(s).catch(() => null);
|
|
|
|
|
|
if (el) {
|
|
|
|
|
|
// 校验尺寸:太小的 canvas 可能是图标
|
|
|
|
|
|
const box = await el.boundingBox().catch(() => null);
|
|
|
|
|
|
if (!box || box.width < 100) { el = null; continue; }
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!el) await new Promise(r => setTimeout(r, 1000));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let shotPath = OUT;
|
|
|
|
|
|
if (el) {
|
|
|
|
|
|
await el.screenshot({ path: OUT }).catch(async () => { await p.screenshot({ path: OUT }); });
|
|
|
|
|
|
console.log('QR_ELEMENT_SHOT');
|
|
|
|
|
|
} else {
|
2026-10-19 02:07:45 +00:00
|
|
|
|
// v1.1(2026-10-15):删掉整页截图兜底——找不到二维码元素就报错,
|
|
|
|
|
|
// 不许把非二维码图片(登录页全屏/推荐页截图)当二维码发出去(用户10-15反馈)
|
|
|
|
|
|
console.error('NO_QR_ELEMENT');
|
|
|
|
|
|
process.exit(1);
|
2026-08-27 03:06:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
console.log('SAVED:', OUT);
|
|
|
|
|
|
process.exit(0);
|
|
|
|
|
|
})().catch(e => { console.error('ERR:', String(e).slice(0, 150)); process.exit(1); });
|