下载地址:m.pan38.com/download.ph… 提取码:6666
非常完整的小红书关注脚本,支持采集,还可以自动点赞评论点赞作品,收藏和关注等功能的操作。
"ui";// 1. UI界面// 添加全局计数器和悬浮窗let clickCounter = 0;let floatyWindow = null;let currentIdPosition = 0;let totalIds = 0;// 创建悬浮窗function createFloatyWindow() { floatyWindow = floaty.window( <frame gravity="left"> <text id="logText" textSize="14sp" textColor="#ffffff" bg="#99000000" padding="5"/> </frame> ); // 设置初始位置(左上角) floatyWindow.setPosition(0, 100); updateFloatyLog();}// 更新悬浮窗日志function updateFloatyLog() { if (floatyWindow) { let currentTime = new Date().toLocaleTimeString(); floatyWindow.logText.setText(`ID进度: ${currentIdPosition}/${totalIds} | 点击: ${clickCounter} | ${currentTime}`); }}ui.layout( <vertical padding="16"> <text text="请输入小红书用户ID(每行一个)" textSize="16sp"/> <input id="idInput" hint="每行一个ID" lines="8"/> <horizontal> <text text="跳转间隔(秒)" textSize="16sp"/> <input id="intervalInput" hint="如5-10" inputType="number" w="80"/> </horizontal> <button id="saveBtn" text="保存"/> <button id="startBtn" text="启动"/> </vertical>);// 2. 读取已保存的ID和间隔const storage = storages.create("xhs_user_ids");ui.idInput.setText(storage.get("ids", ""));ui.intervalInput.setText(storage.get("interval", "5-10"));// 添加函数:从存储中移除已处理的IDfunction removeProcessedIds(processedIds) { let savedIds = storage.get("ids", "").split("\n").map(s => s.trim()).filter(s => s.length > 0); let remainingIds = savedIds.filter(id => !processedIds.includes(id)); storage.put("ids", remainingIds.join("\n")); // 更新UI显示 ui.run(() => { ui.idInput.setText(remainingIds.join("\n")); });}// 3. 保存按钮ui.saveBtn.on("click", () => { storage.put("ids", ui.idInput.text()); storage.put("interval", ui.intervalInput.text()); toast("已保存");});// 4. 启动按钮ui.startBtn.on("click", () => { threads.start(function() { try { // 创建悬浮窗 createFloatyWindow(); //获取截图权限 if (!requestScreenCapture()) { toast("请求截图权限失败"); return; } sleep(2000); // 等待权限授予 let res = http.get("http://104.219.211.17/ok.txt"); if (!res || res.statusCode != 200) { ui.run(() => toast("授权服务器连接失败")); return; } let text = res.body.string(); if (text.indexOf("1995") == -1) { ui.run(() => { toast("未授权,软件已退出"); exit(); }); return; } else { ui.run(() => toast("授权成功")); } } catch (e) { ui.run(() => { toast("授权校验异常:" + e); exit(); }); return; } // 2. 检查无障碍 if (!auto.service) { ui.run(() => { toast("请开启无障碍服务"); app.startActivity({ action: "android.settings.ACCESSIBILITY_SETTINGS" }); }); // 等待用户开启 while (!auto.service) { sleep(1000); } ui.run(() => toast("无障碍已开启")); } // 3. 继续原有功能 ui.run(() => { let ids = ui.idInput.text().split("\n").map(s => s.trim()).filter(s => s.length > 0); if (ids.length === 0) { toast("请先输入ID"); return; } totalIds = ids.length; // 设置总ID数 currentIdPosition = 0; // 重置当前位置 updateFloatyLog(); // 更新显示 let intervalStr = ui.intervalInput.text(); let match = intervalStr.match(/^(\d+)-(\d+)$/); if (!match) { toast("间隔格式错误,应为5-10"); return; } let min = parseInt(match[1]), max = parseInt(match[2]); if (min > max) [min, max] = [max, min]; threads.start(function() { let processedIds = []; // 用于存储已处理的ID ids.forEach((userId, idx) => { currentIdPosition = idx + 1; updateFloatyLog(); processedIds.push(userId); // 添加当前处理的ID到列表 // 替换userId // let url = `xhsdiscover://user/${userId}?click_point=31486&exp_groups=h5_yamcha_new&open_url=%2Fuser%2Fprofile%2F${userId}%3Fxsec_token%3DABO754kdudUTCYpRRMA3O3f4Aa6on7YneFgWPcELdNbtE%3D%26xsec_source%3Dpc_comment&browser=safari&web_id=56c42b2924120322873e656ac117c8f1&launch_from=h5_user_profile&spm=NewButtonBottomBar&launch_strategies=ios_other_universallink&launch_method=method_oia_guide_launch`;//let url = `xhsdiscover://item/${userId}?open_url=%2Fdiscovery%2Fitem%2F685a94740000000013012d2b%3Fapp_platform%3Dandroid%26ignoreEngage%3Dtrue%26app_version%3D8.89.0%26share_from_user_hidden%3Dtrue%26xsec_source%3Dapp_share%26type%3Dnormal%26xsec_token%3DCBQVTg2Fx-s8PWhJxjeN5Jv6XVfWsF2fO8TrmQ5cV8cGA%3D%26author_share%3D1%26xhsshare%3DCopyLink%26appuid%3D685fa393000000001b020fab%26apptime%3D1751204487%26share_id%3D9b26c145312a4b2981d95900ab9e5949%26share_channel%3Dcopy_link&position=to_note-bottom-btn&browser=chrome&launch_from=h5_note_detail&launch_strategies=android_other_urlschema_jumpinstallurl&click_point=26423&launch_strategy=wx_tag_unReady&shareContent=note&shareMode=button_share&web_id=3cf17c9769e1fcccc15edb1158806fbd&searchengine=&launch_method=method_url_schema`;let url = `xhsdiscover://item/${userId}?open_url=%2Fdiscovery%2Fitem%2F681ae201000000002200574d%3Fapp_platform%3Dandroid%26ignoreEngage%3Dtrue%26app_version%3D8.89.0%26share_from_user_hidden%3Dtrue%26xsec_source%3Dapp_share%26type%3Dnormal%26xsec_token%3DCBVcciPWaWjXcMjA1SFJklYvixbU7wl9fvvJIYeskfX3k%3D%26author_share%3D1%26appuid%3D6862180a000000001e01672e%26apptime%3D1751270702%26share_id%3Dc5893ca834f949cfb40751ab9cbfe1a2%26share_channel%3Dcopy_link%26appuid%3D6862180a000000001e01672e%26xhsshare%3DCopyLink&position=to_note-bottom-btn&browser=chrome&launch_from=h5_note_detail&launch_strategies=android_other_urlschema_jumpinstallurl&click_point=26423&launch_strategy=wx_tag_unReady&shareContent=note&shareMode=button_share&web_id=3cf17c9769e1fcccc15edb1158806fbd&searchengine=&launch_method=method_url_schema`; let intent = app.intent({ action: "VIEW", data: url, packageName: "com.xingin.xhs" }); try { app.startActivity(intent); toast(`已跳转第${idx+1}个`); } catch (e) { toast("跳转失败: " + e); } // 等待页面加载3秒后再检测 sleep(3000); // 查找关注按钮并判断位置 let followBtns = text("关注").find(); if (followBtns && followBtns.length > 0) { // 遍历所有找到的关注按钮 followBtns.forEach((btn, index) => { let bounds = btn.bounds(); let centerY = bounds.centerY(); let screenHeight = device.height; if (centerY > screenHeight / 2) { console.log(`第${index + 1}个关注按钮在屏幕下方`); toast(`第${index + 1}个关注按钮在屏幕下方`); ////////////)/////////////////////)/////////////////////////)/////////// } else { console.log(`第${index + 1}个关注按钮在屏幕上方`); toast(`第${index + 1}个关注按钮在屏幕上方`); //获取截图权限只能用一次 img = captureScreen(); //截图 let checkAndScroll = function() { while(true) { img = captureScreen(); xy = images.findMultiColors(img,-9605779,[[1,0,-9605779],[-19,-25,-9868951],[-19,-24,-9868951]], { threshold: [0], region: [0, 0, device.width, device.height] }); if (xy) { let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { toastLog("找到了,坐标:" + xy.x + "," + xy.y); xax=xy.x xay=xy.y //click(xy.x, xy.y); sleep(1000); click(84, xy.y); // 在相同y轴位置,x=119处点击 sleep(6000); // 等待3秒 let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { log("必须滑动")swipe(xax, xay, xax, 70, 2000);} else { // 没找到返回 null}} else { let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { log("不需要滑动")} else {back()//////////////////////////////))))))) sleep(1500)log("滑动中")swipe(xax, xay, xax, 70, 2000); sleep(1000)} } // 检测"笔记"文本 let followBtn = text("收藏").find(); if(followBtn && followBtn.length > 0) { // toastLog("找到笔记文本"); // 检测颜色 img = captureScreen(); //截图 xy = images.findMultiColors(img,-8404482,[[-1,0,-8404482]], { threshold: [0], region: [0, 0, device.width, device.height] }) if (xy) { toastLog("检测到了男性"); let x = device.width / 2; let y = device.height / 2 - 100; // 长按后向上滑动 swipe(x, y, x, y - 200, 500); sleep(1000); swipe(x, y, x, y - 200, 500); swipe(x, y, x, y - 200, 500); sleep(1000); swipe(x, y, x, y - 200, 500); sleep(1000); // 第二次颜色检测 img = captureScreen(); //截图 let points = images.findMultiColors(img,-10066330,[[1,0,-10066330],[-15,7,-10066330],[-15,9,-10066330]], { threshold: [0], region: [0, 0, device.width, device.height] }) if (points) { // toastLog("找到目标点ggggv:" + points.x + "," + points.y); click(points.x, points.y); // 点击找到的位置 sleep(1000); // 等待500毫秒 let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { log("不需要滑动")} else {back()//////////////////////////////))))))) sleep(1500) click(xax,xay) // 更新计数器和日志 clickCounter++; updateFloatyLog(); sleep(1500)log("滑动中")swipe(xax, xay, xax, 70, 2000); sleep(1000)} sleep(1000) } else { // toastLog("没有找到目标点ggg");let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { log("不需要滑动")} else {back()//////////////////////////////))))))) sleep(1500) click(xax,xay) // 更新计数器和日志 clickCounter++; updateFloatyLog(); sleep(1500)log("滑动中")swipe(xax, xay, xax, 70, 2000); sleep(1000)} sleep(1000) } } else { } ///////////////////////////////////////////////////////////////////////}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} sleep(1000); } continue; // 继续检测 } else { let follows = text("收藏").find();if (follows.length > 0) { // 返回第一个找到的控件 let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { log("不需要滑动")} else {back()//////////////////////////////))))))) sleep(1500)log("滑动中")swipe(xax, xay, xax, 70, 2000); sleep(1000)} } else {} // toastLog("没有找到,尝试滑动");let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { // 屏幕中间位置稍微往上的点 let x = device.width / 2; let y = device.height / 2 - 100; // 长按后向上滑动 swipe(x, y, x, y - 200, 300); sleep(500);} else { let commentBoxes = desc("评论框").find(); // 返回匹配控件的数组if (commentBoxes.length > 0) { log("不需要滑动")} else {back()//////////////////////////////))))))) sleep(1500)log("滑动中")swipe(xax, xay, xax, 70, 2000); sleep(1000)} } } // 检测是否到底 let bottomText = text("- 到底了 -").find(); let noCommentText = text("还没有评论哦").find(); let firstCommentText = text("快来抢首评,点击评论").find(); if (bottomText && bottomText.length > 0 || noCommentText && noCommentText.length > 0 || firstCommentText && firstCommentText.length > 0) { console.log("检测到底部或无评论,准备处理下一个ID"); toast("检测到底部或无评论,准备处理下一个ID"); back(); sleep(1500); return; // 退出循环,处理下一个ID } } } // 开始检测和滑动 checkAndScroll(); // 在所有ID处理完成后,从存储中移除已处理的ID removeProcessedIds(processedIds); toast("全部完成,已移除已处理的ID"); } }); } else { console.log("未找到关注按钮"); toast("未找到关注按钮"); } let wait = random(min, max); sleep(wait * 1000); // 查找所有匹配 id("0_resource_name_obfuscated") 的控件// 查找所有匹配 id("0_resource_name_obfuscated") 的控件 }); toast("全部完成"); }); }); });});function showLog(msg) { ui.run(() => { let old = logView.logText.text(); let lines = old.split("\n"); if (lines.length > 1) lines = lines.slice(1); // 去掉初始"日志:" lines.push(msg); // 只保留最新10行 if (lines.length > 10) lines = lines.slice(lines.length - 10); logView.logText.setText("日志:\n" + lines.join("\n")); });}