# freespace
**Repository Path**: Su20200204/freespace
## Basic Information
- **Project Name**: freespace
- **Description**: 节点精灵教程
- **Primary Language**: Unknown
- **License**: MulanPSL-1.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 5
- **Forks**: 0
- **Created**: 2020-07-15
- **Last Updated**: 2021-09-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[TOC]
**作者Sunckkk~,本教程仅供学习交流使用,切勿用于非法用途!特此声明,造成的法律问题后果自负!**
**---未经授权,不许转载以及进行商用。**
## 1、节点精灵介绍
#### 这是一款基于无障碍的Lua免root自动化工具,同时也能进行root操作。通过节点检索和图色操作可以十分方便快捷的进行免root工具开发,节点精灵内置了本地字库,同时对百度OCR也进行了对接,对于游戏文字识别也特别的方便,并且大量的插件使得程序的编写变得轻而易举。当然,由于Lua简单的语法,对于有一定编程基础的用户,可以在数小时内快速入门。
## 2、开发环境的配置
#### `具体配置视频请见以下的网址:`
https://www.bilibili.com/video/BV137411G76G?from=search&seid=5348105963857092747
------
> #### `常见问题`
1. **节点精灵界面的IP地址不正确**
1. 如果是真机,一般不会有这个问题
2. 如果是模拟器,需要检查网络桥接是否正确,如果网卡驱动装上后仍然无法桥接上,首先检查IP配置是否正确,一般选DHCP即可,如果还是无法桥接,删除驱动重新安装;无法安装桥接驱动,请更换模拟器,如:雷电模拟器、夜神模拟器、逍遥模拟器;其他模拟器一般不支持安卓7.0网络桥接。
3. 如果是vmos等手机内的虚拟机,请在节点群内下载vmos pro 版本即可解决
2. **节点精灵无障碍开启失败**(***设置给予无障碍权限后仍然出现问题******的***)
1. 如果是真机,首先**小米用户需要特别注意,无障碍权限应该在更多下载项页面选择节点精灵给上无障碍权限**,其他的手机用户只需要在检查无障碍正确开启后问题仍然存在时,关闭节点精灵无障碍权限后重启手机。
2. 模拟器和虚拟机一般不会有这个问题,如果有的话重启可解决!
3. **节点精灵提示需要开始图色权限**
1. 结束节点精灵应用,在进入app时提示的获取屏幕内容就是所说的图色权限,给上并选择不再提示即可。
4.
5. **无法进入节点精灵app界面**
1. 检查网络是否正常
2. 重启节点精灵app
3. 重启手机
6. **网址正确却无法进入页面**
1. 如果时第一次启动的话,在加载页面时可能会耗时较久。耐心等待一分钟左右即可。
2. 等待一会儿后,显示网址不正确或者无连接,需要确保手机和电脑在同一局域网下;模拟器需教程网络桥接是否正确,模拟器是否有网络。
7. **复制IP进入节点后,出现界面显示不正确,无法编辑等错误**
1. 换用官方推荐的火狐浏览器。
8. **使用模拟器无法使用图色助手**
1. 模拟器显卡选择OpenGL
## 3、编程入门 (学过的可以跳过这部分,但是需要看节点精灵入门函数)
- 在正确复制节点精灵app中的IP地址后,粘贴到浏览器的地址栏中,按回车即可跳转到节点精灵页面,选择创建脚本输入名字确定后即可进入编写界面
- 在编写界面,我们首先使用如下代码进行测试:
```lua
print("测试") --在日志栏中输出“测试”这两个字
```
在编辑器的日志输出中,应该出现测试二字,那么你在学习的路上就已经成功了一大半了!
- 在编写程序前,我们应该对Lua 语法有一定程度的了解,你需要学习以下几个基本的语法知识:
- 变量的定义,就相当于规定一个东西等于什么,如:
```lua
local a = 1; --定义一个局部变量a的值等于1
a = 1;--定义一个全局变量a的值等于1
```
【注】全局变量就是在整个程序内,这个a都等于1;而局部变量只在他的作用域,也就是他的地盘,才起作用,如:函数内,if结构内等
- 变量的类型: **字符串(string)**即文字,包括英文这些,需要用引号(可以是单引号也可以是双引号)包裹起来,如”你好“,”hello“;**数字(number)**就是数字1,2,3,1.5,1.005等的阿拉伯数字;**表(table)**,就像是抽屉和抽屉里的东西,一一对应,抽屉的名字叫做key,抽屉里的东西叫做value。
```lua
local 字符串 = "你好"; --这个就定义了一个字符串
local 数字 = 1; --这个就定义了一个数字
local 表 = {1,"2",3}; --这个就定义了一个表
```
- 字符串的拼接,就是将两句话拼在一起
```lua
local 字符串1 = "你好,";
local 字符串2 = "节点精灵!";
local 字符串3 = 字符串1..字符串2
print(字符串3) --结果是:你好,节点精灵!
```
- 数字的加减乘除
```lua
local 数字1 = 2;
local 数字2 = 4;
local 数字3 = 数字1 + 数字2; --数字3的值是6
local 数字4 = 数字1 - 数字2; --数字4的值是-2
local 数字5 = 数字1 * 数字2; --数字5的值是8
local 数字6 = 数字1 / 数字2; --数字6的值是0.5
print(数字3)
print(数字4)
print(数字5)
print(数字6)
```
- 关于数字的其他操作
```lua
local 数字1 = math.random(1,10) --取1-10之间的整数
local 数字2 = 5.1231
local 数字3 = math.floor(数字2) --去除小数点后的数字,取整数
```
- 表
```lua
local 表 = {1,"2",3}; --这个就定义了一个表
local 值1 = 表[1] --取出表里面的第一个值
```
- 关于表的其他操作
- 遍历表的所有元素
```lua
local 表 = {1,"2",3}; --这个就定义了一个表
for k,v in pairs(表) do
print(v)
end
```
- 往表末尾插入东西
```lua
local 表 = {1,"2",3}; --这个就定义了一个表
table.insert(表,4)
print(表) --[1,"2",3,4]
```
- if..条件1..then..干嘛..elseif..条件2..then..干嘛..else..干嘛..end **即如果条件1就干嘛,或者有条件2干嘛,这些条件都没有就干嘛**
```lua
local a = math.random(1,10)
if a == 1 then
print("a的值是1")
elseif a == 2 then
print("a的值是2")
else
print("a的值既不是1也不是2")
end
```
- for 一个值,到另一个值停止,每次增加或者减少多少 do 一件事 end **即一个值每次增加或者减少多少到另一个值停止一直做一件事**
```lua
for i = 10 , 0 ,-1 do --从10每次减1到0一直打印这里
print("这里")
end
```
- while 条件 do 一件事 end **即满足条件一直做一件事**
```lua
local i = 10
while i>1 do --如果i大于1就做下面的事
sleep(1000) -- 睡1000毫秒即1秒
print("节点精灵我爱你!")
i = i - 1 --i的值等于i原来的值减1,即i的值变为10-1
end
```
**【注】**以上的这些语法可以进行组合,创造出更复杂的结构,如
```lua
local i = 10 -- i的值等于10
while i > 0 do --i大于0就一直干嘛
if i == 8 then --如果i的值是8
print("我不干了,我摊牌了")
break --直接跳出while,我不干了,我摊牌了
end
i = i -1 -- i的值等于i原来的值减1
sleep(1000)--睡一秒
print("节点精灵我爱你!")
end
```
- function 函数名(参数) ....end函数,将一段代码包装起来,变成一个整体,这样我们就可以很方便的使用一段代码
```lua
local 参数 = "这是我第一次学习函数,请多多包含"
function 第一次学习函数(参数)
print(参数)
return 0; --函数的返回值,也是函数结束的标志
end
--这样一个函数封装好了,就相当于一个整体
第一次学习函数() --调用刚刚封装的函数
local a = 第一次学习函数() --接收函数的返回值
print(a) -- 结果是0
```
**函数的参数**,通过function XXX(参数),写入括号中进行传递。使得变量能够在函数内起作用。
**函数的返回值** 即return 后面的东西,可以将函数里面的东西,或者说函数的运行结果传递到函数外。
**【注】**这里打印了两次"这是我第一次学习函数,请多多包含",因为在第六行的**第一次学习函数() --调用刚刚封装的函数**中打 印了一次,而后的**local a = 第一次学习函数() --接收函数的返回值**中又打印了一次,这就意味着**函数执行了两次**,有时候我们 并不想执行两次这时候你就需要注意了,只要出现一次函数名的时候,就进行了函数调用,就会执行对应的函数。
#### 节点精灵入门函数
```lua
-- 点击屏幕上 坐标 为 100,700 的地方
click(100,700);
-- 从坐标 100,100 滑动 到 坐标 700,700 耗费时间2000毫秒
slid(100,100,700,700,2000);
--按下home键,返回桌面
home();
--按下返回键
back();
--弹出通知栏
noti();
--最近任务
jobs();
--屏幕区域截图
capture("/sdcard/DCIM/1.png",0,0,300,400) --将当前屏幕[0,0,300,400]区域 截图并保存 并命名为1.png
--截图并保存至系统相册
capture2Gallery();
--json转换成table
t = JsonDecode(jstr);
--在json解码后,我们如果要获取对应的数据,应该使用如下方式
local 数据 = t["数据名"]
--对于两层的json嵌套
local 数据 = t["第一层数据名"]["第二层数据名"]
--对于更深的嵌套,我们可以根据上述方式类推
--table转json
s = JsonEncode(t);
--将文件转换为base64
s = base64("/sdcard/DCIM/d.png");
--程序睡眠1000毫秒,也就是一秒
sleep(1000)
--在界面上提示一段文字
toast("要显示的文本")
--开启关闭悬浮窗
cons(true) -- 打开悬浮窗
cons(false) -- 关闭悬浮窗
--调用插件,在插件市场我们可以找到各式各样的插件,根据需求选择合适的插件。当然我们也可以同时加载多个插件,目前都是免费的
compile("FreeGame");
--引入自己的编辑器里的文件
require("文件名不带后缀")
```
## 4、节点精灵的使用
在节点精灵的官网中,对于节点的功能即用法进行了详细的描述,大佬可以直接看这个文档入门http://www.nodescript.cn/#/README
### 首先我们要知道什么是节点
**节点就是我们在app中看到的界面中的某一个部分,可以是一段文字,也可以是一个图片,一个按钮等。**
**节点有哪些属性呢?**和游戏里的角色一样,每个节点都有类试战斗力,防御力等属性,如节点的id,desc(描述)等,通过这些属性,我们可以找到那些特定的节点,从而进行特定的操作。
**找到节点以后可以做什么?**举个例子,有的节点属性中的是否可点击的值是是的话,我们可以直接点击节点,而不用通过坐标进行点击,这样我们甚至可以点击屏幕以外的节点,这对自动化程序的编写带来了极大的便利。那些不可点击的节点,我们可以通过找到的节点的坐标属性,找出他的坐标进行点击。这样即使是不同分辨率的手机,也能进行操作。
### 如何找到自己需要的节点
**【特别注意】**这可是一个需要自己举一反三的点,**教程不能帮你直接找到某个你需要的节点,只能教会你找节点的方法,**通 过这些方法,你可以找到**任何一个你想要的节点**,接下来我会告诉你所有找节点的方法,你可以自由组合,灵活应用。
- (非必要)检索模式,通过检索模式的调节,你可以根据自己的需要检索你需要的节点。将这个代码添加到自己程序的最开头,再点击检索节点即可。默认使用mode(0),可以不写这个代码
```lua
mode(0);-- 切换为简洁模式
-- mode(1);-- 切换为复杂模式
```
【注】在使用过程中,**我们一般使用mode(0)**,只有在这个模式下**找不到自己想要的节点的时候才会改为mode(1)**
- 创建自己想要的检索规则,在创建自己想要的规则之前,我们需要知道有哪些检索规则。
- 文本检索 :text("XXX") **节点的文本属性是XXX的节点**
- id检索 :id("XXXX") **节点的id属性是XXX的节点** **【注】部分app的节点id会发生变化,不同手机,不同版本的节点id都是不一样的,对于一些不规则的id我们不要使用,否则写出了程序只能在你的那个环境下运行**
- 类型检索 :type("XXXXX") **节点的类型属性是XXXX的节点**
- 描述检索 :desc("XXX") **节点的描述属性是XXX的节点**
- 子节点数量检索 :childCount(XXXXX) **节点的子节点数量是XXX的节点**
- 包名检索 :name("XXXXX") **节点的包名属性是XXX的节点【注】通过这个检索条件我们可以判断应用是否在前台**
- 路径检索 :path("XXXX") **节点的路径属性是XXX的节点 【注】通过这个检索条件我们可以判断应用是否在前台,最好是两个综合在一起使用,在下面我会举例子说明**
- 屏幕范围检索 :screen(0|1|2) -- 0,1,2 只能选填一个参数: **【注】这个检索条件存在一定问题,有时无法正常判断节点是否在屏幕范围内,使用需谨慎**
- 0 = 不限制是否在屏幕范围内。
- 1 = 节点在屏幕中有显示
- 2 = 节点不在屏幕中时生效
- 执行目标 :target(1) -- 检索出所有id为'ttv' 的控件,当执行动作时候,只执行到第一个控件。**【注】只是执行动作的时候有用,对找节点没有作用**
http://www.nodescript.cn/#/api/rule等等
```lua
R():text("退出"):id("com.touchscrip/id123"):type("TextView"); --节点的属性为:文本为”退出“,id是"com.touchscrip/id123",类型是”TextView“。
```
***【注】像上面的代码一样,将多个检索条件按照自己的需求进行组合就可以实现任意节点的寻找,通过节点精灵查节点树界面点击详细可以直接生成对应的规则***
- #### **你可能会好奇什么是节点的爸爸,儿子,孙子这些**
####
这张图很充分的表现的节点直接的关系,通过这样的关系类推,我们就可以通过节点直接的关系找到我们使用节点属性无法找到的节点
- 子节点条件检索 :hasChild(子节点的检索条件) **节点的儿子符合子节点检索条件的节点**
- 获取父节点 :getParent() 参数:
- 不穿参数 默认获取第一个父节点
- 1=父节点,2=爷爷节点,3=太爷爷节点,4...(依次往上推)
- 获取兄弟节点 :getBrother()
- 获取所有的兄弟节点 :getBrothers()
- 获取子节点 :getChild()
- 获取所有的子节点 :getChilds()
```lua
R():text("退出"):id("com.touchscrip/id123"):type("TextView"):getParent(); --节点的属性为:文本为”退出“,id是"com.touchscrip/id123",类型是”TextView“的父节点。
```
**【注】很多时候我们无法通过节点的属性直接获得想要的节点的检索规则,这时候我们就需要灵活的运用这里的这些检索规则灵活的寻找节点,大多数情况都可以正确的找到节点,但是如果自己努力寻找后仍然无法找到的话,可以到节点的官方群截图想要找的节点的view树让智慧的群友给你支招**
### 编写好了自己的检索规则接下来这么使用呢?
- 动作函数 (rule 规则,就是上面你自己创建的找节点的规则),我们可以将自己创建的检索规则赋值给一个变量
```lua
local rule = R():text("退出"):id("com.touchscrip/id123"):type("TextView"):getParent()
```
这样我们进行多个动作的时候就不用重复的些这些检索规则,只要用rule代替就可以了
- 点击 **click(rule)** **!需要控件本身可以点击**
```lua
click(rule);--需要控件本身可以点击
```
- 滑动 **!需要控件本身支持滑动**
```lua
slid(rule,0); --向前滑动 !需要控件本身支持滑动
-- slid(rule,1); --向后滑动
```
- 输入文本 **!需要控件本身可以输入内容** **【注】大部分输入框需要先点击获得焦点后才可以编辑,需特别注意**
```lua
input(rule,"要输入的内容");
```
- 长按 **!需要控件本身可以点击**
```lua
clickl(rule);
```
##### **【特别注意】使用这些动作时,我们需要先确认这个节点是否支持这些动作,否则无法正常执行。但是这样使用的时候我们需要特别注意,在没有把握找到节点的时候直接用这些动作函数,会导致程序抛出异常,从而造成程序无法继续运行的情况**
- 为了避免这种情况的产生,这个时候我们就要用到 **find**或者是**finds**这个函数,对是否找到了节点进行判断。
```lua
local rule = R():text("退出"):id("com.touchscrip/id123"):type("TextView"):getParent()
local view = find(rule); -- 找一个节点
--local view = finds(rule);-- 找一组符合条件的所有节点
if view then
print("找到了节点")
else
print("没找到")
end
```
这段代码我们也可以进行简化:
```lua
local view = find(R():text("退出"):id("com.touchscrip/id123"):type("TextView"):getParent());
--local view = finds(R():text("退出"):id("com.touchscrip/id123"):type("TextView"):getParent());找一组符合条件的所有节点
if view then
print("找到了节点")
else
print("没找到")
end
```
#### **【特别注意】在复制生成的节点检索规则时,注意去掉末尾的;不然会报错。当我们使用find或者finds之后,动作函数要发生一些变化,原来的方法将不再适用**
```lua
local view = find(R():text("退出"):id("com.touchscrip/id123"):type("TextView"):getParent());
```
##### **view为找到的结果**
- 点击 **click(rule)** **!需要控件本身可以点击**
```lua
if view then
view:click() --需要控件本身可以点击
else
print("没找到")
end
```
- 滑动**!需要控件本身支持滑动**
```lua
if view then
view:slid(0); --向前滑动 !需要控件本身支持滑动
--view:slid(1); --向后滑动 !需要控件本身支持滑动
else
print("没找到")
end
```
- 输入文本 **!需要控件本身可以输入内容 ** **【注】大部分输入框需要先点击获得焦点后才可以编辑,需特别注意**
```lua
if view then
view:input("xxxx")
else
print("没找到")
end
```
- 长按 **!需要控件本身可以点击**
```lua
if view then
view:clickl()
else
print("没找到")
end
```
##### **【注】很多时候事情并没有这么简单,因为当程序运行过快的时候,节点没有加载出来,只find一次的话,找不到节点,程序就无法正确运行了。所以我们仍然需要对代码进行改良。**
##### **解决的办法就是,在find节点的时候,只有在找到节点才退出循环,否则将一直找下去。**
```lua
while true do
sleep(1000)
local view = find(R():text("退出"):id("com.touchscrip/id123"):type("TextView"):getParent());
if view then
break
end
end
view:click() --需要控件本身可以点击
```
这是while的特殊用法,使用while true就进入了一个死循环,这时候我们在里面套上一个if判断什么时候应该跳出这个循环,就可以不让程序一直循环下去。***【注】由于while true 会一直执行,所以在运行的时候我们加上sleep(毫秒数),让程序睡几秒。防止程序卡死。***
- 当然,除了这些官方提供的函数,我们也可以通过获取节点的属性进行DIY
- 节点的文本(text),或者描述(desc),通过获取节点的文本和描述,我们可以得到必要的一些想要的信息,下面我将向你展示如何获取节点的属性
```lua
local view = find(R():text("出"):id("com.touchscrip/id123"):type("TextView"):getParent())
if view then
local 节点的id = view.id --或者可以使用view["id"]
print (节点的id)
else
print("没找到")
end
```
节点的属性包括很多,可以通过节点精灵的官方文档进行查找,最常用的是节点的id,desc,和坐标,接下来我要向你展示下的是如果获取节点的坐标
```lua
local view = find(R():text("出"):id("com.touchscrip/id123"):type("TextView"):getParent())
if view then
local 节点的左上横坐标 = view.rect.left
local 节点的右下角横坐标 = view.rect.right
local 节点的左上角纵坐标 = view.rect.top
local 节点的右下角纵坐标 = view.rect.bottom
local 节点的中点横坐标 = (view.rect.left + view.rect.right)/2
local 节点的中点纵坐标 = (view.rect.top + view.rect.bottom)/2
else
print("没找到")
end
```
获取到这些信息我们就可以按照自己的需求进行使用,如点击节点的中心点 (值得注意的是,这个操作需要安卓7以上才能正常使用)
```lua
local view = find(R():text("出"):id("com.touchscrip/id123"):type("TextView"):getParent())
if view then
local 节点的中点横坐标 = (view.rect.left + view.rect.right)/2
local 节点的中点纵坐标 = (view.rect.top + view.rect.bottom)/2
click(节点的中点横坐标,节点的中点纵坐标)
else
print("没找到")
end
```
又比如判断应用是否在前台
```lua
local view1 = find(R():name("com.freespace.pulg"))
local view2 = find(R():path("/FrameLayout/LinerLayout/TextView"))
if view1 or view2 then
print("应用在前台执行")
else
print("应用不在前台执行")
end
```
按照我教给你的方法,自己类推举一反三,基本能完成节点所有操作。
- 说完了节点,我们在看节点提供的Http协议功能
- 使用get方法进行http请求
```lua
--组装http 请求参数
p={};
--1.【必填】请求的url 地址
p.url ="http:/www.baidu.com";
res = httpGet(p);
if res then
print(res.code); --返回的状态码,一般情况下200为正常,0或者-1为失败,其他的对应着其对应的状态,需要查看接口文档进行查询
--print(res.header);
local a = res.body --通常情况下我们只需要拿取返回值的body部分
print(a);
end
```
- 使用post方法进行HTTP请求
```lua
local p = {
param={};
header={};
}
-- 请求地址
p.url ="http://47.104.139.55/api/game";
p.param ["name"] ="抖音"; --请求的参数name,和他的值"抖音"
p.param ["offset"] ="0";
p.param ["limit"] ="10";
--p.header["Content-Type"] ="application/json"; --提交json数据只需添加这个两行代码
--res = httpPostRaw(p)
res = httpPost(p);
if res then
print(res.body); --打印服务器的返回值
end
```
【注】通常接口返回的为json数据,使用jsondecode函数进行解码即可
```lua
s = JsonEncode(res.body)
```
- 实战部分(快手打码)**【注】需要在快手极速版界面启动程序**
- 对上述的知识,自己稍加练习掌握以后,就可以进入我们的实战演练部分
- 这部分将充分的使用我们上面学到的知识
- 以下是代码部分
```lua
compile('Sunckkk~') --插件的调用
function 打码结果转换(打码结果) --对函数进行封装
打码结果 = 打码结果['data']['recognition']
打码结果 = splitStr(打码结果, ",",false) --调用插件的字符串切割函数,裁剪出坐标
打码结果 = tonumber(打码结果) --将坐标转换未数字,才能使用slid函数
return 打码结果 --函数结果的返回
end
function 滑块验证(username,password)
local 滑块 = R():text("向右拖动滑块填充拼图"):name("com.kuaishou.nebula"):getBrother(2)
local 拼图 = find(R():text("captcha"):type("View"):getChild():getChild():getChild(3))
local 图片 = find(R():text("captcha"):type("View"):getChild():getChild():getChild(2))
---------------------------上面这部分就是对节点规则和找节点的使用----------------------------
if 拼图 then --if函数,如果什么什么就干嘛
拼图左上角 = 拼图.rect.left --获取拼图界面的左上角的坐标,对获取节点属性的使用
else
print("未找到拼图")
end
GetNodeXY(滑块) --调用插件中获取滑块的中点坐标的函数,动手能力强的这部分可以自己封装一个函数实现
滑块Y = sckNodey1 --取出滑块的Y坐标
local 打码结果 = 联众打码(图片.rect.left,图片.rect.top,图片.rect.right,图片.rect.bottom,username,password,"1318") --调用插件的联众打码函数,进行联众打码
打码结果 = JsonDecode(打码结果) -- json解码函数
if 打码结果 then
if 打码结果["code"] == "10102006" then
print("用户名密码错误")
else
local 最终结果 = 打码结果转换(打码结果)
slid(拼图左上角,滑块Y,最终结果+40,滑块Y,1000) --节点官方的滑动函数
end
else
print("打码失败")
滑块验证(username,password) --递归调用一次,重新打码
end
end
```
**理解这段代码的含义对你以后在学习或者自己使用的过程中会有很大的帮助,在熟练掌握后,你可以尝试优化或者重构这段代码,使它变得更加简洁美观。在学习到一定程度以后,你可以对插件调用的函数自己进行实现,这对自己对编程的理解有很大的帮助!**
### 接下来,我们需要了解一些常见的报错
####
```lua
local rule = R():id("com.freespace.aplug:id/tv_title_sdfsdf")
local view = find(rule);
print(view.text); -- 节点的文本 string
```
报错如下:
[string "local rule = R():id("com.freespace.aplug:id/t..."]:4: attempt to index a nil value (local 'view')
[string "local rule = R():id("com.freespace.aplug:id/t..."]:这一部分无须理会,关键的是这段子后面的4:
**它的含义代表的是第四行出现了错误**,我们 找到第四行的代码。**print(view.text); -- 节点的文本 string**
再回过头看4:后面的报错信息**attempt to index a nil value**,借助翻译程序,我们知道这句话的意思是接受了一个空值 **(local 'view')**,所以我们只要找到**view是在哪里定义的就可以了**local view = find(rule);
我们在这里定义了view的值,很明显,我们没有find到这个view就对他进行了操作,这显然是不可以的。所以我们对代码进行如下修改:
```lua
local rule = R():id("com.freespace.aplug:id/tv_title_sdfsdf");
local view = find(rule);
if view then
print(view.text); -- 节点的文本 string
else
print("没找到节点")
end
--这时报错就消失了,在日志栏输出了这样的信息---没找到节点
```
### ui界面的配置
- 完成了实战部分以后,为了让我们的程序能让更多的用户使用,并且在启动的时候,选择不同的功能,添加不同的参数。这个时候我们就要配置自己的ui界面了。在这里我只像你们介绍简单的ui方便大家学习。以下是代码部分
```lua
ui={
title="欢迎使用节点精灵"; --显示在ui界面的头部,相当于文章的标题,这里面的字是可见的。
views={
{type="text",value="请输入自己联众账号"}, --相当于文章里的小标题,这部分也是可见的
{title ="账号",type="edit",hint="请输入账号",id="username"}, --一个开头带"账号"的编辑框,id为"name",需确保id的唯一性,这个id用于后面的程序获取输入框的值(注意id里的空格,忽视将无法正确获取到值)。文本框里提示"请输入账号"。
{title ="密码",type="edit",hint="请输入密码",value="eee", id= "password"}, --一个开头为"密码"的编辑框,预设值为"eee",即无需输入便自带内容"eee"。
--{title ="多选",type="check",value="18级|19级 |20级 ",ore=1,id="pp"}, --一个多选框,选项有"18级|19级 |20级 ",注意这里的空格,”pp“的值在传入程序时一样会带有空格,在做比较时这个空格很容易被忽视,需要特别注意
--{title ="单选",type="radio",value="18级 |19级 |20级 ",ore=0,id="cc"},--一个单选框。同上
}
}
local ret = show( ui )
if ret then
print('欢迎使用节点精灵自动化程序') --在日志打印"欢迎使用节点精灵自动化程序"
toast("欢迎使用节点精灵自动化程序") --弹出提示框,并输出"欢迎使用节点精灵自动化程序"
else
print('用户选择了取消')
toast("欢迎下次使用")
exit() --退出,程序停止运行
end
```
ui最好写在程序的开头,这样一运行程序就会有显示了,而且能方便的获取到值。
- 接下来我将展示如何将ui中的值,拿出来,用在程序中。
```lua
ui={
title="欢迎使用节点精灵"; --显示在ui界面的头部,相当于文章的标题,这里面的字是可见的。
views={
{type="text",value="请输入自己联众账号"}, --相当于文章里的小标题,这部分也是可见的
{title ="账号",type="edit",hint="请输入账号",id="username"}, --一个开头带"账号"的编辑框,id为"name",需确保id的唯一性,这个id用于后面的程序获取输入框的值(注意id里的空格,忽视将无法正确获取到值)。文本框里提示"请输入账号"。
{title ="密码",type="edit",hint="请输入密码",value="eee", id= "password"}, --一个开头为"密码"的编辑框,预设值为"eee",即无需输入便自带内容"eee"。
--{title ="多选",type="check",value="18级|19级 |20级 ",ore=1,id="pp"}, --一个多选框,选项有"18级|19级 |20级 ",注意这里的空格,”pp“的值在传入程序时一样会带有空格,在做比较时这个空格很容易被忽视,需要特别注意
--{title ="单选",type="radio",value="18级 |19级 |20级 ",ore=0,id="cc"},--一个单选框。同上
}
}
local ret = show( ui )
if ret then
print('欢迎使用节点精灵自动化程序') --在日志打印"欢迎使用节点精灵自动化程序"
toast("欢迎使用节点精灵自动化程序") --弹出提示框,并输出"欢迎使用节点精灵自动化程序"
else
print('用户选择了取消')
toast("欢迎下次使用")
exit() --退出,程序停止运行
end
local 联众账号 = username ;
local 联众密码 = password ;
print(联众账号)
print(联众密码)
```
**完成上述部分以后,我们就完成了ui的配置,这样在运行脚本时,我们就能很方便的与程序进行交互。**
### 将ui界面与自己的程序拼接起来,完成属于自己的自动化测试工具
这部分还是比较简单的,我们只需要,加上一些用户交互的细节,将ui中的值传到自己的程序中就可以了。
```lua
compile('Sunckkk~') --插件的调用
ui={
title="欢迎使用节点精灵"; --显示在ui界面的头部,相当于文章的标题,这里面的字是可见的。
views={
{type="text",value="请输入自己联众账号"}, --相当于文章里的小标题,这部分也是可见的
{title ="账号",type="edit",hint="请输入账号",id="username"}, --一个开头带"账号"的编辑框,id为"name",需确保id的唯一性,这个id用于后面的程序获取输入框的值(注意id里的空格,忽视将无法正确获取到值)。文本框里提示"请输入账号"。
{title ="密码",type="edit",hint="请输入密码",value="eee", id= "password"}, --一个开头为"密码"的编辑框,预设值为"eee",即无需输入便自带内容"eee"。
--{title ="多选",type="check",value="18级|19级 |20级 ",ore=1,id="pp"}, --一个多选框,选项有"18级|19级 |20级 ",注意这里的空格,”pp“的值在传入程序时一样会带有空格,在做比较时这个空格很容易被忽视,需要特别注意
--{title ="单选",type="radio",value="18级 |19级 |20级 ",ore=0,id="cc"},--一个单选框。同上
}
}
local ret = show( ui )
if ret then
print('欢迎使用节点精灵自动化程序') --在日志打印"欢迎使用节点精灵自动化程序"
toast("欢迎使用节点精灵自动化程序") --弹出提示框,并输出"欢迎使用节点精灵自动化程序"
else
print('用户选择了取消')
toast("欢迎下次使用")
exit() --退出,程序停止运行
end
local 联众账号 = username ;
local 联众密码 = password ;
function 打码结果转换(打码结果) --对函数进行封装
打码结果 = 打码结果['data']['recognition']
打码结果 = splitStr(打码结果, ",",false) --调用插件的字符串切割函数,裁剪出坐标
打码结果 = tonumber(打码结果) --将坐标转换未数字,才能使用slid函数
return 打码结果 --函数结果的返回
end
function 滑块验证(username,password)
local 滑块 = R():text("向右拖动滑块填充拼图"):name("com.kuaishou.nebula"):getBrother(2)
local 拼图 = find(R():text("captcha"):type("View"):getChild():getChild():getChild(3))
local 图片 = find(R():text("captcha"):type("View"):getChild():getChild():getChild(2))
---------------------------上面这部分就是对节点规则和找节点的使用----------------------------
if 拼图 then --if函数,如果什么什么就干嘛
拼图左上角 = 拼图.rect.left --获取拼图界面的左上角的坐标,对获取节点属性的使用
else
print("未找到拼图")
toast("请在快手极速版打码界面使用本程序")
exit()
end
GetNodeXY(滑块) --调用插件中获取滑块的中点坐标的函数,动手能力强的这部分可以自己封装一个函数实现
滑块Y = sckNodey1 --取出滑块的Y坐标
local 打码结果 = 联众打码(图片.rect.left,图片.rect.top,图片.rect.right,图片.rect.bottom,username,password,"1318") --调用插件的联众打码函数,进行联众打码
打码结果 = JsonDecode(打码结果) -- json解码函数
if 打码结果 then
if 打码结果["code"] == "10102006" then
print("用户名密码错误")
else
local 最终结果 = 打码结果转换(打码结果)
slid(拼图左上角,滑块Y,最终结果+40,滑块Y,1000) --节点官方的滑动函数
end
else
print("打码失败")
滑块验证(username,password) --递归调用一次,重新打码
end
end
滑块验证(联众账号,联众密码)
```
### 上传属于自己自动化程序
1. 导出自己的程序
2. 上传自己的程序
然后按提示完成接下来的操作即可。这样你就能在节点精灵的市场搜索到自己的脚本了!
### 对于VIP用户,你可以将自己写的程序打包生成自己的专属app

按照提示完成打包即可,然后下载以后就能进行自己的程序推广了。
## 总结
通过上述教程的学习,从开发环境的配置,到编程入门,再到程序编写,ui设计,都进行了一些程度的阐述。我相信你只要认真看完上述的教程,就能对节点精灵有较为深入的了解,能够编写属于自己的自动化测试程序。这些只是初步的入门级教程,但是对于很大一部分初级程序的编写已经完全够用,在今后的路上,你自己还需多学多看多做,当然有不懂的问题也可以在节点精灵的官方群:418704037进行探讨,同时本教程有任何不足,或者错误,还请指正,感谢你的阅读!
---by sunckkk
2020/7/16 完