panchengyong
10 days ago b2d3f7caf927e5b83ec52efb74f1f818dbb15236
commit | author | age
b2d3f7 1 /**
P 2  * 抖音养号第3+天
3  * @type {string}
4  */
5
bc5e1e 6 // 视频标题关键字
X 7 // let videoKeyword = ["短视频代运营", "短视频运营", "短视频运营课程", "短视频剪辑", "短视频剪辑课程"]
8 // let searchKeyWord
9 var deviceNo = ecloud.getDeviceNo(); //设备编号
10 var unique_id = deviceNo.slice(3); //账号
11 var taskId = ecloud.getTaskInfo().taskId; //任务id
12 var taskName = ecloud.getTaskInfo().taskName; //任务名称
13 var tenantId = ''
14 let keyWord = ecloud.getTaskInfo().valueJson['标题关键词'].split('|')
15 let messageList = ecloud.getTaskInfo().valueJson['话术列表'].split('|')
16 var version = '1.0'
17 var serial_num = time()
b2d3f7 18
bc5e1e 19 /**
X 20  * 获取设备信息
21  */
22 getDevice()
23
24 function getDevice() {
25     var d = ecloud.getTaskInfo()
26     let taskId = d.taskId
27     taskId = parseInt(taskId, 10)
28     var url = "http://47.120.7.97:8098/openapi/getTask";
29     var pa = {
30         "dataSecret": "test123"
31     };
32     var x = http.postJSON(url, pa, 10 * 1000);
33     x = JSON.parse(x)
34     for (let i = 0; i < x.length; i++) {
35         if (x[i].taskId === taskId) {
36             tenantId = x[i].tenantId
37         }
38     }
39 }
40
41
42 weights = {
43     like: 15,
44     message: 10,
45     favorites: 5,
46     doNothing: 70
47 }
48
49 // 随机获取本次执行时间
50 // var maxRunningTime = getRandomFutureTimestamp()
51 var maxRunningCount = random(60, 100)
52 var views = 0, like_count = 0, favorites_count = 0, message_count = 0
53
54
55 logd(keyWord)
56
57 let packageName = 'com.ss.android.ugc.aweme';
58
59
60 logd('抖音养号第三天')
61
62 run()
63 main()
64
65 function main() {
66     if (launch(packageName, 50 * 1000, 5) && isHome()) {
67         sleepAndPrintLog('应用启动成功', false, '应用启动')
68         insertTrace('应用启动', '', '', '', '','')
69         while (true) {
70             if (views >= maxRunningCount) {
71                 sleepAndPrintLog("脚本执行结束,浏览" + views + "次,点赞" + like_count + "次,评论" + message_count + "次,收藏" + favorites_count + "次", false, '脚本运行结束')
72                 insertTrace("脚本执行结束", '', '', '', '','')
73                 home()
74                 break
75             }
76             logd("已执行" + views + "次,共" + maxRunningCount + "次")
77             sleepAndPrintLog("已执行" + views + "次,共" + maxRunningCount + "次", false, '')
78             let title = getTitleOnMainActivity()
79             logd(title)
80             let auth = getAuth()
81             if (checkTitle(title)) {
82                 randomSleep()
83                 let option = getRandomOption(weights)
84                 if (option === 'like') {
85                     like()
86                     sleepAndPrintLog('点赞作品', true, '点赞作品', '', title, auth)
87                     insertTrace('点赞作品', title, auth, '', '')
88                 }
89                 if (option === 'message') {
90                     let message_content = messageList[random(0, messageList.length - 1)]
91                     message(message_content)
92                     logd(message_content)
93                     sleepAndPrintLog('评论作品', true, '评论作品', '', title, auth)
94                     insertTrace('评论作品', title, auth, '', message_content)
95                 }
96                 if (option === 'favorites') {
97                     favorites()
98                     sleepAndPrintLog('收藏作品', true, '收藏作品', '', title, auth)
99                     sleepAndPrintLog('收藏作品', true, '收藏作品', '', title, auth)
100                 }
101                 randomSleep()
102             }
103             refreshVideo()
104             views += 1
105         }
106     }
107 }
108
109 function favorites() {
110     let favorites_button = id('com.smile.gifmaker:id/collect_icon').getOneNodeInfo(12000)
111     if (favorites_button) {
112         favorites_button.click()
113         return true
114     }
115     return false
116 }
117
118 function like() {
119     let lick_button = id('com.smile.gifmaker:id/like_icon').getOneNodeInfo(12000)
120     if (lick_button) {
121         lick_button.click()
122         return true
123     }
124     return false
125 }
126
127 function message(messageContent) {
128     let comment_icon = descMatch(".*评论.*").getOneNodeInfo(5000);
129     let input;
130     let send_button;
131     if (comment_icon.click()) {
132         input = clz('android.widget.EditText').getOneNodeInfo(5000);
133         if (input.click()) {
134             randomSleep()
135             clz('android.widget.EditText').getOneNodeInfo(5000).click()
136             randomSleep()
137             if (clz('android.widget.EditText').getOneNodeInfo(5000).inputText(messageContent)) {
138                 logd('输入成功');
139             }
140             randomSleep()
141             send_button = text('发送').getOneNodeInfo(3000)
142             if (send_button.click()) {
143                 logd('发送评论成功')
144                 randomSleep()
145                 back()
146                 return messageContent
147             }
148         }
149     }
150 }
151
152
153 function refreshVideo() {
154     let nickname = getAuth()
155     let title = getTitleOnMainActivity()
156     sleepAndPrintLog('浏览视频', false, '浏览作品', title)
157     insertTrace('浏览视频', title, nickname, '', '')
158     // logd(nickname)
159     // logd(title)
160     swiper()
161     randomSleep()
162
163 }
164
165 // 根据权重选择选项
166 function getRandomOption(weights) {
167     let options = Object.keys(weights);
168     let totalWeight = options.reduce((sum, option) => sum + weights[option], 0);
169     let random = Math.random() * totalWeight;
170     let cumulativeWeight = 0;
171     for (let option of options) {
172         cumulativeWeight += weights[option];
173         if (random < cumulativeWeight) {
174             logd('选择结果为' + option);
175             return option;
176         }
177     }
178 }
179
180
181 /**
182  * description 唤醒设备
183  */
184 function run() {
185     sleepAndPrintLog('脚本开始运行,抖音养号第三天,版本:' + version, false, '脚本启动');
186     insertTrace('脚本启动', '', '', '', '脚本启动',serial_num)
187     //保持设备唤醒
188     importClass(android.os.PowerManager);
189     device.keepAwake(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
190     //保持屏幕唤醒
191     device.keepScreenOn();
192     sleep(1000);
193     swipeToPoint(30, 800, 30, 100, 1000); //设备上滑解锁
194     //脚本停止监听
195     setStopCallback(function () {
196         device.cancelKeepingAwake(); //取消保持唤醒状态
197         sleepAndPrintLog('脚本运行结束', false, '脚本停止');
198         insertTrace('脚本结束', '', '', '', '脚本结束',serial_num)
199
200     });
201     //脚本异常停止监听
202     setExceptionCallback(function (msg) {
203         device.cancelKeepingAwake(); //取消保持唤醒状态
204         sleepAndPrintLog('脚本异常停止消息:' + msg, false, '脚本停止');
205         insertTrace('脚本异常', '', '', '', '脚本异常',serial_num)
206
207     });
208
209 }
210
211
212 function checkTitle(title) {
213     if (!keyWord) {
214         logd('关键字为空')
215         return false
216     }
217     for (let i = 0; i < keyWord.length; i++) {
218         if (title.includes(keyWord[i])) {
219             logd('标题包含关键字:' + keyWord[i])
220             return true
221         }
222     }
223     logd('标题不含关键字')
224     return false
225 }
226
227 function randomSleep() {
228     let min = Math.ceil(3);
229     let max = Math.floor(6);
230     let time = (Math.floor(Math.random() * (max - min + 1)) + min) * 1000;
231     sleep(time);
232 }
233
234
235 /**
236  * description 定位到首页
237  * @return {boolean} : 返回是否成功
238  */
239 function isHome() {
240     let result = false;
241     while (true) {
242         var home_selectors = text("首页").getOneNodeInfo(3000); //首页按钮
243         var message_selectors = text("消息").getOneNodeInfo(3000); //消息按钮
244         //判断是否在首页
245         if (home_selectors && message_selectors) {
246             var follow_selectors = text("关注"); //关注按钮
247             var recommend_selectors = text("推荐"); //推荐按钮
248             if (has(follow_selectors) && has(recommend_selectors)) {
249                 toast('已定位首页');
250                 // randomSleep("已定位到首页", "定位到首页", "", "", "", "");
251                 result = true;
252                 break;
253             } else {
254                 home_selectors.click();
255                 sleep(3000);
256             }
257         } else {
258             toast('返回首页...');
259             //返回上一页
260             go_back(1);
261         }
262     }
263     return result;
264 }
265
266 function getAuth() {
267     try {
268         let auth = id('com.ss.android.ugc.aweme:id/title').clz('android.widget.TextView').getOneNodeInfo(12000)
269         if (auth) {
270             return auth.text
271         }
272     } catch (e) {
273         loge('获取用户名失败')
274         return '获取用户名失败'
275     }
276 }
277
278 function getTitleOnMainActivity() {
279     let title = id('com.ss.android.ugc.aweme:id/desc').clz('android.widget.TextView').getOneNodeInfo(12000)
280     if (title) {
281         return title.text
282     } else {
283         logd('未获取到标题')
284         return '未获取到标题'
285     }
286 }
287
288 /**
289  * 记录信息
290  * @param info
291  * @param isSleep
292  * @param operate_type
293  * @param title
294  */
295 function sleepAndPrintLog(info, isSleep, operate_type, title) {
296     var sleepTime = 0;
297     if (isSleep) {
298         //随机选取3000-5000毫秒休眠时间
299         var min = Math.ceil(30);
300         var max = Math.floor(50);
301         sleepTime = (Math.floor(Math.random() * (max - min + 1)) + min) * 100;
302     }
303     var add = {
304         "tableNameEn": "device_log",
305         "columns": {
306             "task_id": taskId, //任务id
307             "task_name": taskName, //任务名称
308             "device_no": deviceNo, //设备编号
309             "unique_no": unique_id, //账号
310             "platform": "DY", //所属平台
311             "operate_time": timeFormat("yyyy-MM-dd HH:mm:ss") + '', //操作时间
312             "log_detail": info, //日志明细
313             "intervals": sleepTime, //操作间隔
314             "tenant_id": tenantId,
315             'tar_post_name': title,
316             "operate_type": operate_type //操作类型
317         }
318     }
319     ecloud.dynamicAdd(add);
320     sleep(sleepTime);
321 }
322
323
324 /**
325  * description 插入埋点
326  * @param post_name {string} : 作品名称
327  * @param nickname {string} : 用户昵称
328  * @param content
329  * @param keyword {string} : 搜索关键词
330  * @param operate_type {string} : 操作类型
331  * @param serial_num
332  */
333 function insertTrace(operate_type, post_name, nickname, keyword, content,serial_num) {
334     let time = timeFormat("yyyy-MM-dd HH:mm:ss") + '';
335     var deviceNo = ecloud.getDeviceNo(); //设备编号
336     var unique_id = deviceNo.slice(3);
337     let add = {
338         "tableNameEn": "trace",
339         "columns": {
340             "task_id": ecloud.getTaskInfo().taskId,
341             "task_name": ecloud.getTaskInfo().taskName,
342             "device_no": deviceNo, //设备编号
343             "operate_time": time, //操作时间
344             "platform": "DY", //所属平台
345             "unique_no": unique_id, //用户唯一编号
346             "post_name": post_name, //作品名称
347             "nickname": nickname, //用户昵称
348             'comment': content,
349             "keyword": keyword, //搜索关键词
350             "operate_type": operate_type, //操作类型
351             "tenant_id": tenantId,
352             'serial_num':serial_num
353         }
354     }
355     ecloud.dynamicAdd(add);
356 }
357
358 /**
359  * description 通过包名启动应用
360  * @param packageName {string} : 应用包名
361  * @param delay {number} : 启动后等待时长(毫秒)
362  * @param startNum {number} : 重试次数
363  * @return {boolean} : 返回是否成功
364  */
365 function launch(packageName, delay, startNum) {
366     let result = false;
367     //判断应用的包名是否存在
368     if (utils.isAppExist(packageName)) {
369         //判断应用是否在前台
370         if (getRunningPkg() == null) {
371             toast('请开启辅助功能权限');
372             exit();
373         } else if (getRunningPkg() === packageName) {
374             logd('应用已经在前台');
375             result = true;
376         } else {
377             logd('启动应用...');
378             let alert_selectors = text("允许");
379             let num = 0;
380             //判断应用是否启动成功
381             while (num < startNum) {
382                 if (getRunningPkg() === packageName) {
383                     logd('启动成功');
384                     result = true;
385                     break;
386                 } else if (has(alert_selectors)) {
387                     //初次打开应用 可能会弹出是否允许打开的弹窗
388                     let node = alert_selectors.getOneNodeInfo(1000);
389                     if (node) {
390                         node.click();
391                     }
392                 } else {
393                     utils.openApp(packageName);
394                     sleep(delay);
395                     num++;
396                 }
397             }
398         }
399         alert(); //应用启动后处理弹窗
400     } else {
401         toast('应用未安装');
402         exit();
403     }
404     return result;
405 }
406
407
408 /**
409  * description 异步执行线程 处理弹窗
410  * @return {boolean} : 返回是否成功
411  */
412 function alert() {
413     thread.execAsync(function () {
414         logd('启动线程,查找弹窗');
415         let btnText = new Array(
416             "下次再说",
417             "以后再说",
418             "关闭",
419             "允许",
420             "暂不",
421             "暂时不要",
422             "我知道了",
423             "知道了",
424             "取消",
425         );
426         while (true) {
427             for (let i = 0; i < btnText.length; i++) {
428                 // logd('检查弹窗...');
429                 let node = text(btnText[i]).getOneNodeInfo(1000);
430                 if (node) {
431                     node.click();
432                     logd('弹窗已处理');
433                 }
434             }
435             sleep(3000);
436         }
437     });
438     return true;
439 }
440
441
442 /**
443  * description 自定义返回函数
444  * @param page {number} : 返回页数
445  */
446 function go_back(page) {
447     let count = 0;
448     while (count < page) {
449         back();
450         count++;
451         // randomSleep("返回上一页", "返回上一页", "", "", "", "");
452     }
453 }
454
455
456 /**
457  * description 滑动视频
458  * @return {boolean} : 返回是否成功
459  */
460 function swiper() {
461     let result = false;
462     //设定坐标 适配全分辨率
463     let x = device.getScreenWidth() * 7 / 10;
464     let y = device.getScreenHeight() * 8 / 10;
465     let x1 = device.getScreenWidth() * 7 / 10;
466     let y1 = device.getScreenHeight() * 1.5 / 10
467
468     if (rnd_Swipe(x, y, x1, y1, 100, 200, 200)) {
469         sleep(3000);
470         logd("滑动完成");
471         result = true;
472
473     }
474     return result;
475 }
476
477
478 /**
479  * description 仿真随机带曲线滑动
480  */
481 function rnd_Swipe(qx, qy, zx, zy, time, times, timess) {
482     //qx, qy, zx, zy, time 代表起点x,起点y,终点x,终点y,times,timess =随机时间(times,timess)
483     let time1, xxy, point, dx0, dx1, dx2, dx3, xxyy
484     time1 = random(times, timess)
485
486     xxy = [];
487     point = [];
488     dx0 = {
489         "x": qx,
490         "y": qy
491     }
492
493     dx1 = {
494         "x": random(qx - 100, qx + 100),
495         "y": random(qy, qy + 50)
496     }
497     dx2 = {
498         "x": random(zx - 100, zx + 100),
499         "y": random(zy, zy + 50),
500     }
501     dx3 = {
502         "x": zx,
503         "y": zy
504     }
505     for (let i = 0; i < 4; i++) {
506         eval("point.push(dx" + i + ")");
507     }
508     for (let i = 0; i < 1; i += 0.08) {
509         xxyy = [parseInt(bezier_curves(point, i).x), parseInt(bezier_curves(point, i).y)]
510         xxy.push(xxyy);
511     }
512     gesture(xxy, time, time1);
513
514     return true;
515 }
516
517
518 /**
519  * description 贝赛尔曲线
520  */
521 function bezier_curves(cp, t) {
522     let cx, bx, ax, cy, by, ay, tSquared, tCubed, result
523     cx = 3.0 * (cp[1].x - cp[0].x);
524     bx = 3.0 * (cp[2].x - cp[1].x) - cx;
525     ax = cp[3].x - cp[0].x - cx - bx;
526     cy = 3.0 * (cp[1].y - cp[0].y);
527     by = 3.0 * (cp[2].y - cp[1].y) - cy;
528     ay = cp[3].y - cp[0].y - cy - by;
529
530     tSquared = t * t;
531     tCubed = tSquared * t;
532     result = {
533         "x": 0,
534         "y": 0
535     }
536     result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
537     result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
538     return result;
539 }
540
541
542 /**
543  * description 手势
544  */
545 function gesture(swipeList, time, time1) {
546     let touch1, touch2, x, i
547     touch1 = [{"action": 0, "x": swipeList[0][0], "y": swipeList[0][1], "pointer": 1, "delay": time}]
548
549     for (i in swipeList) {
550         ++i;
551         if (i === swipeList.length - 2) {
552             break;
553         }
554         touch1.push({"action": 1, "x": swipeList[i][0], "y": swipeList[i][1], "pointer": 1, "delay": time});
555     }
556     touch1.push({
557         "action": 2,
558         "x": swipeList[swipeList.length - 1][0],
559         "y": swipeList[swipeList.length - 1][1],
560         "pointer": 1,
561         "delay": time
562     })
563
564     x = multiTouch(touch1, null, null, time1);
565     logd('仿真滑动:' + x);
566 }