为了这个简单的功能折腾了半天,我可以搞定的。
本来想弄Selenium 、Power Automate,但是都因为中间环节出问题,疯了,还是搞JavaScript吧,但是我前端又不熟悉啊,后悔没好好学习前端了,想着学习C++更高大上,关键你做的工作也没发挥C++的潜力,你应该找浏览器这种C++工作。
不管了,你还是用JavaScript吧。
https://openi.pcl.ac.cn/eatcosmos/init-openi/debugjob?debugListType=all
chatgpt
浏览器控制台 JavaScript 实现如下功能
//循环开始
//等待"再次调试"按钮class不为"disable"
//选择点击"再次调试"按钮,xpath是 /html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]
//等待2分钟
//选择点击"停止"按钮,xpath是/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[2]
//循环结束
Person:
- 浏览器控制台 JavaScript 实现如下功能
//循环开始
//等待"再次调试"按钮class不为"disable"
//选择点击"再次调试"按钮,xpath是 /html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]
//等待2分钟
//选择点击"停止"按钮,xpath是/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[2]
//循环结束
ChatGPT:
- 你可以使用以下 JavaScript 代码实现你描述的功能:
async function waitForElement(selector) {
while (document.querySelector(selector).classList.contains("disable")) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
async function clickElementByXPath(xpath) {
const element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
element.click();
}
async function main() {
// 循环开始
while (true) {
// 等待"再次调试"按钮class不为"disable"
await waitForElement(".your-button-class"); // 替换为实际的按钮类名
// 选择点击"再次调试"按钮
const againDebugXPath = "/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]";
await clickElementByXPath(againDebugXPath);
// 等待2分钟
await new Promise(resolve => setTimeout(resolve, 2 * 60 * 1000));
// 选择点击"停止"按钮
const stopXPath = "/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[2]";
await clickElementByXPath(stopXPath);
}
}
main();
请注意,这只是一个基本的示例,你需要替换实际的按钮类名和XPath。XPath 通常比较脆弱,可能会受到页面结构变化的影响。最好使用更稳定的选择器,如类名、ID 或其他属性。确保你的网页结构稳定,以便脚本正常运行。
Person:
- VM6778:2 Uncaught (in promise) DOMException: Failed to execute ‘querySelector’ on ‘Document’: The provided selector is empty.
ChatGPT:
- 这个错误表明在调用
document.querySelector(selector)
时提供的选择器为空。这可能是由于你传递给waitForElement
函数的选择器没有匹配到任何元素导致的。
确保你传递给 waitForElement
函数的选择器是正确的,并且它能够匹配到页面上的元素。你可以在浏览器的控制台手动运行这些函数并检查选择器是否有效。如果选择器有效,但页面结构可能在运行脚本期间发生变化,你可能需要调整选择器或在选择器之前加入适当的等待。
如果问题仍然存在,请提供你的完整 JavaScript 代码和页面结构,以便更详细地检查并提供帮助。
Person:
- async function waitForElement(selector) {
while (document.querySelector(selector).classList.contains(“disable”)) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
selector 参数可以传递xpath吗,希望传递一个 再次调试 的xpath变量进去
ChatGPT:
document.querySelector
函数通常用于 CSS 选择器,而不是 XPath。如果你想使用 XPath,你可以使用document.evaluate
方法,但是它返回的是一个 XPathResult 对象而不是直接的元素。因此,你需要调整你的waitForElement
函数来处理 XPath。
下面是一个修改后的代码片段:
async function waitForElement(xpath) {
const getElement = () => document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
while (getElement() && getElement().classList.contains("disable")) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
// 使用示例
const xpath = "/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]";
await waitForElement(xpath);
在这里,waitForElement
函数接受一个 XPath,使用 document.evaluate
获取相应的元素,然后检查该元素的类名是否包含 “disable”。这样,你可以传递 XPath 作为参数,并等待相应的元素状态。
Person:
- await clickElementByXPath(againDebugXPath);
await什么作用?直观显示
ChatGPT:
await
是用于异步 JavaScript 中的关键字,它通常与async
函数一起使用。await
用于等待一个 Promise 对象的解决(fulfillment)或拒绝(rejection)。在这个上下文中,await
用于等待clickElementByXPath(againDebugXPath)
这个异步函数执行完毕。
在你的代码中,clickElementByXPath
函数可能包含一些异步的操作,比如 DOM 元素的点击,可能需要一些时间才能完成。使用 await
关键字,它会让 JavaScript 运行时等待这个异步操作完成,然后再继续执行下一个语句。
在这里,await clickElementByXPath(againDebugXPath);
的作用是等待点击元素的操作完成,确保在执行下一步之前,必须等到点击操作执行完成。如果没有 await
,代码将不会等待异步操作完成,可能会导致后续的代码在异步操作执行之前就执行了。
Person:
-
async function waitForElement(xpath) {
const getElement = () => document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;while (getElement() && getElement().classList.contains(“disable”)) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
// 使用示例
const againDebugXPath = “/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]”;
const stopXPath = “/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[2]”;
async function clickElementByXPath(xpath) {
const element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
element.click();
}
async function main() {
// 循环开始
while (true) {
// 等待"再次调试"按钮class不为"disable"
await waitForElement(againDebugXPath);
// 选择点击"再次调试"按钮
await clickElementByXPath(againDebugXPath);
// 等待2分钟
await new Promise(resolve => setTimeout(resolve, 1 * 60 * 1000));
// 等待"停止"按钮class不为"disable"
// 选择点击"停止"按钮
await clickElementByXPath(stopXPath);
}
}
main();
Promise {}[[Prototype]]: Promise[[PromiseState]]: “pending”[[PromiseResult]]: undefined 打印这些什么意思?
为什么停止了?应该循环的啊,点击停止后似乎推出循环了?
ChatGPT:
- 你的代码在执行时会进入一个无限循环,并且在点击"停止"按钮后似乎陷入了问题。原因可能是点击"停止"按钮后,可能导致页面的重新加载或发生了一些其他影响循环的事件。此外,在你的代码中没有包含等待"停止"按钮状态不为"disable"的逻辑,这也可能导致问题。
为了更好地调试和了解发生了什么,你可以在循环中加入一些日志输出,以便在控制台中查看程序执行的过程。例如:
async function main() {
// 循环开始
while (true) {
console.log("Waiting for '再次调试' button...");
// 等待"再次调试"按钮class不为"disable"
await waitForElement(againDebugXPath);
console.log("Clicking '再次调试' button...");
// 选择点击"再次调试"按钮
await clickElementByXPath(againDebugXPath);
console.log("Waiting for 2 minutes...");
// 等待2分钟
await new Promise(resolve => setTimeout(resolve, 2 * 60 * 1000));
console.log("Waiting for '停止' button...");
// 等待"停止"按钮class不为"disable"
await waitForElement(stopXPath);
console.log("Clicking '停止' button...");
// 选择点击"停止"按钮
await clickElementByXPath(stopXPath);
}
}
这样可以帮助你更清晰地看到程序执行的步骤,以便定位问题。
此外,你还可以考虑加入一些额外的安全机制,例如设置一个计数器,限制循环次数,以防止陷入无限循环。
Person:
- await waitForElement(stopXPath);
console.log(“Clicking ‘停止’ button…”); 能不能改成阻塞等待
ChatGPT:
- 如果你想要等待
waitForElement(stopXPath)
完成后再执行后续的代码,可以将waitForElement
函数改为返回一个解决后的 Promise。在waitForElement
函数的最后,当等待结束后,你可以使用resolve
将 Promise 解决。
下面是修改的代码:
async function waitForElement(xpath) {
return new Promise(resolve => {
const checkElement = () => {
const element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (element && !element.classList.contains("disable")) {
resolve();
} else {
setTimeout(checkElement, 1000);
}
};
checkElement();
});
}
async function main() {
// 循环开始
while (true) {
console.log("Waiting for '再次调试' button...");
// 等待"再次调试"按钮class不为"disable"
await waitForElement(againDebugXPath);
console.log("Clicking '再次调试' button...");
// 选择点击"再次调试"按钮
await clickElementByXPath(againDebugXPath);
console.log("Waiting for 2 minutes...");
// 等待2分钟
await new Promise(resolve => setTimeout(resolve, 2 * 60 * 1000));
console.log("Waiting for '停止' button...");
// 等待"停止"按钮class不为"disable"
await waitForElement(stopXPath);
console.log("Clicking '停止' button...");
// 选择点击"停止"按钮
await clickElementByXPath(stopXPath);
}
}
这样,await waitForElement(stopXPath);
将等待 waitForElement
函数的解决,并在解决后执行后续的代码。
Person:
- while (true) { 改为循环特定次数
ChatGPT:
- 如果你想在循环特定的次数后结束,你可以使用一个计数器变量来追踪循环次数,并在达到特定次数时跳出循环。例如:
async function main() {
const maxIterations = 10; // 设置循环的最大次数
let iterationCount = 0;
while (iterationCount < maxIterations) {
console.log(`Iteration ${iterationCount + 1}`);
console.log("Waiting for '再次调试' button...");
// 等待"再次调试"按钮class不为"disable"
await waitForElement(againDebugXPath);
console.log("Clicking '再次调试' button...");
// 选择点击"再次调试"按钮
await clickElementByXPath(againDebugXPath);
console.log("Waiting for 2 minutes...");
// 等待2分钟
await new Promise(resolve => setTimeout(resolve, 2 * 60 * 1000));
console.log("Waiting for '停止' button...");
// 等待"停止"按钮class不为"disable"
await waitForElement(stopXPath);
console.log("Clicking '停止' button...");
// 选择点击"停止"按钮
await clickElementByXPath(stopXPath);
iterationCount++;
}
console.log(`Reached maximum iterations: ${maxIterations}`);
}
在这个例子中,maxIterations
是你想要执行的循环次数的上限。每次循环时,增加 iterationCount
的值,当 iterationCount
达到 maxIterations
时,循环就会结束。
Person:
- 如何中断 控制台 死循环
ChatGPT:
- 在控制台中执行的 JavaScript 代码如果陷入了死循环,可以通过以下几种方法中断:
- 手动停止脚本执行: 在浏览器的开发者工具中,你可以手动停止脚本的执行。通常,这可以通过点击开发者工具的“停止”按钮(一般是一个红色的方块)来实现。这会终止当前正在执行的脚本。
- 刷新页面: 刷新页面会导致当前的 JavaScript 执行中断,并重新加载页面。这可以通过浏览器刷新按钮或者使用快捷键(通常是 F5 或者 Ctrl+R)来完成。
- 关闭/重新打开开发者工具: 关闭开发者工具会中断当前的 JavaScript 执行。你可以通过关闭开发者工具,然后重新打开来中止脚本。
- ** 终止执行:** 在浏览器控制台中,你可以尝试使用
Ctrl+C
组合键来强制中断执行。在某些情况下,这可能会中断脚本。 - 清除控制台: 清除控制台的所有输出有时候也可以帮助中断执行。你可以通过执行
console.clear()
或者手动清除控制台来尝试。
请注意,这些方法的有效性可能取决于浏览器和具体的情况。在实际中,最好的做法是编写代码时注意避免死循环,或者在循环中添加一些条件来确保在合适的时候退出循环。
Person:
-
完整代码
async function waitForElement(xpath) {
console.log(“async function waitForElement(xpath)…”);
const getElement = () => document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;while (getElement() && getElement().classList.contains(“disabled”)) {
console.log(“Waiting for element…”);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
// 使用示例
const againDebugXPath = “/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]”;
const debugXPath = “/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]”;
const stopXPath = “/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[2]”;
async function clickElementByXPath(xpath) {
const element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
element.click();
}
async function main() {
const maxIterations = 3; // 设置循环的最大次数
let iterationCount = 0;
while (iterationCount < maxIterations) {
console.log(“>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>”);
// 选择点击"再次调试"按钮
console.log(“Clicking ‘再次调试’ button…”);
await waitForElement(againDebugXPath); //等待disabled属性消失
await clickElementByXPath(againDebugXPath);
await waitForElement(debugXPath); //等待disabled属性消失
//点击调试按钮
//console.log("Clicking '调试' button...");
//await clickElementByXPath(debugXPath);
console.log("#######################################");
console.log("Waiting for 28 minutes...");
// 等待28分钟
await new Promise(resolve => setTimeout(resolve, 28 * 60 * 1000));
//await new Promise(resolve => setTimeout(resolve, 1 * 10 * 1000));
// 选择点击"停止"按钮
console.log("Clicking '停止' button...");
//await waitForElement(stopXPath); //等待disabled属性消失
await clickElementByXPath(stopXPath);
iterationCount++;
console.log("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
main();
ChatGPT:
- 看起来你的代码主要用于模拟在页面上进行一系列操作,并在每次迭代中等待一段时间。我留意到你在
waitForElement
函数中等待元素的类名不为 “disabled”,但在代码中你使用的是 “classList.contains(“disabled”)”。这可能会导致等待条件出现问题,因为你的代码中元素可能是 “classList.contains(“disable”)” 而不是 “classList.contains(“disabled”)”。
你可以调整 waitForElement
函数中的条件,确保与页面上元素的实际类名匹配。此外,你还可以加入一些错误处理机制,以便更好地了解在代码执行过程中是否出现了问题。下面是稍作修改的代码:
async function waitForElement(xpath, className) {
console.log(`Waiting for element with XPath: ${xpath} and class: ${className}...`);
const getElement = () => document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
while (getElement() && getElement().classList.contains(className)) {
console.log("Element still has the expected class, waiting...");
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
// 使用示例
const againDebugXPath = "/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]";
const debugXPath = "/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[1]";
const stopXPath = "/html/body/div[2]/div[3]/div[2]/div[1]/div[2]/div[1]/div/div[3]/table/tbody/tr[1]/td[6]/div/div/a[2]";
async function main() {
const maxIterations = 3; // 设置循环的最大次数
let iterationCount = 0;
while (iterationCount < maxIterations) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
// 选择点击"再次调试"按钮
console.log("Clicking '再次调试' button...");
await waitForElement(againDebugXPath, "disable"); // 等待类名不为 "disable"
await clickElementByXPath(againDebugXPath);
await waitForElement(debugXPath, "disable"); // 等待类名不为 "disable"
console.log("#######################################");
console.log("Waiting for 28 minutes...");
// 等待28分钟
await new Promise(resolve => setTimeout(resolve, 28 * 60 * 1000));
// 选择点击"停止"按钮
console.log("Clicking '停止' button...");
await clickElementByXPath(stopXPath);
iterationCount++;
console.log("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
main();
请确保类名与页面上的实际类名匹配,并适时修改。如果你在执行中遇到问题,也可以检查浏览器控制台是否有错误消息,以帮助定位问题。