小红书项目使用文档
项目启动说明
使用
node xiaohongshuWork/xiaohongshuMain.js <xx>或者npm run xhs启动 使用前请确认已上传 任务文件
<xx> 为对应的机器序号
启动参数代码
const indOffset = 120
const projectInd = Number(process.argv.slice(2)[0]) + indOffset
const keepCookie = true
const packageName = 'com.xingin.xhs'
const activityName = 'com.xingin.xhs.index.v2.IndexActivityV2'
const robotName = `robot${projectInd}`
const projectName = `xiaohongshuWork`
启动参数说明
| Name | Type | example | Description |
|---|---|---|---|
projectInd | number | 0 | 项目机器序号 |
indOffset | number | 120 | 项目序号组(每20为一个项目) |
keepCookie | boolean | true | 启动是否保留手机账号信息 |
packageName | string | com.xxx.xxx | app包名 |
activityName | string | com.xxx.xxx.MainActivity | app活动名 |
robotName | string | robot0 | 对应机器人名称 |
projectName | string | xiaohongshuWork | 项目名称 |
appium设置参数
const opts = {
path: '/',
port: 4723,
capabilities: {
"platformName": "Android",
"appium:noReset": keepCookie,
"appium:newCommandTimeout": "9999",
"appium:automationName": "UiAutomator2",
"appium:disableWindowAnimation": true,
"appium:disableIdLocatorAutocompletion": true,
"appium:limitXPathContextScope": false
},
logLevel: "error",
}
详见appium设置文档 https://appium.io/docs/en/latest/guides/caps/.
任务执行设置
const taskOpt = {
bucket: 'bucket-task', //amz bucket名称
totalRetry: 86400, //获取新任务的尝试次数
taskRetry: 86400, //等待任务开始的尝试次数
totalRetryGap: 10, //单位秒,支持小数
taskRetryGap: 10, //单位秒,支持小数
}
任务类型介绍
const myCapacity = async (act, type, data) => {
let result = ''
switch (type) {
case 'searchVideo':
result = await searchPost(act, data); //在app内搜索某个视频
break;
case 'searchUser':
result = await searchUser(act, data); //在app内搜索某个用户
break;
case 'releaseVideo':
result = await releasePost(act, data); //发布视频
break;
case 'replyMessage':
result = await replyMessage(act, data); //处理消息私信
break;
case 'clearDailyFollow':
result = await clearDailyFollow(projectName); //重置每日关注计数
break;
default:
break;
}
return result
}
读取任务文件中
todoList的type分别使用各个功能
任务文件示例
missionStart参数为false时,代码会循环等待直到其更新为truename参数为json文件名,同时可在bucket-task上查看
name参数说明
| Name | example | Description |
|---|---|---|
robot120 | robot120 | 项目机器序号 |
worklist01 | first,second,*** | 识别文件名并决定优先读取顺序 |
douyin | douyin,wechat,xiaohongshu | 项目名称 |
todoList参数为任务列表,代码会依次识别数组内的type执行对应的功能
{
"missionStart": true, // 任务开始的标志
"name": "robot120--worklist01--xiaohongshu", // 任务的名称
"todoList": [
{
"type": "searchVideo",// 任务类型搜索视频
"data": {
"location": [
"幻兽帕鲁",
"幻兽帕鲁",
"幻兽帕鲁",
"palworld",
"帕鲁世界",
"帕鲁服务器",
"幻兽帕鲁服务器",
"幻兽帕鲁攻略",
"幻兽帕鲁修改器"
], //随机一个搜索关键字
"addLikes": true,//是否点赞
"comment": "", //评论内容
"review": null, //恢复任务标识
"access": { //遍历评论区
"userList": [], //查重数组
"follow": false, //是否关注
"limit": 100, //限制访问人数
"chat": false //是否发送ai私信
}
}
},
{
"type": "searchUser",// 任务类型搜索用户
"data": {
"userName": "嘟嘟助手团_97965599632", //用户名称或id
"follow": false //进入主页是否关注
}
},
{
"type": "replyMessage",// 任务类型处理消息
"data": [
{
"type": "notice" //查看系统消息
},
{
"type": "reply" //回复私信
},
{
"type": "search", //搜索用户并发送消息
"userName": "Starnes",
"text": "测试自动化2"
}
]
},
{
"type": "releaseVideo", // 任务类型
"data": {
"url": "https://video-bucket.s3.cn-northwest-1.amazonaws.com.cn/pal-promo.mp4", // 视频的URL地址
"title": "帕帕云,一键部署服务器轻松玩转幻兽帕鲁。", // 视频的标题
"tags": [
"#幻兽帕鲁",
"#palworld",
"#帕鲁服务器",
"#steam游戏",
"#游戏鉴赏家"
], // 视频的标签数组
"content":"一段内容", // 视频的描述
"location": "", // 视频的地理位置信息
"permission": "公开可见", // 视频的权限设置
"advanced": [
{
"text": "发文助手:自主声明", // 设置的描述文本
"value": "虚构演绎,仅供娱乐/笔记含AI合成内容/内容来源声明" // 设置的值
}
] // 视频发布的高级设置数组
}
}
]
}
代码运行说明
1. checkFile 检查项目所需文件是否存在,如果不存在则创建文件,并初始化数据结构。
await checkFile(projectName);
Source : douyinWork/douyinMain.js,line 407
2. robotApi 查询robot信息。
let robotStat = await robotApi.getInfo();
Source : douyinWork/douyinMain.js,line 409
3. 项目代码卡死重启功能,通过重新创建client实例实现,如有报错则检查adb连接
for (let running = 0; running < 5; running++) {
try{
//...
}
catch{
for (let i = 0; i < 99999; i++) {
let checkAdb = await cmd.runSync(`adb devices`);
let adbData = checkAdb.data.replace("devices", "")
if (adbData.includes("device")) {
console.log(adbData);
break
}
else {
if (i % 2 === 0) { console.log('adb 断开了', i, adbData); }
}
await sleep(2);
}
}
}
Source : douyinWork/douyinMain.js,line 469
4. 创建wdioclient 实例,并创建act类方便使用appium代码。
const client = await wdio.remote(opts);
const act = new MyAction(client);
Source : douyinWork/douyinMain.js,line 424
5. 检测app的状态判断是否拉起app。
let start = await client.queryAppState(packageName)
if (start === 1) {
console.log('启动app');
await client.startActivity(packageName, activityName);
}
else if (start === 3 || start === 2) {
console.log('后台拉出app');
await client.activateApp(packageName);
}
else if (start === 4) {
if (robotStat.step < 4) {
await client.terminateApp(packageName);
await new Promise(resolve => setTimeout(resolve, 2000));
console.log('重新打开app');
await client.startActivity(packageName, activityName);
}
else { console.log('app已启动保持状态'); }
}
Source : douyinWork/douyinMain.js,line 425
6. 调用 main appium脚本主程序。
let runningRes = await main(robotStat, act);
const main = async (robotStat, act, restart) => {
//....
}
Source : douyinWork/douyinMain.js,line 240
7. main: 获取手机号信息。
let phonelist = await phoneListApi.getInfo();
if (!phonelist[projectInd]) return `get phonelist Fail`
else console.log('手机号信息', phonelist[projectInd]);
8. main: 启动appium打开app
let startC = await startChecking(act, restart);
if (startC === 'error') return `startChecking Error ==>> ${startC}`
9. main: 注册/登录
根据需求登录或注册账号,检测到登录完成进入主页时会返回
true,否则返回false并停止main运行。
if (robotStat.step === 1) {
//...
let update = await robotApi.updateInfo(robotStat);
if (!update) return `signUp Update Fail`
}
9. main: 读取任务文件执行功能
获取任务文件,读取任务文件内容并调用myCapacity执行对应功能。
let task = await getLists(queue);
let todoList = await getTodoList(task);
log.notice(`开始执行任务列表, ${i} ==> ${task}`)
let fullComplete = true //任务无错检测
for (let n = 0; n < todoList.length; n++) {
let res = await myCapacity(act, todoList[n].type, todoList[n].data);
if (res.main !== 'over') {
fullComplete = false
errorTimes++
}
else {
errorTimes = 0
}
await updateTask(task, res, todoList[n].type);
log.notice(`任务执行完毕 ==> ${todoList[n].type}`);
}
log.notice(`任务列表执行完毕, ${i} ==> ${task}`);
if (fullComplete) {
log.notice(`所有任务都完成了`);
await updateTask(task, null, null, true);
}
9. main: 任务完成后续处理
防崩溃检测,检测休息弹窗等功能。
await act.waitForElement(['text', '下线提醒'], 3000);
log.warning('被踢下线了');
await act.clickElement(['text', '忽略提醒'], 3000);
log.warning('出现休息弹窗');
let start = await act.client.queryAppState(packageName)
if (start !== 4 || errorTimes > 2) {
log.warning(`~~程序崩溃,重启app, ${errorTimes}`);
await act.client.startActivity(packageName, activityName);
await startChecking(act, restart);
n--
}