mirror of
https://github.com/NaiboWang/EasySpider.git
synced 2025-04-16 16:26:56 +08:00
Code Online Debugging!!!
This commit is contained in:
parent
32f357a866
commit
de547cac11
Binary file not shown.
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const {app, BrowserWindow, dialog, ipcMain, screen, session} = require('electron');
|
||||
app.commandLine.appendSwitch("--disable-http-cache");
|
||||
const {Builder, By, Key, until} = require("selenium-webdriver");
|
||||
const {Builder, By, Key, until, Select, StaleElementReferenceException} = require("selenium-webdriver");
|
||||
const chrome = require('selenium-webdriver/chrome');
|
||||
const {ServiceBuilder} = require('selenium-webdriver/chrome');
|
||||
const {rootCertificates} = require('tls');
|
||||
@ -16,14 +16,14 @@ const util = require('util');
|
||||
let config = fs.readFileSync(path.join(task_server.getDir(), `config.json`), 'utf8');
|
||||
config = JSON.parse(config);
|
||||
|
||||
if(config.debug){
|
||||
if (config.debug) {
|
||||
let logPath = 'info.log'
|
||||
let logFile = fs.createWriteStream(logPath, { flags: 'a' })
|
||||
console.log = function() {
|
||||
let logFile = fs.createWriteStream(logPath, {flags: 'a'})
|
||||
console.log = function () {
|
||||
logFile.write(util.format.apply(null, arguments) + '\n')
|
||||
process.stdout.write(util.format.apply(null, arguments) + '\n')
|
||||
}
|
||||
console.error = function() {
|
||||
console.error = function () {
|
||||
logFile.write(util.format.apply(null, arguments) + '\n')
|
||||
process.stderr.write(util.format.apply(null, arguments) + '\n')
|
||||
}
|
||||
@ -39,7 +39,7 @@ let chromeBinaryPath = "";
|
||||
let execute_path = "";
|
||||
console.log(process.arch);
|
||||
|
||||
exec(`wmic os get Caption`, function(error, stdout, stderr) {
|
||||
exec(`wmic os get Caption`, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
console.error(`执行的错误: ${error}`);
|
||||
return;
|
||||
@ -120,7 +120,7 @@ function createWindow() {
|
||||
|
||||
// and load the index.html of the app.
|
||||
// mainWindow.loadFile('src/index.html');
|
||||
mainWindow.loadURL(server_address + '/index.html?user_data_folder=' + config.user_data_folder+"©right=" + config.copyright, { extraHeaders: 'pragma: no-cache\n' });
|
||||
mainWindow.loadURL(server_address + '/index.html?user_data_folder=' + config.user_data_folder + "©right=" + config.copyright, {extraHeaders: 'pragma: no-cache\n'});
|
||||
// 隐藏菜单栏
|
||||
const {Menu} = require('electron');
|
||||
Menu.setApplicationMenu(null);
|
||||
@ -135,6 +135,134 @@ function createWindow() {
|
||||
}
|
||||
|
||||
|
||||
async function findElementRecursive(driver, by, value, frames) {
|
||||
for (const frame of frames) {
|
||||
try {
|
||||
// Try to switch to the frame
|
||||
try {
|
||||
await driver.switchTo().frame(frame);
|
||||
} catch (error) {
|
||||
if (error.name.indexOf('StaleElement') >= 0) {
|
||||
// If the frame is stale, switch to the parent frame and then retry switching to the frame
|
||||
await driver.switchTo().parentFrame();
|
||||
await driver.switchTo().frame(frame);
|
||||
} else {
|
||||
// If it is another exception rethrow it
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
let element;
|
||||
try {
|
||||
// Attempt to find the element in this frame
|
||||
element = await driver.findElement(by(value));
|
||||
return element;
|
||||
} catch (error) {
|
||||
if (error.name.indexOf('NoSuchElement') >= 0) {
|
||||
// The element was not found in this frame, recurse into nested iframes
|
||||
const nestedFrames = await driver.findElements(By.tagName("iframe"));
|
||||
if (nestedFrames.length > 0) {
|
||||
element = await findElementRecursive(driver, by, value, nestedFrames);
|
||||
if (element) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it is another exception, log it
|
||||
console.error(`Exception while processing frame: ${error}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Exception while processing frame: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Element ${value} not found in any frame or iframe`);
|
||||
}
|
||||
|
||||
async function findElement(driver, by, value, iframe = false) {
|
||||
// Switch back to the main document
|
||||
await driver.switchTo().defaultContent();
|
||||
|
||||
if (iframe) {
|
||||
const frames = await driver.findElements(By.tagName("iframe"));
|
||||
if (frames.length === 0) {
|
||||
throw new Error(`No iframes found in the current page while searching for ${value}`);
|
||||
}
|
||||
const element = await findElementRecursive(driver, by, value, frames);
|
||||
return element;
|
||||
} else {
|
||||
// Find element in the main document as normal
|
||||
let element = await driver.findElement(by(value));
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
async function findElementAcrossAllWindows(msg) {
|
||||
let handles = await driver.getAllWindowHandles();
|
||||
// console.log("handles", handles);
|
||||
let content_handle = current_handle;
|
||||
let id = -1;
|
||||
try {
|
||||
id = msg.message.id;
|
||||
} catch {
|
||||
id = msg.id;
|
||||
}
|
||||
if (id == -1) { //如果是-1,从当前窗口开始搜索
|
||||
content_handle = current_handle;
|
||||
} else {
|
||||
content_handle = handle_pairs[id];
|
||||
}
|
||||
// console.log(msg.message.id, content_handle);
|
||||
let order = [...handles.filter(handle => handle != current_handle && handle != content_handle), current_handle, content_handle]; //搜索顺序
|
||||
let len = order.length;
|
||||
let element = null;
|
||||
let iframe = false;
|
||||
try {
|
||||
iframe = msg.message.iframe;
|
||||
} catch {
|
||||
iframe = msg.iframe;
|
||||
}
|
||||
if (iframe) {
|
||||
notify_browser("在IFrame中执行操作可能需要较长时间,请耐心等待。", "Executing operations in IFrame may take a long time, please wait patiently.", "info");
|
||||
}
|
||||
let xpath = "";
|
||||
try {
|
||||
xpath = msg.message.xpath;
|
||||
} catch {
|
||||
xpath = msg.xpath;
|
||||
}
|
||||
let notify = false;
|
||||
while (true) {
|
||||
// console.log("handles");
|
||||
try {
|
||||
let h = order[len - 1];
|
||||
console.log("current_handle", current_handle);
|
||||
if (h != null && handles.includes(h)) {
|
||||
await driver.switchTo().window(h);
|
||||
current_handle = h;
|
||||
console.log("switch to handle: ", h);
|
||||
}
|
||||
element = await findElement(driver, By.xpath, xpath, iframe);
|
||||
break;
|
||||
} catch (error) {
|
||||
console.log("len", len);
|
||||
len = len - 1;
|
||||
if (!notify) {
|
||||
notify = true;
|
||||
notify_browser("正在尝试在其他窗口中查找元素,请耐心等待。", "Trying to find elements in other windows, please wait patiently.", "info");
|
||||
}
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (element == null) {
|
||||
notify_browser("无法找到元素,请检查xpath是否正确:" + xpath, "Cannot find the element, please check if the xpath is correct: " + xpath, "warning");
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
async function beginInvoke(msg, ws) {
|
||||
if (msg.type == 1) {
|
||||
if (msg.message.id != -1) {
|
||||
@ -145,13 +273,13 @@ async function beginInvoke(msg, ws) {
|
||||
url = server_address + `/taskGrid/FlowChart.html?id=${msg.message.id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address;
|
||||
}
|
||||
console.log(url);
|
||||
flowchart_window.loadURL(url, { extraHeaders: 'pragma: no-cache\n' });
|
||||
flowchart_window.loadURL(url, {extraHeaders: 'pragma: no-cache\n'});
|
||||
}
|
||||
mainWindow.hide();
|
||||
// Prints the currently focused window bounds.
|
||||
// This method has to be called on macOS before changing the window's bounds, otherwise it will throw an error.
|
||||
// It will prompt an accessibility permission request dialog, if needed.
|
||||
if(process.platform != "linux" && process.platform != "darwin"){
|
||||
if (process.platform != "linux" && process.platform != "darwin") {
|
||||
const {windowManager} = require("node-window-manager");
|
||||
const window = windowManager.getActiveWindow();
|
||||
console.log(window);
|
||||
@ -169,74 +297,15 @@ async function beginInvoke(msg, ws) {
|
||||
// 键盘输入事件
|
||||
// const robot = require("@jitsi/robotjs");
|
||||
let keyInfo = msg.message.keyboardStr;
|
||||
let handles = await driver.getAllWindowHandles();
|
||||
console.log("handles", handles);
|
||||
let exit = false;
|
||||
let content_handle = handle_pairs[msg.message.id];
|
||||
console.log(msg.message.id, content_handle);
|
||||
let order = [...handles.filter(handle => handle != current_handle && handle != content_handle), current_handle, content_handle]; //搜索顺序
|
||||
let len = order.length;
|
||||
while (true) {
|
||||
// console.log("handles");
|
||||
try{
|
||||
let iframe = msg.message.iframe;
|
||||
let enter = false;
|
||||
if (/<enter>/i.test(keyInfo)) {
|
||||
keyInfo = keyInfo.replace(/<enter>/gi, '');
|
||||
enter = true;
|
||||
}
|
||||
let h = order[len - 1];
|
||||
console.log("current_handle", current_handle);
|
||||
if(h != null && handles.includes(h)){
|
||||
await driver.switchTo().window(h);
|
||||
current_handle = h;
|
||||
console.log("switch to handle: ", h);
|
||||
}
|
||||
// await driver.executeScript("window.stop();");
|
||||
// console.log("executeScript");
|
||||
if(!iframe){
|
||||
let element = await driver.findElement(By.xpath(msg.message.xpath));
|
||||
console.log("Find Element at handle: ", current_handle);
|
||||
// 使用正则表达式匹配 '<enter>',不论大小写
|
||||
await element.sendKeys(Key.HOME, Key.chord(Key.SHIFT, Key.END), keyInfo);
|
||||
if(enter){
|
||||
await element.sendKeys(Key.ENTER);
|
||||
}
|
||||
console.log("send key");
|
||||
break;
|
||||
} else {
|
||||
let iframes = await driver.findElements(By.tagName('iframe'));
|
||||
// 遍历所有的 iframe 并点击里面的元素
|
||||
for(let i = 0; i < iframes.length; i++) {
|
||||
let iframe = iframes[i];
|
||||
// 切换到 iframe
|
||||
await driver.switchTo().frame(iframe);
|
||||
// 在 iframe 中查找并点击元素
|
||||
let element;
|
||||
try {
|
||||
element = await driver.findElement(By.xpath(msg.message.xpath));
|
||||
} catch (error) {
|
||||
console.log('No such element found in the iframe');
|
||||
}
|
||||
if (element) {
|
||||
await element.sendKeys(Key.HOME, Key.chord(Key.SHIFT, Key.END), keyInfo);
|
||||
if(enter){
|
||||
await element.sendKeys(Key.ENTER);
|
||||
}
|
||||
}
|
||||
// 完成操作后切回主文档
|
||||
await driver.switchTo().defaultContent();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log("len", len);
|
||||
len = len - 1;
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let enter = false;
|
||||
if (/<enter>/i.test(keyInfo)) {
|
||||
keyInfo = keyInfo.replace(/<enter>/gi, '');
|
||||
enter = true;
|
||||
}
|
||||
let element = await findElementAcrossAllWindows(msg);
|
||||
await element.sendKeys(Key.HOME, Key.chord(Key.SHIFT, Key.END), keyInfo);
|
||||
if (enter) {
|
||||
await element.sendKeys(Key.ENTER);
|
||||
}
|
||||
} else if (msg.type == 3) {
|
||||
try {
|
||||
@ -245,76 +314,144 @@ async function beginInvoke(msg, ws) {
|
||||
let message = JSON.parse(msg.message.pipe);
|
||||
let type = message.type;
|
||||
console.log("FROM Browser: ", message);
|
||||
console.log("Iframe:", message.iframe);
|
||||
if(type.indexOf("Click")>=0){
|
||||
// 鼠标点击事件
|
||||
let iframe = message.iframe;
|
||||
let handles = await driver.getAllWindowHandles();
|
||||
console.log("handles", handles);
|
||||
let exit = false;
|
||||
let content_handle = handle_pairs[message.id];
|
||||
console.log(message.id, content_handle);
|
||||
let order = [...handles.filter(handle => handle != current_handle && handle != content_handle), current_handle, content_handle]; //搜索顺序
|
||||
let len = order.length;
|
||||
while(true) {
|
||||
try{
|
||||
let h = order[len - 1];
|
||||
console.log("current_handle", current_handle);
|
||||
if(h != null && handles.includes(h)){
|
||||
await driver.switchTo().window(h); //执行失败会抛出异常
|
||||
current_handle = h;
|
||||
console.log("switch to handle: ", h);
|
||||
}
|
||||
//下面是找到窗口的情况下
|
||||
if(!iframe){
|
||||
let element = await driver.findElement(By.xpath(message.xpath));
|
||||
await element.click();
|
||||
break;
|
||||
} else {
|
||||
let iframes = await driver.findElements(By.tagName('iframe'));
|
||||
// 遍历所有的 iframe 并点击里面的元素
|
||||
for(let i = 0; i < iframes.length; i++) {
|
||||
let iframe = iframes[i];
|
||||
// 切换到 iframe
|
||||
await driver.switchTo().frame(iframe);
|
||||
// 在 iframe 中查找并点击元素
|
||||
let element;
|
||||
try {
|
||||
element = await driver.findElement(By.xpath(message.xpath));
|
||||
} catch (error) {
|
||||
console.log('No such element found in the iframe');
|
||||
}
|
||||
if (element) {
|
||||
await element.click();
|
||||
}
|
||||
// 完成操作后切回主文档
|
||||
await driver.switchTo().defaultContent();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("len", len); //如果没有找到元素,就切换到下一个窗口
|
||||
len = len - 1;
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type.indexOf("Click") >= 0 || type.indexOf("Move") >= 0) {
|
||||
let element = await findElementAcrossAllWindows(message);
|
||||
if (type.indexOf("Click") >= 0) {
|
||||
await click_element(element);
|
||||
} else if (type.indexOf("Move") >= 0) {
|
||||
await driver.actions().move({origin: element}).perform();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
socket_window.send(msg.message.pipe);
|
||||
for(let i in allWindowSockets){
|
||||
try{
|
||||
allWindowSockets[i].send(msg.message.pipe);
|
||||
} catch {
|
||||
console.log("Cannot send to socket with id: ", allWindowScoketNames[i]);
|
||||
}
|
||||
}
|
||||
send_message_to_browser(msg.message.pipe);
|
||||
console.log("FROM Flowchart: ", JSON.parse(msg.message.pipe));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
} else if (msg.type == 4) { //试运行功能
|
||||
if (socket_window == null) {
|
||||
notify_flowchart("试运行功能只能在设计任务阶段,Chrome浏览器打开时使用!", "The trial run function can only be used when designing tasks and opening in Chrome browser!", "error");
|
||||
} else {
|
||||
let node = JSON.parse(msg.message.node);
|
||||
notify_browser("正在试运行操作:" + node.title, "Trying to run the operation: " + node.title, "info");
|
||||
let option = node.option;
|
||||
let parameters = node.parameters;
|
||||
let beforeJS = "";
|
||||
let beforeJSWaitTime = 0;
|
||||
let afterJS = "";
|
||||
let afterJSWaitTime = 0;
|
||||
try {
|
||||
beforeJS = parameters.beforeJS;
|
||||
beforeJSWaitTime = parameters.beforeJSWaitTime;
|
||||
afterJS = parameters.afterJS;
|
||||
afterJSWaitTime = parameters.afterJSWaitTime;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
if (option == 1) {
|
||||
let url = parameters.links.split("\n")[0].trim();
|
||||
if (parameters.useLoop) {
|
||||
let parent_node = JSON.parse(msg.message.parentNode);
|
||||
url = parent_node["parameters"]["textList"].split("\n")[0];
|
||||
}
|
||||
await driver.get(url);
|
||||
} else if (option == 2 || option == 7) { //点击事件
|
||||
let elementInfo = {"iframe": parameters.iframe, "xpath": parameters.xpath, "id": -1};
|
||||
if (parameters.useLoop) {
|
||||
let parent_node = JSON.parse(msg.message.parentNode);
|
||||
let parent_xpath = parent_node.parameters.xpath;
|
||||
elementInfo.xpath = parent_xpath + elementInfo.xpath;
|
||||
}
|
||||
let element = await findElementAcrossAllWindows(elementInfo);
|
||||
if (beforeJS != "") {
|
||||
await driver.executeScript(beforeJS, element);
|
||||
await new Promise(resolve => setTimeout(resolve, beforeJSWaitTime));
|
||||
}
|
||||
if (option == 2) {
|
||||
await click_element(element);
|
||||
} else if (option == 7) {
|
||||
await driver.actions().move({origin: element}).perform();
|
||||
}
|
||||
if (afterJS != "") {
|
||||
await driver.executeScript(afterJS, element);
|
||||
await new Promise(resolve => setTimeout(resolve, afterJSWaitTime));
|
||||
}
|
||||
send_message_to_browser(JSON.stringify({"type": "cancelSelection"}));
|
||||
} else if (option == 4) { //键盘输入事件
|
||||
let elementInfo = {"iframe": parameters.iframe, "xpath": parameters.xpath, "id": -1};
|
||||
let value = node.parameters.value;
|
||||
if (node.parameters.useLoop) {
|
||||
let parent_node = JSON.parse(msg.message.parentNode);
|
||||
value = parent_node["parameters"]["textList"].split("\n")[0];
|
||||
let index = node.parameters.index;
|
||||
if (index > 0) {
|
||||
value = value.split("~")[index - 1];
|
||||
}
|
||||
}
|
||||
let keyInfo = value
|
||||
let enter = false;
|
||||
if (/<enter>/i.test(keyInfo)) {
|
||||
keyInfo = keyInfo.replace(/<enter>/gi, '');
|
||||
enter = true;
|
||||
}
|
||||
let element = await findElementAcrossAllWindows(elementInfo);
|
||||
if (beforeJS != "") {
|
||||
await driver.executeScript(beforeJS, element);
|
||||
await new Promise(resolve => setTimeout(resolve, beforeJSWaitTime));
|
||||
}
|
||||
await element.sendKeys(Key.HOME, Key.chord(Key.SHIFT, Key.END), keyInfo);
|
||||
if (enter) {
|
||||
await element.sendKeys(Key.ENTER);
|
||||
}
|
||||
if (afterJS != "") {
|
||||
await driver.executeScript(afterJS, element);
|
||||
await new Promise(resolve => setTimeout(resolve, afterJSWaitTime));
|
||||
}
|
||||
} else if (option == 5) { //自定义操作的JS代码
|
||||
let code = parameters.code;
|
||||
await driver.executeScript(code);
|
||||
} else if (option == 6) { //切换下拉选项
|
||||
let optionMode = parseInt(parameters.optionMode);
|
||||
let optionValue = parameters.optionValue;
|
||||
if (node.parameters.useLoop) {
|
||||
let parent_node = JSON.parse(msg.message.parentNode);
|
||||
optionValue = parent_node["parameters"]["textList"].split("\n")[0];
|
||||
let index = node.parameters.index;
|
||||
if (index > 0) {
|
||||
optionValue = optionValue.split("~")[index - 1];
|
||||
}
|
||||
}
|
||||
let elementInfo = {"iframe": parameters.iframe, "xpath": parameters.xpath, "id": -1};
|
||||
let element = await findElementAcrossAllWindows(elementInfo);
|
||||
if (beforeJS != "") {
|
||||
await driver.executeScript(beforeJS, element);
|
||||
await new Promise(resolve => setTimeout(resolve, beforeJSWaitTime));
|
||||
}
|
||||
let dropdown = new Select(element);
|
||||
// Interacting with dropdown element based on optionMode
|
||||
switch (optionMode) {
|
||||
case 0: //切换到下一个选项
|
||||
let script = "var options = arguments[0].options;for (var i = 0; i < options.length; i++) {if (options[i].selected) {options[i].selected = false;if (i == options.length - 1) {options[0].selected = true;} else {options[i + 1].selected = true;}break;}}";
|
||||
await driver.executeScript(script, element);
|
||||
break;
|
||||
case 1:
|
||||
await dropdown.selectByIndex(parseInt(optionValue));
|
||||
break;
|
||||
case 2:
|
||||
await dropdown.selectByValue(optionValue);
|
||||
break;
|
||||
case 3:
|
||||
await dropdown.selectByVisibleText(optionValue);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid option mode');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (msg.type == 8) { //展示元素功能
|
||||
|
||||
} else if (msg.type == 5) {
|
||||
let child = require('child_process').execFile;
|
||||
// 参数顺序: 1. task id 2. server address 3. saved_file_name 4. "remote" or "local" 5. user_data_folder
|
||||
@ -330,7 +467,7 @@ async function beginInvoke(msg, ws) {
|
||||
config.absolute_user_data_folder = user_data_folder_path;
|
||||
fs.writeFileSync(path.join(task_server.getDir(), "config.json"), JSON.stringify(config));
|
||||
}
|
||||
if(msg.message.mysql_config_path != "-1"){
|
||||
if (msg.message.mysql_config_path != "-1") {
|
||||
config.mysql_config_path = msg.message.mysql_config_path;
|
||||
}
|
||||
fs.writeFileSync(path.join(task_server.getDir(), "config.json"), JSON.stringify(config));
|
||||
@ -345,21 +482,24 @@ async function beginInvoke(msg, ws) {
|
||||
console.log(data.toString());
|
||||
});
|
||||
}
|
||||
ws.send(JSON.stringify({"config_folder": task_server.getDir() + "/", "easyspider_location": task_server.getEasySpiderLocation()}));
|
||||
ws.send(JSON.stringify({
|
||||
"config_folder": task_server.getDir() + "/",
|
||||
"easyspider_location": task_server.getEasySpiderLocation()
|
||||
}));
|
||||
} else if (msg.type == 6) {
|
||||
try{
|
||||
try {
|
||||
flowchart_window.openDevTools();
|
||||
} catch {
|
||||
console.log("open devtools error");
|
||||
}
|
||||
try{
|
||||
try {
|
||||
invoke_window.openDevTools();
|
||||
} catch {
|
||||
console.log("open devtools error");
|
||||
}
|
||||
} else if (msg.type == 7) {
|
||||
// 获得当前页面Cookies
|
||||
try{
|
||||
try {
|
||||
let cookies = await driver.manage().getCookies();
|
||||
console.log("Cookies: ", cookies);
|
||||
let cookiesText = cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('\n');
|
||||
@ -370,6 +510,34 @@ async function beginInvoke(msg, ws) {
|
||||
}
|
||||
}
|
||||
|
||||
async function click_element(element) {
|
||||
try {
|
||||
await element.click();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
await driver.executeScript("arguments[0].click();", element);
|
||||
}
|
||||
}
|
||||
|
||||
function notify_flowchart(msg_zh, msg_en, level = "info") {
|
||||
socket_flowchart.send(JSON.stringify({"type": "notify", "level": level, "msg_zh": msg_zh, "msg_en": msg_en}));
|
||||
}
|
||||
|
||||
function notify_browser(msg_zh, msg_en, level = "info") {
|
||||
send_message_to_browser(JSON.stringify({"type": "notify", "level": level, "msg_zh": msg_zh, "msg_en": msg_en}));
|
||||
}
|
||||
|
||||
function send_message_to_browser(message) {
|
||||
socket_window.send(message);
|
||||
for (let i in allWindowSockets) {
|
||||
try {
|
||||
allWindowSockets[i].send(message);
|
||||
} catch {
|
||||
console.log("Cannot send to socket with id: ", allWindowScoketNames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const WebSocket = require('ws');
|
||||
const {all} = require("express/lib/application");
|
||||
let wss = new WebSocket.Server({port: websocket_port});
|
||||
@ -381,41 +549,48 @@ wss.on('connection', function (ws) {
|
||||
if (msg.type == 0) {
|
||||
if (msg.message.id == 0) {
|
||||
socket_window = ws;
|
||||
// socket_window.on('close', function (event) {
|
||||
// socket_window = null;
|
||||
// console.log("socket_window closed");
|
||||
// });
|
||||
console.log("set socket_window")
|
||||
} else if (msg.message.id == 1) {
|
||||
socket_start = ws;
|
||||
console.log("set socket_start")
|
||||
} else if (msg.message.id == 2) {
|
||||
socket_flowchart = ws;
|
||||
// socket_flowchart.on('close', function (event) {
|
||||
// socket_flowchart = null;
|
||||
// console.log("socket_flowchart closed");
|
||||
// });
|
||||
console.log("set socket_flowchart");
|
||||
} else { //其他的ID是用来标识不同的浏览器标签页的
|
||||
await new Promise(resolve => setTimeout(resolve, 2300));
|
||||
let handles = await driver.getAllWindowHandles();
|
||||
if(arrayDifference(handles, old_handles).length > 0){
|
||||
if (arrayDifference(handles, old_handles).length > 0) {
|
||||
old_handles = handles;
|
||||
current_handle = handles[handles.length - 1];
|
||||
console.log("New tab opened, change current_handle to: ", current_handle);
|
||||
}
|
||||
handle_pairs[msg.message.id] = current_handle;
|
||||
console.log("Set handle_pair for id: ", msg.message.id, " to ", current_handle, ", title is: ", msg.message.title);
|
||||
socket_flowchart.send(JSON.stringify({"type": "title", "data": {"title":msg.message.title}}));
|
||||
socket_flowchart.send(JSON.stringify({"type": "title", "data": {"title": msg.message.title}}));
|
||||
allWindowSockets.push(ws);
|
||||
allWindowScoketNames.push(msg.message.id);
|
||||
// console.log("handle_pairs: ", handle_pairs);
|
||||
}
|
||||
} else if (msg.type == 10) {
|
||||
let leave_handle = handle_pairs[msg.message.id];
|
||||
if (leave_handle!=null && leave_handle!=undefined && leave_handle!="")
|
||||
{
|
||||
if (leave_handle != null && leave_handle != undefined && leave_handle != "") {
|
||||
await driver.switchTo().window(leave_handle);
|
||||
console.log("Switch to handle: ", leave_handle);
|
||||
current_handle = leave_handle;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await beginInvoke(msg, ws);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
console.log(process.platform);
|
||||
@ -461,7 +636,7 @@ async function runBrowser(lang = "en", user_data_folder = '', mobile = false) {
|
||||
source: stealth,
|
||||
});
|
||||
try {
|
||||
if(mobile){
|
||||
if (mobile) {
|
||||
await driver.get(server_address + "/taskGrid/taskList.html?wsport=" + websocket_port + "&backEndAddressServiceWrapper=" + server_address + "&mobile=1&lang=" + lang);
|
||||
} else {
|
||||
await driver.get(server_address + "/taskGrid/taskList.html?wsport=" + websocket_port + "&backEndAddressServiceWrapper=" + server_address + "&lang=" + lang);
|
||||
@ -493,11 +668,11 @@ function handleOpenBrowser(event, lang = "en", user_data_folder = "", mobile = f
|
||||
if (lang == "en") {
|
||||
url = server_address + `/taskGrid/FlowChart.html?id=${id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address + "&mobile=" + mobile.toString();
|
||||
} else if (lang == "zh") {
|
||||
url = server_address + `/taskGrid/FlowChart_CN.html?id=${id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address+ "&mobile=" + mobile.toString();
|
||||
url = server_address + `/taskGrid/FlowChart_CN.html?id=${id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address + "&mobile=" + mobile.toString();
|
||||
}
|
||||
// and load the index.html of the app.
|
||||
flowchart_window.loadURL(url, { extraHeaders: 'pragma: no-cache\n' });
|
||||
if(process.platform != "darwin"){
|
||||
flowchart_window.loadURL(url, {extraHeaders: 'pragma: no-cache\n'});
|
||||
if (process.platform != "darwin") {
|
||||
flowchart_window.hide();
|
||||
}
|
||||
flowchart_window.on('close', function (event) {
|
||||
@ -516,7 +691,7 @@ function handleOpenInvoke(event, lang = "en") {
|
||||
url = server_address + `/taskGrid/taskList.html?type=1&wsport=${websocket_port}&backEndAddressServiceWrapper=` + server_address + "&lang=zh";
|
||||
}
|
||||
// and load the index.html of the app.
|
||||
invoke_window.loadURL(url, { extraHeaders: 'pragma: no-cache\n' });
|
||||
invoke_window.loadURL(url, {extraHeaders: 'pragma: no-cache\n'});
|
||||
invoke_window.maximize();
|
||||
mainWindow.hide();
|
||||
invoke_window.on('close', function (event) {
|
||||
@ -530,7 +705,7 @@ function handleOpenInvoke(event, lang = "en") {
|
||||
app.whenReady().then(() => {
|
||||
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||
details.requestHeaders['Accept-Language'] = 'zh'
|
||||
callback({ cancel: false, requestHeaders: details.requestHeaders })
|
||||
callback({cancel: false, requestHeaders: details.requestHeaders})
|
||||
})
|
||||
ipcMain.on('start-design', handleOpenBrowser);
|
||||
ipcMain.on('start-invoke', handleOpenInvoke);
|
||||
|
@ -16,13 +16,13 @@
|
||||
|
||||
<body>
|
||||
<div id="tip" class="alert alert-success alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> Hint: Save Successfully!
|
||||
</div>
|
||||
<div id="tipError" class="alert alert-danger alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="error_message">提示:保存名不符合MySQL表名规范,请重试!</span>
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="tip_message">Tip: Save successful!</span>
|
||||
</div>
|
||||
<div id="tipInfo" class="alert alert-info alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="info_message">提示:您加载的任务版本不是最新版,可能出现兼容性问题。</span>
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="info_message">Tip: The task version you loaded is not the latest, which may cause compatibility issues.</span>
|
||||
</div>
|
||||
<div id="tipError" class="alert alert-danger alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="error_message">Tip: The save name does not conform to MySQL table naming conventions, please try again!</span>
|
||||
</div>
|
||||
<div id="navigator">
|
||||
<nav aria-label="breadcrumb" v-if="type==1">
|
||||
@ -559,7 +559,7 @@ If the expression returns a value greater than 0 or evaluates to True, the loop
|
||||
<div v-if='parseInt(loopType) == 0'>
|
||||
<label>Maximum number of loop iterations (0 represents an infinite loop until no more elements are found or no changes in page content are detected):</label>
|
||||
<input onkeydown="inputDelete(event)" required class="form-control" type="number" v-model.number='nowNode["parameters"]["exitCount"]'></input>
|
||||
<label>Exit the loop when the content of the following page element does not change (only works when loop iterations are set to 0):</label>
|
||||
<label>Exit the loop when the content of the following elements on the page does not change (effective when the count is 0. If it is a multi-layer nested iframe, it is recommended to write an XPath for an element that only exists within the iframe page you want to extract, such as /html/body/div[@class='LeftSide_menu']):</label>
|
||||
<input onkeydown="inputDelete(event)" required class="form-control" type="text" v-model='nowNode["parameters"]["exitElement"]'></input>
|
||||
</div>
|
||||
|
||||
|
@ -382,6 +382,24 @@ function elementClick(e) {
|
||||
e.stopPropagation(); //防止冒泡
|
||||
}
|
||||
|
||||
function elementDblClick(e) {
|
||||
try {
|
||||
let nodeType = app._data.nowNode["option"]
|
||||
if (nodeType >= 8) {
|
||||
showInfo(LANG("试运行功能不适用于循环和条件分支操作。", "The trial run function is not applicable to loop and condition branch operations."))
|
||||
} else {
|
||||
if(nodeType == 5 && app._data.nowNode["parameters"]["codeMode"] != 0){
|
||||
showInfo(LANG("试运行自定义操作功能只适用于执行JavaScript操作。", "The trial run custom action function is only applicable to run JavaScript operation."))
|
||||
} else {
|
||||
trailRun(app._data.nowNode);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
showError(LANG("试运行功能只能在设计任务阶段,Chrome浏览器打开时使用!", "The trial run function can only be used when designing tasks and opening in Chrome browser!"));
|
||||
}
|
||||
e.stopPropagation(); //防止冒泡
|
||||
}
|
||||
|
||||
//箭头点击事件
|
||||
function arrowClick(e) {
|
||||
if (option != 0) {
|
||||
@ -495,12 +513,11 @@ function toolBoxKernel(e, para = null) {
|
||||
if (str == "") {
|
||||
title += LANG("元素", "Element");
|
||||
} else {
|
||||
let lang = detectLang(str);
|
||||
if (lang == 1) { //中文
|
||||
if(window.location.href.indexOf("_CN") != -1){
|
||||
if (str.length > l) {
|
||||
str = str.substring(0, l) + "...";
|
||||
}
|
||||
} else { //英文
|
||||
} else {
|
||||
if (str.length > l + 7) {
|
||||
str = str.substring(0, l + 7) + "...";
|
||||
}
|
||||
@ -643,6 +660,8 @@ function bindEvents() {
|
||||
rule.addEventListener('mousedown', elementMousedown);
|
||||
rule.removeEventListener('click', elementClick);
|
||||
rule.addEventListener('click', elementClick);
|
||||
rule.removeEventListener('dblclick', elementDblClick);
|
||||
rule.addEventListener('dblclick', elementDblClick);
|
||||
rule.removeEventListener('dragend', elementDragEnd);
|
||||
rule.addEventListener('dragend', elementDragEnd);
|
||||
}
|
||||
@ -749,7 +768,7 @@ document.getElementById("flowchart_graph").oncontextmenu = function (e) {
|
||||
// 创建一个包含删除选项的右键菜单
|
||||
let contextMenu = document.createElement("div");
|
||||
contextMenu.id = "contextMenu";
|
||||
contextMenu.innerHTML = `<div>${LANG("试运行", "Test Run")}</div>
|
||||
contextMenu.innerHTML = `<div>${LANG("试运行", "Trial Run")}</div>
|
||||
<div>${LANG("复制元素", "Copy Element")}</div>
|
||||
<div>${LANG("剪切元素", "Move Element")}</div>
|
||||
<div>${LANG("删除元素(双击)", "Delete Element (Double Click)")}</div>`;
|
||||
@ -802,7 +821,8 @@ document.getElementById("flowchart_graph").oncontextmenu = function (e) {
|
||||
|
||||
// Add Test Run functionality
|
||||
contextMenu.children[0].addEventListener('click', function () {
|
||||
|
||||
elementDblClick(e);
|
||||
contextMenu.remove(); // Remove the context menu
|
||||
});
|
||||
|
||||
// Add copy functionality
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
<body>
|
||||
<div id="tip" class="alert alert-success alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> 提示:保存成功!
|
||||
</div>
|
||||
<div id="tipError" class="alert alert-danger alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="error_message">提示:保存名不符合MySQL表名规范,请重试!</span>
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="tip_message">提示:保存成功!</span>
|
||||
</div>
|
||||
<div id="tipInfo" class="alert alert-info alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="info_message">提示:您加载的任务版本不是最新版,可能出现兼容性问题。</span>
|
||||
</div>
|
||||
<div id="tipError" class="alert alert-danger alert-dismissible fade show" style="position: fixed; width:100%;display: none;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button> <span id="error_message">提示:保存名不符合MySQL表名规范,请重试!</span>
|
||||
</div>
|
||||
<div id="navigator">
|
||||
<nav aria-label="breadcrumb" v-if="type==1">
|
||||
<ol class="breadcrumb" style="padding-left:23px;padding-bottom: 0;margin-bottom:0;background-color: white">
|
||||
@ -559,7 +559,7 @@ print(emotlib.emoji()) # 使用其中的函数。
|
||||
<div v-if='parseInt(loopType) == 0'>
|
||||
<label>最多执行循环次数(0代表无限循环直到找不到元素或检测不到页面元素内容变化为止):</label>
|
||||
<input onkeydown="inputDelete(event)" required class="form-control" type="number" v-model.number='nowNode["parameters"]["exitCount"]'></input>
|
||||
<label>检测页面以下元素内容不变化时退出循环(次数为0时生效):</label>
|
||||
<label>检测页面以下元素内容不变化时退出循环(次数为0时生效,如果是多层嵌套iframe,建议写一个只有要提取的iframe页面内才有的元素的XPath,如/html/body/div[@class='LeftSide_menu']):</label>
|
||||
<input onkeydown="inputDelete(event)" required class="form-control" type="text" v-model='nowNode["parameters"]["exitElement"]'></input>
|
||||
</div>
|
||||
|
||||
|
@ -33,6 +33,14 @@ ws.onmessage = function(evt) {
|
||||
$("#serviceName").val(evt.data.title);
|
||||
}
|
||||
old_title = evt.data.title;
|
||||
} else if (evt["type"] == "notify") {
|
||||
if (evt["level"] == "success") {
|
||||
showSuccess(LANG(evt["msg_zh"], evt["msg_en"]));
|
||||
} else if(evt["level"] == "info"){
|
||||
showInfo(LANG(evt["msg_zh"], evt["msg_en"]));
|
||||
} else if(evt["level"] == "error"){
|
||||
showError(LANG(evt["msg_zh"], evt["msg_en"]));
|
||||
}
|
||||
} else {
|
||||
handleAddElement(evt); //处理增加元素操作
|
||||
}
|
||||
@ -130,11 +138,21 @@ function notifyParameterNum(num) {
|
||||
let message = {
|
||||
type: 3, //消息类型,3代表元素增加事件
|
||||
from: 1, //0代表从浏览器到流程图,1代表从流程图到浏览器
|
||||
message: { "pipe": JSON.stringify({ "type": 0, "value": parameterNum }) } // {}全选{BS}退格
|
||||
message: { "pipe": JSON.stringify({ "type": "update_parameter_num", "value": parameterNum }) } // {}全选{BS}退格
|
||||
};
|
||||
ws.send(JSON.stringify(message));
|
||||
}
|
||||
|
||||
function trailRun(node){
|
||||
let message = {
|
||||
type: 4, //消息类型,4代表试运行事件
|
||||
from: 1, //0代表从浏览器到流程图,1代表从流程图到浏览器
|
||||
message: { "node": JSON.stringify(node), "parentNode": JSON.stringify(nodeList[actionSequence[node["parentId"]]])}
|
||||
};
|
||||
ws.send(JSON.stringify(message));
|
||||
console.log(message);
|
||||
}
|
||||
|
||||
|
||||
// 流程图元素点击后的处理逻辑,注意在FlowChart_CN.js中watch的那些数据的加载都需要在这里执行!!!
|
||||
function handleElement() {
|
||||
@ -325,6 +343,20 @@ function modifyParameters(t, para) {
|
||||
}
|
||||
}
|
||||
|
||||
function showSuccess(msg, time=4000) {
|
||||
$("#tip").text(msg);
|
||||
$("#tip").slideDown(); //提示框
|
||||
let fadeout = setTimeout(function() {
|
||||
$("#tip").slideUp();
|
||||
}, time);
|
||||
}
|
||||
function showInfo(msg, time=4000) {
|
||||
$("#info_message").text(msg);
|
||||
$("#tipInfo").slideDown(); //提示框
|
||||
let fadeout = setTimeout(function() {
|
||||
$("#tipInfo").slideUp();
|
||||
}, time);
|
||||
}
|
||||
function showError(msg, time=4000) {
|
||||
$("#error_message").text(msg);
|
||||
$("#tipError").slideDown(); //提示框
|
||||
@ -333,13 +365,6 @@ function showError(msg, time=4000) {
|
||||
}, time);
|
||||
}
|
||||
|
||||
function showInfo(msg, time=4000) {
|
||||
$("#info_message").text(msg);
|
||||
$("#tipInfo").slideDown(); //提示框
|
||||
let fadeout = setTimeout(function() {
|
||||
$("#tipInfo").slideUp();
|
||||
}, time);
|
||||
}
|
||||
|
||||
//点击确定按钮时的处理
|
||||
$("#confirm").mousedown(updateUI);
|
||||
@ -525,10 +550,7 @@ function saveService(type) {
|
||||
function(result) { $("#serviceId").val(parseInt(result)) });
|
||||
// alert("保存成功!");
|
||||
$('#myModal').modal('hide');
|
||||
$("#tip").slideDown(); //提示框
|
||||
let fadeout = setTimeout(function() {
|
||||
$("#tip").slideUp();
|
||||
}, 2000);
|
||||
showSuccess(LANG("保存成功!","Save successfully!"));
|
||||
// }
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
ElectronJS/tasks/245.json
Normal file
1
ElectronJS/tasks/245.json
Normal file
File diff suppressed because one or more lines are too long
1
ElectronJS/tasks/246.json
Normal file
1
ElectronJS/tasks/246.json
Normal file
File diff suppressed because one or more lines are too long
1
ElectronJS/tasks/247.json
Normal file
1
ElectronJS/tasks/247.json
Normal file
File diff suppressed because one or more lines are too long
807
ElectronJS/tasks/248.json
Normal file
807
ElectronJS/tasks/248.json
Normal file
@ -0,0 +1,807 @@
|
||||
{
|
||||
"id": 248,
|
||||
"name": "中国地震台网——历史查询",
|
||||
"url": "https://www.ceic.ac.cn/history",
|
||||
"links": "https://www.ceic.ac.cn/history",
|
||||
"create_time": "",
|
||||
"update_time": "12/10/2023, 9:14:40 AM",
|
||||
"version": "0.6.0",
|
||||
"saveThreshold": 10,
|
||||
"quitWaitTime": 60,
|
||||
"environment": 0,
|
||||
"maximizeWindow": 0,
|
||||
"maxViewLength": 15,
|
||||
"recordLog": 1,
|
||||
"outputFormat": "xlsx",
|
||||
"saveName": "current_time",
|
||||
"inputExcel": "",
|
||||
"startFromExit": 0,
|
||||
"pauseKey": "p",
|
||||
"containJudge": false,
|
||||
"desc": "https://www.ceic.ac.cn/history",
|
||||
"inputParameters": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "urlList_0",
|
||||
"nodeId": 1,
|
||||
"nodeName": "打开网页",
|
||||
"value": "https://www.ceic.ac.cn/history",
|
||||
"desc": "要采集的网址列表,多行以\\n分开",
|
||||
"type": "text",
|
||||
"exampleValue": "https://www.ceic.ac.cn/history"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "inputText_1",
|
||||
"nodeName": "输入文字",
|
||||
"nodeId": 2,
|
||||
"desc": "要输入的文本,如京东搜索框输入:电脑",
|
||||
"type": "text",
|
||||
"exampleValue": "12",
|
||||
"value": "12"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "loopTimes_循环点击单个元素_2",
|
||||
"nodeId": 4,
|
||||
"nodeName": "循环点击单个元素",
|
||||
"desc": "循环循环点击单个元素执行的次数(0代表无限循环)",
|
||||
"type": "int",
|
||||
"exampleValue": 0,
|
||||
"value": 0
|
||||
}
|
||||
],
|
||||
"outputParameters": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "参数1_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "3.3"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "参数2_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "2023-11-1817:48:35"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "参数3_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "36.55"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "参数4_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "106.31"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "参数5_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "15"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "参数6_链接文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "宁夏中卫市海原县"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "参数7_链接地址",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "https://news.ceic.ac.cn/CD20231118174835.html"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "参数8_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "震级(M)"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "参数9_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "发震时刻(UTC+8)"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "参数10_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "纬度(°)"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "参数11_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "经度(°)"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "参数12_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "深度(千米)"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "参数13_文本",
|
||||
"desc": "",
|
||||
"type": "text",
|
||||
"recordASField": 1,
|
||||
"exampleValue": "参考位置"
|
||||
}
|
||||
],
|
||||
"graph": [
|
||||
{
|
||||
"index": 0,
|
||||
"id": 0,
|
||||
"parentId": 0,
|
||||
"type": -1,
|
||||
"option": 0,
|
||||
"title": "root",
|
||||
"sequence": [1, 2, 3, 4],
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0
|
||||
},
|
||||
"isInLoop": false
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"index": 1,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 1,
|
||||
"title": "打开网页",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 0,
|
||||
"parameters": {
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"url": "https://www.ceic.ac.cn/history",
|
||||
"links": "https://www.ceic.ac.cn/history",
|
||||
"maxWaitTime": 10,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"cookies": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"index": 2,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 4,
|
||||
"title": "输入文字",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 1,
|
||||
"parameters": {
|
||||
"history": 7,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//*[@id=\"weidu1\"]",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"value": "12",
|
||||
"index": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[1]/div[3]/div[1]/div[1]/div[1]/form[1]/div[2]/input[1]",
|
||||
"//input[contains(., '')]",
|
||||
"id(\"weidu1\")",
|
||||
"//INPUT[@class='span1']",
|
||||
"//INPUT[@name='weidu1']",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div[last()-1]/form/div[last()-3]/input[last()-1]"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"index": 3,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 2,
|
||||
"title": "点击查询",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 2,
|
||||
"parameters": {
|
||||
"history": 7,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//*[@id=\"search\"]",
|
||||
"iframe": false,
|
||||
"wait": 2,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"clickWay": 0,
|
||||
"maxWaitTime": 10,
|
||||
"paras": [],
|
||||
"alertHandleType": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[1]/div[3]/div[1]/div[1]/div[1]/form[1]/div[5]/a[1]",
|
||||
"//a[contains(., '查询')]",
|
||||
"id(\"search\")",
|
||||
"//A[@class='check']",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div[last()-1]/form/div/a"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"index": 4,
|
||||
"parentId": 0,
|
||||
"type": 1,
|
||||
"option": 8,
|
||||
"title": "循环点击单个元素",
|
||||
"sequence": [6, 5],
|
||||
"isInLoop": false,
|
||||
"position": 3,
|
||||
"parameters": {
|
||||
"history": 7,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//a[contains(., '»')]",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"loopType": 0,
|
||||
"pathList": "",
|
||||
"textList": "",
|
||||
"code": "",
|
||||
"waitTime": 0,
|
||||
"exitCount": 0,
|
||||
"exitElement": "//body",
|
||||
"historyWait": 2,
|
||||
"breakMode": 0,
|
||||
"breakCode": "",
|
||||
"breakCodeWaitTime": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[1]/div[3]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/ul[1]/li[10]/a[1]",
|
||||
"//a[contains(., '»')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div/div/div/ul/li[last()-1]/a"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"index": 5,
|
||||
"parentId": 4,
|
||||
"type": 0,
|
||||
"option": 2,
|
||||
"title": "点击»",
|
||||
"sequence": [],
|
||||
"isInLoop": true,
|
||||
"position": 1,
|
||||
"parameters": {
|
||||
"history": 7,
|
||||
"tabIndex": -1,
|
||||
"useLoop": true,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 2,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"clickWay": 0,
|
||||
"maxWaitTime": 10,
|
||||
"paras": [],
|
||||
"alertHandleType": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[1]/div[3]/div[1]/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/ul[1]/li[10]/a[1]",
|
||||
"//a[contains(., '»')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div/div/div/ul/li[last()-1]/a"
|
||||
],
|
||||
"loopType": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"index": 6,
|
||||
"parentId": 4,
|
||||
"type": 1,
|
||||
"option": 8,
|
||||
"title": "循环采集数据",
|
||||
"sequence": [7],
|
||||
"isInLoop": true,
|
||||
"position": 0,
|
||||
"parameters": {
|
||||
"history": 7,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "/html/body/div[1]/div[3]/div[1]/div[1]/div[2]/div[1]/div[1]/table[1]/tbody[1]/tr",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"loopType": 1,
|
||||
"pathList": "",
|
||||
"textList": "",
|
||||
"code": "",
|
||||
"waitTime": 0,
|
||||
"exitCount": 0,
|
||||
"exitElement": "//body",
|
||||
"historyWait": 2,
|
||||
"breakMode": 0,
|
||||
"breakCode": "",
|
||||
"breakCodeWaitTime": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[1]/div[3]/div[1]/div[1]/div[2]/div[1]/div[1]/table[1]/tbody[1]/tr[1]",
|
||||
"//tr[contains(., '震级(M)发震时刻(')]",
|
||||
"//TR[@class='speed-tr-h1']",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr[last()-20]"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"index": 7,
|
||||
"parentId": 5,
|
||||
"type": 0,
|
||||
"option": 3,
|
||||
"title": "提取数据",
|
||||
"sequence": [],
|
||||
"isInLoop": true,
|
||||
"position": 0,
|
||||
"parameters": {
|
||||
"history": 7,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"clear": 0,
|
||||
"newLine": 1,
|
||||
"paras": [
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数1_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/td[1]",
|
||||
"allXPaths": [
|
||||
"/td[1]",
|
||||
"//td[contains(., '3.3')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr/td[last()-5]"
|
||||
],
|
||||
"exampleValues": [{ "num": 0, "value": "3.3" }],
|
||||
"unique_index": "/td[1]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数2_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/td[2]",
|
||||
"allXPaths": [
|
||||
"/td[2]",
|
||||
"//td[contains(., '2023-11-18')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr/td[last()-4]"
|
||||
],
|
||||
"exampleValues": [{ "num": 0, "value": "2023-11-1817:48:35" }],
|
||||
"unique_index": "/td[2]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数3_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/td[3]",
|
||||
"allXPaths": [
|
||||
"/td[3]",
|
||||
"//td[contains(., '36.55')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr/td[last()-3]"
|
||||
],
|
||||
"exampleValues": [{ "num": 0, "value": "36.55" }],
|
||||
"unique_index": "/td[3]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数4_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/td[4]",
|
||||
"allXPaths": [
|
||||
"/td[4]",
|
||||
"//td[contains(., '106.31')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr/td[last()-2]"
|
||||
],
|
||||
"exampleValues": [{ "num": 0, "value": "106.31" }],
|
||||
"unique_index": "/td[4]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数5_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/td[5]",
|
||||
"allXPaths": [
|
||||
"/td[5]",
|
||||
"//td[contains(., '15')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr/td[last()-1]"
|
||||
],
|
||||
"exampleValues": [{ "num": 0, "value": "15" }],
|
||||
"unique_index": "/td[5]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 1,
|
||||
"contentType": 0,
|
||||
"relative": true,
|
||||
"name": "参数6_链接文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/td[6]/a[1]",
|
||||
"allXPaths": [
|
||||
"/td[6]/a[1]",
|
||||
"//a[contains(., '宁夏中卫市海原县')]",
|
||||
"id(\"cid\")",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr/td/a"
|
||||
],
|
||||
"exampleValues": [{ "num": 0, "value": "宁夏中卫市海原县" }],
|
||||
"unique_index": "/td[6]/a[1]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 2,
|
||||
"contentType": 0,
|
||||
"relative": true,
|
||||
"name": "参数7_链接地址",
|
||||
"desc": "",
|
||||
"relativeXPath": "/td[6]/a[1]",
|
||||
"allXPaths": [
|
||||
"/td[6]/a[1]",
|
||||
"//a[contains(., '宁夏中卫市海原县')]",
|
||||
"id(\"cid\")",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr/td/a"
|
||||
],
|
||||
"exampleValues": [
|
||||
{
|
||||
"num": 0,
|
||||
"value": "https://news.ceic.ac.cn/CD20231118174835.html"
|
||||
}
|
||||
],
|
||||
"unique_index": "/td[6]/a[1]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数8_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/th[1]",
|
||||
"allXPaths": [
|
||||
"/th[1]",
|
||||
"//th[contains(., '震级(M)')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr[last()-20]/th[last()-5]"
|
||||
],
|
||||
"exampleValues": [{ "num": 1, "value": "震级(M)" }],
|
||||
"unique_index": "/th[1]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数9_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/th[2]",
|
||||
"allXPaths": [
|
||||
"/th[2]",
|
||||
"//th[contains(., '发震时刻(UTC+8')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr[last()-20]/th[last()-4]"
|
||||
],
|
||||
"exampleValues": [{ "num": 1, "value": "发震时刻(UTC+8)" }],
|
||||
"unique_index": "/th[2]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数10_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/th[3]",
|
||||
"allXPaths": [
|
||||
"/th[3]",
|
||||
"//th[contains(., '纬度(°)')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr[last()-20]/th[last()-3]"
|
||||
],
|
||||
"exampleValues": [{ "num": 1, "value": "纬度(°)" }],
|
||||
"unique_index": "/th[3]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数11_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/th[4]",
|
||||
"allXPaths": [
|
||||
"/th[4]",
|
||||
"//th[contains(., '经度(°)')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr[last()-20]/th[last()-2]"
|
||||
],
|
||||
"exampleValues": [{ "num": 1, "value": "经度(°)" }],
|
||||
"unique_index": "/th[4]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数12_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/th[5]",
|
||||
"allXPaths": [
|
||||
"/th[5]",
|
||||
"//th[contains(., '深度(千米)')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr[last()-20]/th[last()-1]"
|
||||
],
|
||||
"exampleValues": [{ "num": 1, "value": "深度(千米)" }],
|
||||
"unique_index": "/th[5]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
},
|
||||
{
|
||||
"nodeType": 0,
|
||||
"contentType": 1,
|
||||
"relative": true,
|
||||
"name": "参数13_文本",
|
||||
"desc": "",
|
||||
"relativeXPath": "/th[6]",
|
||||
"allXPaths": [
|
||||
"/th[6]",
|
||||
"//th[contains(., '参考位置')]",
|
||||
"/html/body/div[last()-3]/div[last()-1]/div/div/div/div/div[last()-1]/table/tbody/tr[last()-20]/th"
|
||||
],
|
||||
"exampleValues": [{ "num": 1, "value": "参考位置" }],
|
||||
"unique_index": "/th[6]",
|
||||
"iframe": false,
|
||||
"default": "",
|
||||
"paraType": "text",
|
||||
"recordASField": 1,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"JS": "",
|
||||
"JSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"downloadPic": 0
|
||||
}
|
||||
],
|
||||
"loopType": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
223
ElectronJS/tasks/249.json
Normal file
223
ElectronJS/tasks/249.json
Normal file
@ -0,0 +1,223 @@
|
||||
{
|
||||
"id": 249,
|
||||
"name": "京东全球版-专业的综合网上购物商城",
|
||||
"url": "https://www.jd.com",
|
||||
"links": "https://google.com",
|
||||
"create_time": "",
|
||||
"update_time": "12/10/2023, 2:19:08 PM",
|
||||
"version": "0.6.0",
|
||||
"saveThreshold": 10,
|
||||
"quitWaitTime": 60,
|
||||
"environment": 0,
|
||||
"maximizeWindow": 0,
|
||||
"maxViewLength": 15,
|
||||
"recordLog": 1,
|
||||
"outputFormat": "xlsx",
|
||||
"saveName": "current_time",
|
||||
"inputExcel": "",
|
||||
"startFromExit": 0,
|
||||
"pauseKey": "p",
|
||||
"containJudge": false,
|
||||
"desc": "https://www.jd.com",
|
||||
"inputParameters": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "urlList_0",
|
||||
"nodeId": 1,
|
||||
"nodeName": "打开网页1",
|
||||
"value": "https://www.jd.com",
|
||||
"desc": "要采集的网址列表,多行以\\n分开",
|
||||
"type": "text",
|
||||
"exampleValue": "https://www.jd.com"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "loopText_1",
|
||||
"nodeId": 3,
|
||||
"nodeName": "循环",
|
||||
"desc": "要输入的文本/网址,多行以\\n分开",
|
||||
"type": "text",
|
||||
"exampleValue": "https://baidu.com\nhttps://baidu1.com",
|
||||
"value": "https://baidu.com\nhttps://baidu1.com"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "urlList_2",
|
||||
"nodeId": 4,
|
||||
"nodeName": "打开网页2",
|
||||
"value": "https://google.com",
|
||||
"desc": "要采集的网址列表,多行以\\n分开",
|
||||
"type": "text",
|
||||
"exampleValue": "https://google.com"
|
||||
}
|
||||
],
|
||||
"outputParameters": [],
|
||||
"graph": [
|
||||
{
|
||||
"index": 0,
|
||||
"id": 0,
|
||||
"parentId": 0,
|
||||
"type": -1,
|
||||
"option": 0,
|
||||
"title": "root",
|
||||
"sequence": [1, 4, 3],
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0
|
||||
},
|
||||
"isInLoop": false
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"index": 1,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 1,
|
||||
"title": "打开网页1",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 0,
|
||||
"parameters": {
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"url": "https://www.jd.com",
|
||||
"links": "https://www.jd.com",
|
||||
"maxWaitTime": 10,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"cookies": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"index": 2,
|
||||
"parentId": 3,
|
||||
"type": 0,
|
||||
"option": 1,
|
||||
"title": "打开网页3",
|
||||
"sequence": [],
|
||||
"isInLoop": true,
|
||||
"position": 0,
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": true,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"url": "about:blank",
|
||||
"links": "about:blank",
|
||||
"maxWaitTime": 10,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"cookies": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"index": 3,
|
||||
"parentId": 0,
|
||||
"type": 1,
|
||||
"option": 8,
|
||||
"title": "循环",
|
||||
"sequence": [2],
|
||||
"isInLoop": false,
|
||||
"position": 2,
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"loopType": 4,
|
||||
"pathList": "",
|
||||
"textList": "https://baidu.com\nhttps://baidu1.com",
|
||||
"code": "",
|
||||
"waitTime": 0,
|
||||
"exitCount": 0,
|
||||
"exitElement": "//body",
|
||||
"historyWait": 2,
|
||||
"breakMode": 0,
|
||||
"breakCode": "",
|
||||
"breakCodeWaitTime": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"index": 4,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 1,
|
||||
"title": "打开网页2",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 1,
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"url": "about:blank",
|
||||
"links": "https://google.com",
|
||||
"maxWaitTime": 10,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"cookies": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
147
ElectronJS/tasks/250.json
Normal file
147
ElectronJS/tasks/250.json
Normal file
@ -0,0 +1,147 @@
|
||||
{
|
||||
"id": 250,
|
||||
"name": "京东全球版-专业的综合网上购物商城",
|
||||
"url": "https://www.jd.com",
|
||||
"links": "https://www.jd.com",
|
||||
"create_time": "",
|
||||
"update_time": "12/10/2023, 2:24:56 PM",
|
||||
"version": "0.6.0",
|
||||
"saveThreshold": 10,
|
||||
"quitWaitTime": 60,
|
||||
"environment": 0,
|
||||
"maximizeWindow": 0,
|
||||
"maxViewLength": 15,
|
||||
"recordLog": 1,
|
||||
"outputFormat": "xlsx",
|
||||
"saveName": "current_time",
|
||||
"inputExcel": "",
|
||||
"startFromExit": 0,
|
||||
"pauseKey": "p",
|
||||
"containJudge": false,
|
||||
"desc": "https://www.jd.com",
|
||||
"inputParameters": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "urlList_0",
|
||||
"nodeId": 1,
|
||||
"nodeName": "打开网页",
|
||||
"value": "https://www.jd.com",
|
||||
"desc": "要采集的网址列表,多行以\\n分开",
|
||||
"type": "text",
|
||||
"exampleValue": "https://www.jd.com"
|
||||
}
|
||||
],
|
||||
"outputParameters": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "执行JavaScript1",
|
||||
"desc": "自定义操作返回的数据",
|
||||
"type": "text",
|
||||
"recordASField": 0,
|
||||
"exampleValue": ""
|
||||
}
|
||||
],
|
||||
"graph": [
|
||||
{
|
||||
"index": 0,
|
||||
"id": 0,
|
||||
"parentId": 0,
|
||||
"type": -1,
|
||||
"option": 0,
|
||||
"title": "root",
|
||||
"sequence": [1, 2],
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0
|
||||
},
|
||||
"isInLoop": false
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"index": 1,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 1,
|
||||
"title": "打开网页",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 0,
|
||||
"parameters": {
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"url": "https://www.jd.com",
|
||||
"links": "https://www.jd.com",
|
||||
"maxWaitTime": 10,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"cookies": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"index": 2,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 5,
|
||||
"title": "执行JavaScript1",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 1,
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"clear": 0,
|
||||
"newLine": 1,
|
||||
"codeMode": 0,
|
||||
"code": "document.body.style.color = \"blue\"",
|
||||
"waitTime": 0,
|
||||
"recordASField": 0,
|
||||
"paraType": "text",
|
||||
"emailConfig": {
|
||||
"host": "",
|
||||
"port": 465,
|
||||
"username": "",
|
||||
"password": "",
|
||||
"from": "",
|
||||
"to": "",
|
||||
"subject": "",
|
||||
"content": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
274
ElectronJS/tasks/251.json
Normal file
274
ElectronJS/tasks/251.json
Normal file
@ -0,0 +1,274 @@
|
||||
{
|
||||
"id": 251,
|
||||
"name": "Select · Bootstrap v5.3",
|
||||
"url": "https://getbootstrap.com/docs/5.3/forms/select/",
|
||||
"links": "https://getbootstrap.com/docs/5.3/forms/select/",
|
||||
"create_time": "12/10/2023, 2:29:23 PM",
|
||||
"update_time": "12/10/2023, 2:29:23 PM",
|
||||
"version": "0.6.0",
|
||||
"saveThreshold": 10,
|
||||
"quitWaitTime": 60,
|
||||
"environment": 0,
|
||||
"maximizeWindow": 0,
|
||||
"maxViewLength": 15,
|
||||
"recordLog": 1,
|
||||
"outputFormat": "xlsx",
|
||||
"saveName": "current_time",
|
||||
"inputExcel": "",
|
||||
"startFromExit": 0,
|
||||
"pauseKey": "p",
|
||||
"containJudge": false,
|
||||
"desc": "https://getbootstrap.com/docs/5.3/forms/select/",
|
||||
"inputParameters": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "urlList_0",
|
||||
"nodeId": 1,
|
||||
"nodeName": "打开网页",
|
||||
"value": "https://getbootstrap.com/docs/5.3/forms/select/",
|
||||
"desc": "要采集的网址列表,多行以\\n分开",
|
||||
"type": "text",
|
||||
"exampleValue": "https://getbootstrap.com/docs/5.3/forms/select/"
|
||||
}
|
||||
],
|
||||
"outputParameters": [],
|
||||
"graph": [
|
||||
{
|
||||
"index": 0,
|
||||
"id": 0,
|
||||
"parentId": 0,
|
||||
"type": -1,
|
||||
"option": 0,
|
||||
"title": "root",
|
||||
"sequence": [1, 2, 3, 5, 6],
|
||||
"parameters": {
|
||||
"history": 1,
|
||||
"tabIndex": 0,
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0
|
||||
},
|
||||
"isInLoop": false
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"index": 1,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 1,
|
||||
"title": "打开网页",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 0,
|
||||
"parameters": {
|
||||
"useLoop": false,
|
||||
"xpath": "",
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"url": "https://getbootstrap.com/docs/5.3/forms/select/",
|
||||
"links": "https://getbootstrap.com/docs/5.3/forms/select/",
|
||||
"maxWaitTime": 10,
|
||||
"scrollType": 0,
|
||||
"scrollCount": 1,
|
||||
"scrollWaitTime": 1,
|
||||
"cookies": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"index": 2,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 6,
|
||||
"title": "切换下拉选项",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 1,
|
||||
"parameters": {
|
||||
"history": 4,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//*[contains(@class, \"bd-content\")]/div[1]/div[1]/select[1]",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"optionMode": 0,
|
||||
"optionValue": "One",
|
||||
"index": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[2]/main[1]/div[3]/div[1]/div[1]/select[1]",
|
||||
"//select[contains(., 'Open th')]",
|
||||
"//SELECT[@class='form-select']",
|
||||
"/html/body/div[last()-4]/main/div/div[last()-5]/div[last()-2]/select"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"index": 3,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 6,
|
||||
"title": "切换下拉选项",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 2,
|
||||
"parameters": {
|
||||
"history": 4,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//*[contains(@class, \"bd-content\")]/div[1]/div[1]/select[1]",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"optionMode": "1",
|
||||
"optionValue": "2",
|
||||
"index": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[2]/main[1]/div[3]/div[1]/div[1]/select[1]",
|
||||
"//select[contains(., 'Open th')]",
|
||||
"//SELECT[@class='form-select']",
|
||||
"/html/body/div[last()-4]/main/div/div[last()-5]/div[last()-2]/select"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": -1,
|
||||
"index": 4,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 6,
|
||||
"title": "切换下拉选项",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 3,
|
||||
"parameters": {
|
||||
"history": 4,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//*[contains(@class, \"bd-content\")]/div[1]/div[1]/select[1]",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"optionMode": "2",
|
||||
"optionValue": "1",
|
||||
"index": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[2]/main[1]/div[3]/div[1]/div[1]/select[1]",
|
||||
"//select[contains(., 'Open th')]",
|
||||
"//SELECT[@class='form-select']",
|
||||
"/html/body/div[last()-4]/main/div/div[last()-5]/div[last()-2]/select"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"index": 5,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 6,
|
||||
"title": "切换下拉选项",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 3,
|
||||
"parameters": {
|
||||
"history": 4,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//*[contains(@class, \"bd-content\")]/div[1]/div[1]/select[1]",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"optionMode": "2",
|
||||
"optionValue": "1",
|
||||
"index": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[2]/main[1]/div[3]/div[1]/div[1]/select[1]",
|
||||
"//select[contains(., 'Open th')]",
|
||||
"//SELECT[@class='form-select']",
|
||||
"/html/body/div[last()-4]/main/div/div[last()-5]/div[last()-2]/select"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"index": 6,
|
||||
"parentId": 0,
|
||||
"type": 0,
|
||||
"option": 6,
|
||||
"title": "切换下拉选项",
|
||||
"sequence": [],
|
||||
"isInLoop": false,
|
||||
"position": 4,
|
||||
"parameters": {
|
||||
"history": 4,
|
||||
"tabIndex": -1,
|
||||
"useLoop": false,
|
||||
"xpath": "//*[contains(@class, \"bd-content\")]/div[1]/div[1]/select[1]",
|
||||
"iframe": false,
|
||||
"wait": 0,
|
||||
"waitType": 0,
|
||||
"beforeJS": "",
|
||||
"beforeJSWaitTime": 0,
|
||||
"afterJS": "",
|
||||
"afterJSWaitTime": 0,
|
||||
"waitElement": "",
|
||||
"waitElementTime": 10,
|
||||
"waitElementIframeIndex": 0,
|
||||
"optionMode": "3",
|
||||
"optionValue": "Three",
|
||||
"index": 0,
|
||||
"allXPaths": [
|
||||
"/html/body/div[2]/main[1]/div[3]/div[1]/div[1]/select[1]",
|
||||
"//select[contains(., 'Open th')]",
|
||||
"//SELECT[@class='form-select']",
|
||||
"/html/body/div[last()-4]/main/div/div[last()-5]/div[last()-2]/select"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
2
ExecuteStage/.vscode/launch.json
vendored
2
ExecuteStage/.vscode/launch.json
vendored
@ -12,7 +12,7 @@
|
||||
"justMyCode": false,
|
||||
// "args": ["--ids", "[7]", "--read_type", "remote", "--headless", "0"]
|
||||
// "args": ["--ids", "[9]", "--read_type", "remote", "--headless", "0", "--saved_file_name", "YOUTUBE"]
|
||||
"args": ["--ids", "[95]", "--headless", "0", "--user_data", "0", "--keyboard", "0"]
|
||||
"args": ["--ids", "[10]", "--headless", "0", "--user_data", "0", "--keyboard", "0"]
|
||||
// "args": "--ids '[97]' --user_data 1 --server_address http://localhost:8074 --config_folder '/Users/naibo/Documents/EasySpider/ElectronJS/' --headless 0 --read_type remote --config_file_name config.json --saved_file_name"
|
||||
}
|
||||
]
|
||||
|
@ -1507,13 +1507,25 @@ class BrowserThread(Thread):
|
||||
click_way = 0
|
||||
try:
|
||||
if click_way == 0: # 用selenium的点击方法
|
||||
actions = ActionChains(self.browser) # 实例化一个action对象
|
||||
actions.click(element).perform()
|
||||
try:
|
||||
actions = ActionChains(self.browser) # 实例化一个action对象
|
||||
actions.click(element).perform()
|
||||
except Exception as e:
|
||||
self.browser.execute_script("arguments[0].scrollIntoView();", element)
|
||||
try:
|
||||
actions = ActionChains(self.browser) # 实例化一个action对象
|
||||
actions.click(element).perform()
|
||||
except Exception as e:
|
||||
self.print_and_log(f"Selenium点击元素{path}失败,将尝试使用JavaScript点击")
|
||||
self.print_and_log(f"Failed to click element {path} with Selenium, will try to click with JavaScript")
|
||||
script = 'var result = document.evaluate(`' + path + \
|
||||
'`, document, null, XPathResult.ANY_TYPE, null);for(let i=0;i<arguments[0];i++){result.iterateNext();} result.iterateNext().click();'
|
||||
self.browser.execute_script(script, str(index)) # 用js的点击方法
|
||||
elif click_way == 1: # 用js的点击方法
|
||||
script = 'var result = document.evaluate(`' + path + \
|
||||
'`, document, null, XPathResult.ANY_TYPE, null);for(let i=0;i<arguments[0];i++){result.iterateNext();} result.iterateNext().click();'
|
||||
self.browser.execute_script(script, str(index)) # 用js的点击方法
|
||||
# self.recordLog("点击元素|Click element: " + path)
|
||||
self.recordLog("点击元素|Click element: " + path)
|
||||
except TimeoutException:
|
||||
self.print_and_log(
|
||||
'Time out after set seconds when loading clicked page')
|
||||
|
@ -1 +1 @@
|
||||
{"language":"en"}
|
||||
{"language":"zh"}
|
BIN
Extension/manifest_v3/src/content-scripts/icon-128.png
Normal file
BIN
Extension/manifest_v3/src/content-scripts/icon-128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@ -63,6 +63,23 @@ document.addEventListener("mousemove", function() {
|
||||
if (x >= divx1 && x <= divx2 && y >= divy1 && y <= divy2) {
|
||||
tooltips = true;
|
||||
return;
|
||||
}
|
||||
//如果鼠标在ID为notification_of_easyspider内则点击和选中失效
|
||||
try {
|
||||
let notification_of_easyspider = document.getElementsByClassName("notification_of_easyspider")[0];
|
||||
let x = event.clientX;
|
||||
let y = event.clientY;
|
||||
let divx1 = notification_of_easyspider.offsetLeft;
|
||||
let divy1 = notification_of_easyspider.offsetTop;
|
||||
let divx2 = notification_of_easyspider.offsetLeft + notification_of_easyspider.offsetWidth;
|
||||
let divy2 = notification_of_easyspider.offsetTop + notification_of_easyspider.offsetHeight;
|
||||
if (y >= divy1 - 100 && y <= divy2 + 100) {
|
||||
tooltips = true;
|
||||
// console.log("notification_of_easyspider");
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
global.oe = document.elementFromPoint(event.x, event.y);
|
||||
if (global.oe == global.tdiv) {
|
||||
|
@ -1,22 +1,9 @@
|
||||
//实现与后台和流程图部分的交互
|
||||
|
||||
import {getElementXPaths, global, readXPath, isInIframe} from "./global.js";
|
||||
|
||||
// var startMsg = { "type": 0, msg: ""};
|
||||
//
|
||||
// chrome.runtime.sendMessage(startMsg, function(response) {
|
||||
// console.log(response.msg);
|
||||
// }); //每次打开新页面的时候需要告诉后台
|
||||
// chrome.runtime.onMessage.addListener(
|
||||
// function(request, sender, sendResponse) {
|
||||
// if (request["type"] == 1){
|
||||
// sendResponse("回答处理结果");
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
import {getElementXPaths, global, readXPath, isInIframe, clearEl} from "./global.js";
|
||||
|
||||
global.ws = new WebSocket("ws://localhost:8084");
|
||||
global.ws.onopen = function() {
|
||||
global.ws.onopen = function () {
|
||||
// Web Socket 已连接上,使用 send() 方法发送数据
|
||||
console.log("已连接");
|
||||
let message = {
|
||||
@ -28,13 +15,26 @@ global.ws.onopen = function() {
|
||||
};
|
||||
this.send(JSON.stringify(message));
|
||||
};
|
||||
global.ws.onmessage = function(evt) {
|
||||
global.ws.onmessage = function (evt) {
|
||||
evt = JSON.parse(evt.data);
|
||||
if (evt["type"] == "0") { //0代表更新参数添加索引值
|
||||
chrome.storage.local.set({ "parameterNum": parseInt(evt["value"]) }); //修改值
|
||||
if (evt["type"] == "update_parameter_num") { //0代表更新参数添加索引值
|
||||
chrome.storage.local.set({"parameterNum": parseInt(evt["value"])}); //修改值
|
||||
console.log("更新参数添加索引值为:" + evt["value"]);
|
||||
} else if (evt["type"] == "notify") { //1代表更新参数
|
||||
createNotification(LANG(evt["msg_zh"], evt["msg_en"]), evt["level"]);
|
||||
} else if (evt["type"] == "cancelSelection") { //试运行点击元素后取消选中元素
|
||||
clearEl();
|
||||
}
|
||||
};
|
||||
|
||||
function LANG(zh, en) {
|
||||
if (global.lang == "zh") {
|
||||
return zh;
|
||||
} else {
|
||||
return en;
|
||||
}
|
||||
}
|
||||
|
||||
export function input(value) {
|
||||
let message = {
|
||||
"type": "inputText",
|
||||
@ -55,7 +55,7 @@ export function input(value) {
|
||||
// msg = { type: 2, value: value, xpath: message.xpath, id: global.id};
|
||||
let message_keyboard = {
|
||||
type: 2, //消息类型,2代表键盘输入
|
||||
message: { "keyboardStr": value, "xpath": message.xpath, "iframe": global.iframe, "id": global.id } // {}全选{BS}退格
|
||||
message: {"keyboardStr": value, "xpath": message.xpath, "iframe": global.iframe, "id": global.id} // {}全选{BS}退格
|
||||
};
|
||||
global.ws.send(JSON.stringify(message_keyboard));
|
||||
}
|
||||
@ -81,7 +81,7 @@ export function sendSingleClick() {
|
||||
global.ws.send(JSON.stringify(message_action));
|
||||
}
|
||||
|
||||
export function sendChangeOption(optionMode, optionValue){
|
||||
export function sendChangeOption(optionMode, optionValue) {
|
||||
let message = {
|
||||
"type": "changeOption",
|
||||
"optionMode": optionMode,
|
||||
@ -101,7 +101,7 @@ export function sendChangeOption(optionMode, optionValue){
|
||||
global.ws.send(JSON.stringify(message_action));
|
||||
}
|
||||
|
||||
export function sendMouseMove(){
|
||||
export function sendMouseMove() {
|
||||
let message = {
|
||||
"type": "mouseMove",
|
||||
"history": history.length, //记录history的长度
|
||||
@ -120,7 +120,7 @@ export function sendMouseMove(){
|
||||
global.ws.send(JSON.stringify(message_action));
|
||||
}
|
||||
|
||||
export function sendLoopMouseMove(){
|
||||
export function sendLoopMouseMove() {
|
||||
let message = {
|
||||
"type": "loopMouseMove",
|
||||
"history": history.length, //记录history的长度
|
||||
@ -168,8 +168,75 @@ export function collectSingle() {
|
||||
message: {"pipe": JSON.stringify(message)}
|
||||
};
|
||||
global.ws.send(JSON.stringify(message_action));
|
||||
createNotification(LANG("采集成功", "Collect successfully"), "success");
|
||||
}
|
||||
|
||||
function createNotification(text, type="info") {
|
||||
// 创建通知元素
|
||||
let notification = document.createElement('div');
|
||||
notification.className = 'notification_of_easyspider'; // 使用 class 方便后续添加样式
|
||||
notification.setAttribute("data-timestamp", new Date().getTime()); // 用于清除通知
|
||||
// 设置通知文本
|
||||
notification.innerText = text;
|
||||
|
||||
// 定义与添加样式
|
||||
let cssText = `
|
||||
position: fixed;
|
||||
bottom: 20px; /* 距底部20px */
|
||||
right: -320px; /* 初始位置在屏幕右侧,假设通知框宽度320px */
|
||||
min-width: 300px;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
z-index: 2147483641;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
|
||||
transition: right 0.5s ease-in-out; /* 动画效果 */
|
||||
`;
|
||||
notification.style.cssText = cssText;
|
||||
|
||||
if (type === "success") {
|
||||
notification.style.backgroundColor = 'rgb(103, 194, 58)';
|
||||
} else if (type === "info") {
|
||||
notification.style.backgroundColor = '#00a8ff';
|
||||
} else if (type === "warning") {
|
||||
notification.style.backgroundColor = 'rgb(230, 162, 60)';
|
||||
} else if (type === "error") {
|
||||
notification.style.backgroundColor = '#ff6b6b';
|
||||
}
|
||||
|
||||
// 将通知添加到页面中
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// 触发动画,通知从右向左滑入
|
||||
setTimeout(function () {
|
||||
notification.style.right = '20px'; // 调整距离左边的位置
|
||||
}, 100);
|
||||
let timeoutInterval = 1500 * text.length / 5;
|
||||
// 设置退出动画,通知从右向左滑出
|
||||
setTimeout(function () {
|
||||
notification.style.right = '-320px'; // 向左退出
|
||||
// 确定动画结束后移除通知
|
||||
notification.addEventListener('transitionend', function () {
|
||||
if (notification.parentNode === document.body) {
|
||||
document.body.removeChild(notification); // 避免移除已经不存在的元素
|
||||
}
|
||||
});
|
||||
}, timeoutInterval + 500); // 通知停留时间加上动画时间
|
||||
}
|
||||
|
||||
setInterval(function () {
|
||||
let notifications = document.getElementsByClassName("notification_of_easyspider");
|
||||
for (let i = 0; i < notifications.length; i++) {
|
||||
if (new Date().getTime() - parseInt(notifications[i].getAttribute("data-timestamp")) > 10000) {
|
||||
if (notifications[i].parentNode === document.body) {
|
||||
document.body.removeChild(notifications[i]); // 避免移除已经不存在的元素
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
|
||||
//采集无规律多元素
|
||||
export function collectMultiNoPattern() {
|
||||
let message = {
|
||||
@ -201,7 +268,7 @@ export function collectMultiWithPattern() {
|
||||
"isDescendents": global.app._data.selectedDescendents, //标记是否采集的是子元素
|
||||
"parameters": global.outputParameters,
|
||||
};
|
||||
for(let i=0;i<global.outputParameters.length;i++){
|
||||
for (let i = 0; i < global.outputParameters.length; i++) {
|
||||
global.outputParameters[i]["exampleValues"] = [global.outputParameters[i]["exampleValues"][0]];
|
||||
}
|
||||
if (!detectAllSelected()) //如果不是全部选中的话
|
||||
|
@ -52,6 +52,7 @@
|
||||
"identity",
|
||||
"storage",
|
||||
"tabs",
|
||||
"scripting"
|
||||
"scripting",
|
||||
"notifications"
|
||||
]
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
min-height: 300px;
|
||||
background-color: white;
|
||||
position: fixed;
|
||||
z-index: 2147483647;
|
||||
z-index: 2147483640;
|
||||
right: 30px;
|
||||
bottom: 30px;
|
||||
font-size: 13px !important;
|
||||
|
Loading…
x
Reference in New Issue
Block a user