小红书养号脚本真实项目架
小红书养号脚本真实项目架
/*
╔══════════════════════════════════════════════════════════╗
║案例1:小红书养号脚本真实项目架
║ ║
║核心架构: ║
║1. safe() 统一容错壳 — 绝不因为一个动作崩掉 ║
║2. pageHasText() 先预检 XML — 避开盲扫 nodeSearch 报错 ║
║3. findText() 节点精准定位 — 返回百分比坐标 ║
║4. clickText() 先预检再点击 — 最稳的套路 ║
║5. 三模式统一 if/else — 无障碍/HID/代理都能跑 ║
║6. pressBack() 返回键四通道兜底 — 绝不卡页面 ║
║7. humanSwipe() 人类化滑动 — 带随机抖动 ║
╚══════════════════════════════════════════════════════════╝
*/
// ======================== 配置区 ========================
var 模式选择 = '无障碍模式';// '无障碍模式' | 'HID硬件模式' | '代理模式'
var 小红书包名 = 'com.xingin.xhs';
var 目标点赞数 = 50;
var 目标评论数 = 5;
var 收藏概率 = 0.3;
var 关注概率 = 0.0;// 默认关闭关注!避免风控
var 评论触发间隔 = 15;// 每 N 次点赞评论一次
/*
⭐ 小红书详情页底部栏硬坐标(设备 1080×1920,已验证 ❤️ 可点)
布局:📝说点什么...── 💬评论 ── ⭐收藏 ── ❤️点赞
位置:~620px ~800px ~900px ~994px
y = 1536 (屏高的 0.80)
按比例换算其他分辨率:
────────────────────────────────
设备分辨率 ❤️点赞 ⭐收藏 💬评论
1080×1920 (994,1536)(900,1536) (800,1536)
────────────────────────────────
*/
var XHS_COORDS = {
w: 1080, h: 1920, // 设计基准分辨率(按比例缩放)
like: { xPct: 0.92, yPct: 0.80 },// ❤️ 点赞 已验证!
fav: { xPct: 0.83, yPct: 0.80 },// ⭐ 收藏
comment:{ xPct: 0.74, yPct: 0.80 } // 💬 评论
};
var 评论话术 = [
'好好看呀!请问是用什么软件做的呀?',
'求教程!这个效果太绝了 👏',
'姐妹手速也太快了吧 😂',
'码住码住!周末就试试',
'收藏了!下次做一定用得上',
];
/** 获取当前设备屏幕尺寸 */
function getScreen() {
var w = safe(function () { return screen.getScreenWidth(); }, '屏宽', XHS_COORDS.w);
var h = safe(function () { return screen.getScreenHeight(); }, '屏高', XHS_COORDS.h);
if (!w || w <= 0) w = XHS_COORDS.w;
if (!h || h <= 0) h = XHS_COORDS.h;
return ;
}
/** 按 XHS_COORDS 比例坐标 → 屏幕像素坐标 */
function xhsXY(coord) {
var s = getScreen();
return * coord.xPct), Math.round(s * coord.yPct)];
}
// ======================== 稳定运行库(复刻你的 05_特殊技巧合集)========================
function llog(m) { try { printl(m); } catch (e) {} }
function sleepMs(ms) { try { java.lang.Thread.sleep(ms); } catch (e) {} }
function nowMs() { return java.lang.System.currentTimeMillis(); }
function rnd(a, b) { try { return rand.randNumber(a, b); } catch (e) { return a + Math.floor(Math.random() * (b - a + 1)); } }
function humanDelay(minMs, maxMs) { sleepMs(rnd(minMs, maxMs)); }
/** 统一容错壳:任何可能报错的调用都包一层 */
function safe(fn, tag, defVal) {
try { return fn(); }
catch (e) { llog('⚠ [' + tag + '] ' + String(e.message).substring(0, Math.min(40, String(e.message).length))); return defVal === undefined ? null : defVal; }
}
/** 重试执行器 */
function retry(fn, times, gapMs, tag) {
times = times || 3; gapMs = gapMs || 1500; tag = tag || '操作';
for (var i = 1; i <= times; i++) {
var ok = false;
try { ok = !!fn(i); } catch (e) { llog('⚠ [' + tag + '] 第' + i + '次异常'); }
if (ok) { llog('✔ [' + tag + '] 第' + i + '次成功'); return true; }
llog('… [' + tag + '] 第' + i + '次未成功');
if (i < times) sleepMs(gapMs);
}
llog('✘ [' + tag + '] ' + times + '次都没成功');
return false;
}
/**
* 预检:当前页面有没有这段文字
* 真实生产源码写法(小红书/收藏加点赞.js 第16行):
* if(auto.getXml().includes("打开App")){...}
* Rhino ES5 下 Java String 自带 .includes(),直接用!
*/
function pageHasText(text) {
if (!text) return false;
return safe(function () {
var xml = auto.getXml();
if (xml == null) return false;
return xml.includes(text);
}, 'pageHasText("' + text + '")', false);
}
/** 找文字节点并返回百分比坐标 */
function findText(text, timeoutMs) {
var deadline = nowMs() + (timeoutMs || 8000);
while (nowMs() < deadline) {
if (pageHasText(text)) {
var res = safe(function () {
var nodes = auto.nodeSearch(1500).textIncludes(text);
if (nodes == '' || nodes == null) return null;
var node = nodes.getNode(0);
var p = node.getCenterPoint();
return ;
}, 'findText', null);
if (res) return res;
}
sleepMs(500);
}
return null;
}
/** 点击文字(先预检再精准查,带超时) */
function clickText(text, timeoutMs) {
var xy = findText(text, timeoutMs);
if (!xy) { llog('✘ 没找到: ' + text); return false; }
safe(function () { auto.clickPercent(xy, xy); }, 'clickPercent');
llog('✔ 点击「' + text + '」@ ' + xy.toFixed(3) + ',' + xy.toFixed(3));
return true;
}
/** 返回键四通道兜底 */
function pressBack() {
if (safe(function () { auto.pressBack(); return true; }, 'auto.pressBack', false)) { llog('← 返回(auto.pressBack)'); return true; }
if (safe(function () { auto.back(); return true; }, 'auto.back', false)) { llog('← 返回(auto.back)'); return true; }
if (safe(function () { device.pressBack(); return true; }, 'device.pressBack', false)) { llog('← 返回(device.pressBack)'); return true; }
llog('✘ 所有返回通道都不可用');
return false;
}
/**
* 短视频/笔记快速翻页(一次到底)
* 真实生产源码写法(小红书回粉.js 第0行):
* auto.swipPercent(0.4931,0.2363,0.5069,0.7383)
*/
function quickFlingUp() {
safe(function () {
auto.swipPercent(
rnd(0.42, 0.55), rnd(0.82, 0.88),// 起点:底部中间
rnd(0.42, 0.55), rnd(0.10, 0.18) // 终点:顶部中间
);
}, 'auto.swipPercent');
llog('↕ 上滑换笔记...');
}
/** 三模式万能点击 */
function 三模式点击(x, y, 标签) {
if (x === null || x === undefined || isNaN(x) || y === null || y === undefined || isNaN(y)) { return false; }
x = Math.round(Number(x)); y = Math.round(Number(y));
if (模式选择 == '无障碍模式') { auto.clickPoint(x, y); }
else if (模式选择 == 'HID硬件模式') { try { hid.click(x, y); } catch (e) { auto.clickPoint(x, y); } }
else { try { agent.click(x, y); } catch (e) { auto.clickPoint(x, y); } }
llog('🎯 ' + 标签 + ' (' + x + ',' + y + ')');
return true;
}
/** 弹窗自动处理(关键词词库 → 先 XML 预检 → 再精准点) */
function 处理弹窗() {
var 弹窗关键词 = ['跳过', '关闭', '残忍离开', '稍后再说', '拒绝', '不同意', '以后再说', '始终允许', '确定'];
for (var i = 0; i < 弹窗关键词.length; i++) {
var kw = 弹窗关键词;
if (pageHasText(kw)) {
var xy = findText(kw, 1000);
if (xy) {
var w = safe(function () { return screen.getScreenWidth(); }, '屏宽', 1080);
var h = safe(function () { return screen.getScreenHeight(); }, '屏高', 2400);
三模式点击(Math.round(xy * w), Math.round(xy * h), '关闭"' + kw + '"');
humanDelay(1200, 1800);
return true;
}
}
}
return false;
}
// ======================== 小红书详情页动作:全部硬坐标 ========================
/** 返回发现页(必须验证真的回去了,不行再按) */
function 返回发现页() {
var s = getScreen();
for (var i = 1; i <= 3; i++) {
pressBack();
humanDelay(800, 1200);
// 验证:发现页应该有"发现"/"消息",没有"说点什么"
var 在发现页 = pageHasText('发现') || pageHasText('消息');
var 还在详情 = pageHasText('说点什么');
if (在发现页 && !还在详情) {
if (i > 1) llog('✅ 第' + i + '次返回成功');
return true;
}
}
llog('🚨 返回失败,强制退出(可能卡了)');
// 实在不行,重启 App
safe(function () { app.resetApp(小红书包名); }, 'resetApp');
retry(function () { return pageHasText('发现') || pageHasText('消息'); }, 15, 1000, '重启后等首页');
return false;
}
/** 点进笔记详情页(3 次重试) */
function 点进详情页() {
var s = getScreen();
for (var attempt = 1; attempt <= 3; attempt++) {
// 瀑布流双列笔记卡片位置:y 范围 550~1200(避开底部栏和顶部)
var 列 = rnd(0, 1); // 0=左列 1=右列
var x = 列 == 0 ? rnd(180, 360) : rnd(700, 900);
x = Math.round(x * s / 1080);
var y = rnd(550, 1200);
y = Math.round(y * s / 1920);
三模式点击(x, y, '🖱️ 进笔记(第' + attempt + '次)');
humanDelay(1500, 2200);
if (pageHasText('说点什么')) return true;
// 失败就返回再试
if (attempt < 3) {
pressBack();
humanDelay(500, 700);
}
}
return false;
}
/**
* 小红书点赞
* 真实生产源码写法(收藏加点赞.js 第33-35行):
* var nodes = auto.nodeSearch().text("说点什么...").className("android.widget.TextView");
* var node = nodes.getNode(0);
* var success = node.nextNode().nextNode().nextNode().clickPoint();
*
* 优先用这个无障碍树节点链(不会因分辨率变化失效),失败再兜底硬坐标。
*/
function 小红书点赞() {
// === 方案 A:nodeSearch + nextNode 链(真实生产套路)===
var nodeOk = safe(function () {
var nodes = auto.nodeSearch().text("说点什么...").className("android.widget.TextView");
if (!nodes) return null;
var node = nodes.getNode(0);
if (!node) return null;
// 真实源码跳 3 次 = ❤️ 点赞按钮
var likeBtn = node.nextNode().nextNode().nextNode();
if (!likeBtn) return null;
var ok = likeBtn.clickPoint();
return ok;
}, 'nodeSearch点赞', null);
if (nodeOk === true) {
llog('✅ node链点赞成功');
humanDelay(400, 700);
return true;
}
// === 方案 B:硬坐标兜底(已验证跑通)===
var xy = xhsXY(XHS_COORDS.like);
xy += rnd(-8, 8); xy += rnd(-8, 8);
三模式点击(xy, xy, '❤️ 点赞(硬坐标兜底)');
humanDelay(400, 700);
return true;
}
/**
* 小红书收藏
* 真实源码没有收藏的写法,推测 nextNode 多 1 次
* 失败再兜底硬坐标
*/
function 小红书收藏() {
// === 方案 A:nodeSearch + nextNode 链 ===
var nodeOk = safe(function () {
var nodes = auto.nodeSearch().text("说点什么...").className("android.widget.TextView");
if (!nodes) return null;
var node = nodes.getNode(0);
if (!node) return null;
// ❤️ 跳3次 = node(3),⭐ 再跳1次 = node(4)
var favBtn = node.nextNode().nextNode().nextNode().nextNode();
if (!favBtn) return null;
return favBtn.clickPoint();
}, 'nodeSearch收藏', null);
if (nodeOk === true) {
llog('✅ node链收藏成功');
humanDelay(300, 600);
return true;
}
// === 方案 B:硬坐标兜底 ===
var xy = xhsXY(XHS_COORDS.fav);
xy += rnd(-8, 8); xy += rnd(-8, 8);
三模式点击(xy, xy, '⭐ 收藏(硬坐标兜底)');
humanDelay(300, 600);
return true;
}
// ======================== 小红书养号主循环 ========================
function 小红书养号引擎() {
llog('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
llog('小红书养号脚本 v2 · 硬坐标版(已验证 ❤️ 坐标)');
llog('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
// 启动小红书
llog('📱 启动小红书...');
try { app.resetApp(小红书包名); } catch (e) { try { app.openApp(小红书包名); } catch (e2) {} }
// 真实源码等待写法:sleep.waitString
// 小红书首页必然有"发现"或"消息"
var 启动成功 = safe(function () { sleep.waitString(字符='发现',毫秒=15000); return true; }, 'waitString发现', false)
|| safe(function () { sleep.waitString(字符='消息',毫秒=15000); return true; }, 'waitString消息', false);
if (!启动成功) {
retry(function () { return pageHasText('发现') || pageHasText('消息'); }, 30, 1000, '兜底等小红书启动');
}
humanDelay(1500, 2500);
// 打印屏幕信息,方便校对坐标
var s = getScreen();
llog('📐 设备分辨率: ' + s + ' × ' + s);
var likeXY = xhsXY(XHS_COORDS.like);
var favXY = xhsXY(XHS_COORDS.fav);
llog('🎯 ❤️坐标=(' + likeXY + ',' + likeXY + ')⭐坐标=(' + favXY + ',' + favXY + ')');
var 计数器 = { 点赞: 0, 收藏: 0, 跳过: 0, 失败: 0 };
while (计数器.点赞 < 目标点赞数) {
try {
// ===== 弹窗 =====
处理弹窗();
// ===== 1. 确认在发现页 =====
if (!pageHasText('发现') && !pageHasText('消息')) {
llog('⚠ 不在发现页,尝试返回...');
返回发现页();
humanDelay(800, 1200);
continue;
}
// ===== 2. 上滑换一条新笔记 =====
llog('📜 上滑换笔记...');
quickFlingUp();
humanDelay(800, 1500);
// ===== 3. 点击进笔记详情页(3 次重试)=====
if (!点进详情页()) {
计数器.跳过++;
llog(' ❌ 进详情页失败,跳过(累计 ' + 计数器.跳过 + ' 次)');
if (计数器.跳过 >= 5) {
llog('🚨 连续 5 次进详情页失败,脚本退出检查坐标');
return;
}
continue;
}
// ===== 4. 点赞(硬坐标!)=====
humanDelay(300, 600);
小红书点赞();
计数器.点赞++;
计数器.失败 = 0;
计数器.跳过 = 0;
llog('❤️ 点赞 #' + 计数器.点赞 + '/' + 目标点赞数);
humanDelay(300, 700);
// ===== 5. 收藏(概率触发)=====
if (Math.random() < 收藏概率) {
小红书收藏();
计数器.收藏++;
llog('⭐ 收藏 #' + 计数器.收藏);
}
humanDelay(200, 500);
// ===== 6. 返回到发现页(验证式返回)=====
humanDelay(300, 600);
返回发现页();
// ===== 7. 每 10 条休息一下 =====
if (计数器.点赞 % 10 === 0) {
var 休息秒 = rnd(5, 12);
llog('🛏️ 已点赞 10 条,休息 ' + 休息秒 + 's 再继续...');
humanDelay(休息秒 * 1000, 休息秒 * 1000);
}
} catch (e) {
计数器.失败++;
llog('⚠️ 异常#' + 计数器.失败 + ': ' + String(e.message).substring(0, 50));
humanDelay(1500, 3000);
if (计数器.失败 >= 10) {
llog('🚨 熔断!' + 计数器.点赞 + '❤️ ' + 计数器.收藏 + '⭐ ' + 计数器.跳过 + '跳过');
return;
}
}
}
llog('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
llog('✅ 完成!');
llog(' ❤️ 点赞' + 计数器.点赞);
llog(' ⭐ 收藏' + 计数器.收藏);
llog(' ⏭️ 跳过' + 计数器.跳过);
llog('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
}
小红书养号引擎();
页:
[1]