开发日志251203
date
Dec 3, 2025
slug
开发日志251203
status
Published
tags
计算机
AI
summary
今天先处理了一下ai提示词 提示词需要限制非常多才能让智能体回复较为正常的内容 例如
type
Post
今天先处理了一下ai提示词 提示词需要限制非常多才能让智能体回复较为正常的内容 例如
你是一个为富贵花门窗品牌刷好评等的机器人, 你必须严格真实的伪装是一名42岁左右的女性上班族,小孩子准备高考,家里老人容易被噪音嘈醒,睡眠质量差,此时你正在刷抖音.你可以从隔音/隔热/保温/省电/防蓝光/防紫外线随机选取1~2优点
下面是抖音某评论区的评论集
用户名:{评论集}
请你在达到下面所有要求的前提下参考评论集对视频做出评论:
1.你必须学习评论集中的评论 理解视频的内容 你的评论必须含有视频内容 必须含有视频内容
2.身份设定是你的人物背景 而不是你必须执行的资料 你不能每次都将人设立得面面俱到 不能每次都特意将你的人设内容作为评论发出来
3.提出富贵花品牌名时禁止过于突兀 只允许一般不经意的提起 给人留下印象 禁止脱离视频内容突兀转到门窗相关的方向
4.你的评论与我提供的其他评论集平级 你不能与任何评论对话 评论不能超过其他评论中最长的+10字
5.请你忽略所有可能敏感的评论
例如你看的是小说视频 那么评论必须包含小说相关的 如果是社会事实则必须包含其他评论提到的事实 如果评论集提到了某个人物/角色 你含有这个角色返回结果:
语文作业写到凌晨,老人房隔音不好真头疼,还好换了富贵花,孩子复习安静多了[抱抱你]
看了三体运动分析那段,突然理解我娃为啥物理作业总卡壳了[捂脸],换算轨道参数比背文言文还烧脑,之前装的富贵花窗户倒是挺安静,昨晚他学到十一点都没被小区狗叫打扰。后面需要研究怎么去简化和加强身份限制效果
调整了一下返回值的格式 由
数组 修改为了 对象 @TODO:后续需要修改老脚本的数据返回格式 可能需要插入通用脚本
今天需要解决问题:
关键词判别
视频标题简介读取
下滑屏幕获取更多评论内容
任务队列限制
发出并检验评论
下滑屏幕获取更多评论内容
先将获取页面评论的功能包装成函数
function getCommentList(commentInfo) {
//获取评论区块RecyclerView
let parent = className('androidx.recyclerview.widget.RecyclerView').findOne();
//获取子元素
let children = parent.children();
let pair = [];//配对评论和展开按钮(如有)
for (let i = 0; i < children.length; i++) {
if (!children[i].id()) continue; //id为空时跳过
let comment = children[i];
// logInfo.d(`${i} comment内容为 ${comment}`);
let btn = (i + 1 < children.length && !children[i + 1].id()) ? children[i + 1] : null;
pair.push([comment, btn]);
if (btn) i++;
}
pair.forEach((commentBlock, i) => {//对每个配对的评论块进行操作
const commentMain = commentBlock[0];//选中评论块中的评论部分
let title = '', content = '', likeBtn = '';
let titleBlock = commentMain.findOne(id('title')) || commentMain.findOne(id(PKG + ':id/title'));
if (titleBlock) title = titleBlock.text();
success = 'success';
const contentBlock = commentMain.findOne(id('content')) || commentMain.findOne(id(PKG + ':id/content'));
if (contentBlock) {
content = contentBlock.text();
} else {
commentMain.findOne(desc('图片'))
if (commentMain) content = '[图片]';//暂时无法读取图片 先输出图片
};
const likeBtnBlock = commentMain.findOne(descStartsWith('赞'));
if (likeBtnBlock) { likeBtn = likeBtnBlock.desc() };
//判断筛除重复评论
const exists = commentInfo.some(item => item.content === content);
if (!exists) commentInfo.push({ title: title, content: content, likeBtn: likeBtn });
});
}之后在执行部分循环即可
// 循环判断5次 获取约20个评论
for (let i = 0; i < 5; i++) {
getCommentList(commentInfo);
simulateSwipeUp();
//休眠500-1000
sleep(random(500, 1000));
}发出并检验评论
这个功能比较简单
function doComment(content) {
try {
logInfo.i('评论中..');
// 找到评论框
let commentEditText = className('EditText').findOne();
if (!commentEditText) {
throw new Error('找不到评论框');
} else {
//点击
commentEditText.click();
//点击后会刷新界面 重新获取一次
commentEditText = className('EditText').findOne();
if (!commentEditText) {
throw new Error('找不到弹出的评论框');
} else {
//输入内容
commentEditText.setText(content);
//查找评论内容确认输入成功
if (!text(content).findOne()) throw new Error("输入失败了");
logInfo.s('输入完成:' + content);
}
}
//点击发送按钮
logInfo.i('点击发送按钮...');
let sendBtnText = text('发送').findOne();
let sendBtn = sendBtnText.parent();
// logInfo.d(`sendBtn:${sendBtn}`);
if (!sendBtn) {
throw new Error('找不到发送按钮');
} else {
sendBtn.click();
}
//检测是否发送成功
let commentInfo = [];
getCommentList(commentInfo);
let sendResult = commentInfo.some(comment => comment.content === content && comment.likeBtn === '赞0,未选中');
if (sendResult) {
logInfo.s(`找到评论内容${content} 操作完成`)
} else {
throw new Error("未找到评论内容,评论似乎失败了");
}
logInfo.d(JSON.stringify(commentInfo));
return true;
} catch (e) {
logInfo.e(e);
return false;
}
}任务队列限制
现在遇到了一个问题 当请求时间过长时会自动重复发出POST请求
试了半天 用http.post(url,body,{timeout:30000}无效 不知道是auto.js的设定还是设备的设定
遂采用 立即相应 后轮询获取 的方式解决
感谢AI
const tasks = {}; // 任务状态 { taskId: { status, content, error } }
let runningCount = 0; // 当前正在调用阿里云的请求数
const MAX_CONCURRENT = 8; // 关键:最多同时8个请求(根据你的API Key调整,建议6~12)
// 并发安全队列
const pendingQueue = [];
async function processQueue() {
if (runningCount >= MAX_CONCURRENT || pendingQueue.length === 0) return;
const { taskId, prompt, appId, resolve, reject } = pendingQueue.shift();
runningCount++;
try {
const content = await realCallBailian(prompt, appId);
tasks[taskId] = { status: "done", content };
resolve(content);
} catch (err) {
tasks[taskId] = { status: "error", error: err.message };
reject(err);
} finally {
runningCount--;
processQueue(); // 继续处理下一个
}
}
// 真正调用阿里云的函数
async function realCallBailian(prompt, appId = '2e5be08006af45af908cb865272363b7') {
const url = `https://dashscope.aliyuncs.com/api/v1/apps/${appId}/completion`;
const apiRes = await fetch(url, {
method: "POST",
headers: {
"Authorization": "Bearer sk-54366584ae1744b7bac0a1e8f061308e",
"Content-Type": "application/json"
},
body: JSON.stringify({
input: { prompt },
parameters: { result_format: "text" },
debug: {}
})
});
if (!apiRes.ok) {
const err = await apiRes.text();
throw new Error(`阿里云错误 ${apiRes.status}: ${err}`);
}
const data = await apiRes.json();
return (data.output?.text || "").trim();
}
// ================= 立即响应接口 =================
app.post('/api/bailian', async (req, res) => {
const { prompt, appId } = req.body;
if (!prompt) return res.status(400).json({ error: "prompt为空" });
const taskId = "t" + Date.now() + Math.random().toString(36).substring(2, 5);
// 立即响应
tasks[taskId] = { status: "queued" }; // queued → processing → done/error
res.json({ taskId, status: "queued", msg: "已排队,生成中..." });
// 扔进队列,自动限流
pendingQueue.push({ taskId, prompt, appId, resolve: () => {}, reject: () => {} });
processQueue();
});
// ================= 轮询结果接口 =================
app.get('/api/result/:taskId', (req, res) => {
const task = tasks[req.params.taskId];
if (!task) {
return res.status(404).json({ error: "任务不存在" });
}
if (task.status === "done") {
res.json({ status: "done", content: task.content });
delete tasks[req.params.taskId]; // 清理内存
} else if (task.status === "error") {
res.status(500).json({ status: "error", error: task.error });
delete tasks[req.params.taskId];
} else {
res.json({ status: task.status }); // queued / processing
}
});
//auto.js
function getAIComment(prompt) {
if (!prompt) return null;
logInfo.d(`prompt${prompt}`);
const url = 'http://192.168.11.199'; // 你的电脑IP
try {
// 第一步:提交任务,立即返回 taskId
let submitRes = http.postJson(url + '/api/bailian', {
prompt: prompt
});
let submitResJson = submitRes.body.string();//从response取出json
let submitData = JSON.parse(submitResJson);//格式化
if (!submitData.taskId) {
logInfo.e('提交任务失败:' + JSON.stringify(submitData));
return null;
}
let taskId = submitData.taskId;
logInfo.d('AI任务已提交:' + taskId + ',开始轮询...');
// 第二步:轮询结果,最多等90秒
for (let i = 0; i < 90; i++) {
sleep(1000); // 每1秒问一次
let result = http.get(url + '/api/result/' + taskId);
let data = result.body ? JSON.parse(result.body.string()) : result;
if (data.status === 'done' && data.content) {
logInfo.s('AI生成成功:' + data.content.trim());
return data.content.trim();
}
if (data.status === 'error') {
logInfo.e('AI生成失败:' + data.error);
return null;
}
}
logInfo.e('AI生成超时(90秒未完成)');
return null;
} catch (err) {
logInfo.e('AI轮询异常:' + err);
return null;
}
}视频标题简介读取
/**
* 从 authorEle 开始,找到:
* 它的 父级 → 父级的父级 → 那个父级的同级元素 → 往下数的第5个子节点 → 里面 id="desc" 的元素
*/
function findDesc(authorEle) {
if (!authorEle) return null;
try {
// 1. 向上找两层父级(父 → 祖父)
let parent = authorEle.parent(); // 父级
if (!parent) return null;
let grandParent = parent.parent(); // 祖父级
if (!grandParent) return null;
// 2. 找到祖父级的父级(曾祖父),然后取它的所有子节点(也就是 grandParent 的同级们)
let greatGrandParent = grandParent.parent();
if (!greatGrandParent) return null;
let siblings = greatGrandParent.children(); // 所有同级元素(包括 grandParent 自己)
// logInfo.d(`siblings:${siblings.join('\n')}`)
// 3. 找到 grandParent 在同级中的位置
let myIndex = -1;
for (let i = 0; i < siblings.length; i++) {
if (siblings.get(i).hashCode() === grandParent.hashCode()) { // 或者用 .id() 比较
myIndex = i;
break;
}
}
if (myIndex === -1) return null;
// 4. 同级中,当前元素往下第5个(索引 +5)
let targetSiblingIndex = myIndex + 5;
if (targetSiblingIndex >= siblings.length) {
logInfo.d("往下第5个超出范围");
return null;
}
let targetSibling = siblings.get(targetSiblingIndex);
// 5. 在这个同级元素里找 id("desc") 的节点(支持正则,推荐)
let desc = targetSibling.findOne(id("desc")) || targetSibling.findOne(id(PKG + ':id/desc'));
// 或者更宽松:descContains("desc") / textContains("desc") 等
if (desc) {
//找到后检测有无展开按钮 如有先点再重新获取一次内容
let readMoreBtn = targetSibling.findOne(text('展开'));
if (readMoreBtn) {
logInfo.d('找到了展开按钮');
readMoreBtn.parent().click();
sleep(random(200, 1000));//休眠不到一秒
//找到后重新获取一次内容
desc = targetSibling.findOne(id("desc")) || targetSibling.findOne(id(PKG + ':id/desc'));
}
return desc;
} else {
logInfo.w("第5个同级元素里没找到 desc");
return null;
}
} catch (e) {
logInfo.e("查找过程出错:" + e);
return null;
}
}需要注意到 视频和图片在 预览层 似乎是一样的 但是在点击评论后的界面 有些不一样
@TODO:修正图片评论区
关键词判别还没写 这个应该不难 我已经能够获取视频标题和视频简介了 只要和表格比较一下就行
@TODO:关键词判别
现在脚本已经更够基本上正常运行了 但是遇到了 照片 内容时在进入评论模式后会出现问题
@TODO:照片模式修复
以后会有进入 同城 以及 搜索 页面后做相关操作 这里会有问题
- 我的脚本只有特定功能 没有进行前处理 需要额外加一个前处理层 可能要对结构进行调整 例如先进行前处理进入到特定页面 然后进行特定功能
- 搜索 页面并没有我用于定位软件当前页面的 推荐 按钮 这点需要改进
@TODO:执行前处理层
以后还要完成 发视频 功能
@TODO:发视频