修复 sec_user_id 抓取:同时解析请求 URL 与 body,修正关注按钮选择器
This commit is contained in:
+52
-21
@@ -1,4 +1,4 @@
|
||||
// 获取抖音 Cookie 和 sec_user_id 的 Playwright 脚本
|
||||
// 获取抖音 Cookie 和 sec_user_id 的 Playwright 脚本
|
||||
// 用法: node get-cookie.js 或通过 cli.js cookies 调用
|
||||
// 首次运行扫码登录,后续运行浏览器会记住登录状态,无需重复扫码
|
||||
|
||||
@@ -128,24 +128,43 @@ async function openAndLogin(context) {
|
||||
// ============================================================
|
||||
// 提取 sec_user_id
|
||||
// ============================================================
|
||||
// 从任意文本/URL 中提取 sec_user_id
|
||||
// 兼容:URL query ?sec_user_id=xxx / JSON body "sec_user_id":"xxx"
|
||||
function pickSecUserId(text) {
|
||||
if (!text) return null;
|
||||
// 匹配 sec_user_id=xxx 或 "sec_user_id":"xxx"
|
||||
const m = text.match(/sec_user_id(?:=|%3D|":"|%22:%22|\":\")([^&"'\s]+)/i);
|
||||
if (m && m[1] && m[1] !== "self") return decodeURIComponent(m[1]);
|
||||
return null;
|
||||
}
|
||||
|
||||
async function extractSecUserId(page) {
|
||||
return new Promise(async (resolve) => {
|
||||
let found = null;
|
||||
|
||||
page.on("request", (request) => {
|
||||
// 监听所有请求:既看 URL 查询串,也看 POST body
|
||||
const onRequest = (request) => {
|
||||
if (found) return;
|
||||
try {
|
||||
// 1) 优先看 URL(following/list 等 GET 请求的 sec_user_id 在这里)
|
||||
const fromUrl = pickSecUserId(request.url());
|
||||
if (fromUrl) {
|
||||
found = fromUrl;
|
||||
console.log("✅ 从请求 URL 捕获到 sec_user_id:", found);
|
||||
return;
|
||||
}
|
||||
// 2) 再看 POST body
|
||||
const data = request.postData();
|
||||
if (data && data.includes("sec_user_id")) {
|
||||
const parsed = JSON.parse(data);
|
||||
if (parsed.sec_user_id && !found) {
|
||||
found = parsed.sec_user_id;
|
||||
console.log("✅ 从请求中捕获到 sec_user_id:", found);
|
||||
}
|
||||
const fromBody = pickSecUserId(data);
|
||||
if (fromBody) {
|
||||
found = fromBody;
|
||||
console.log("✅ 从请求 Body 捕获到 sec_user_id:", found);
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
};
|
||||
page.on("request", onRequest);
|
||||
|
||||
// 尝试从页面获取
|
||||
// 从页面本身尝试
|
||||
await page.waitForTimeout(TIMEOUTS.pageWait);
|
||||
if (!found) {
|
||||
try {
|
||||
@@ -167,20 +186,32 @@ async function extractSecUserId(page) {
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 尝试点击关注按钮触发请求
|
||||
// 兜底:主动点击头像旁边的「关注 / 关注列表」按钮,触发 following/list 请求
|
||||
// 抖音此按钮有多种 data-e2e,逐个尝试
|
||||
if (!found) {
|
||||
console.log("🖱️ 尝试点击关注按钮...");
|
||||
try {
|
||||
const btn = page.locator('[data-e2e="follow-count"]').first();
|
||||
if (await btn.isVisible({ timeout: TIMEOUTS.elementVisible })) {
|
||||
await btn.click();
|
||||
await page.waitForTimeout(TIMEOUTS.pageWait);
|
||||
}
|
||||
} catch (e) {}
|
||||
const selectors = [
|
||||
'[data-e2e="following-count"]', // 关注数(点它弹关注列表)
|
||||
'[data-e2e="user-info-follow"]', // 关注按钮
|
||||
'span:has-text("关注")',
|
||||
];
|
||||
for (const sel of selectors) {
|
||||
if (found) break;
|
||||
console.log(`🖱️ 尝试点击关注入口: ${sel}`);
|
||||
try {
|
||||
const btn = page.locator(sel).first();
|
||||
if (await btn.isVisible({ timeout: TIMEOUTS.elementVisible }).catch(() => false)) {
|
||||
await btn.click().catch(() => {});
|
||||
// 触发后再多等一会儿收集请求
|
||||
await page.waitForTimeout(TIMEOUTS.pageWait);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
// 等最后 3 秒收集网络请求
|
||||
await page.waitForTimeout(TIMEOUTS.pageWait);
|
||||
// 再等一会儿收集网络请求
|
||||
if (!found) await page.waitForTimeout(TIMEOUTS.pageWait);
|
||||
|
||||
page.off("request", onRequest);
|
||||
resolve(found);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user