From 1982cb3c634f4d4e6ad5a1d389c908a7048ac12b Mon Sep 17 00:00:00 2001 From: naibo Date: Fri, 22 Dec 2023 04:16:36 +0800 Subject: [PATCH] Change version check to only macos --- .../Code/easyspider_executestage.py | 29 +- ElectronJS/EasySpider_en.crx | Bin 211968 -> 211968 bytes ElectronJS/EasySpider_zh.crx | Bin 211969 -> 211969 bytes ElectronJS/main.js | 2571 +++++++++-------- 4 files changed, 1308 insertions(+), 1292 deletions(-) diff --git a/.temp_to_pub/EasySpider_windows_x64/Code/easyspider_executestage.py b/.temp_to_pub/EasySpider_windows_x64/Code/easyspider_executestage.py index e760a48..b65f540 100644 --- a/.temp_to_pub/EasySpider_windows_x64/Code/easyspider_executestage.py +++ b/.temp_to_pub/EasySpider_windows_x64/Code/easyspider_executestage.py @@ -1835,16 +1835,20 @@ class BrowserThread(Thread): content = self.browser.title elif p["contentType"] == 7: # 获取整个网页的高度和宽度 - height = self.browser.execute_script( - "return document.body.scrollHeight") - width = self.browser.execute_script( - "return document.body.scrollWidth") + size = self.browser.get_window_size() + width = size["width"] + height = size["height"] # 调整浏览器窗口的大小 self.browser.set_window_size(width, height) element.screenshot("Data/Task_" + str(self.id) + "/" + self.saveName + "/" + str(time.time()) + ".png") + # 截图完成后,将浏览器的窗口大小设置为原来的大小 + self.browser.set_window_size(width, height) elif p["contentType"] == 8: try: + size = self.browser.get_window_size() + width = size["width"] + height = size["height"] screenshot = element.screenshot_as_png screenshot_stream = io.BytesIO(screenshot) # 使用Pillow库打开截图,并转换为灰度图像 @@ -1858,6 +1862,7 @@ class BrowserThread(Thread): image_bytes = f.read() content = ocr.classification(image_bytes) os.remove(location) + self.browser.set_window_size(width, height) # 使用Tesseract OCR引擎识别图像中的文本 # content = pytesseract.image_to_string(image, lang='chi_sim+eng') except Exception as e: @@ -2258,13 +2263,21 @@ if __name__ == '__main__': tmp_user_data_folder = os.path.join(tmp_user_folder_parent, "user_data_" + str(id) + "_" + str(time.time()).replace(".","") + "_" + random_string) tmp_options[i]["tmp_user_data_folder"] = tmp_user_data_folder if os.path.exists(tmp_user_data_folder): - shutil.rmtree(tmp_user_data_folder) + try: + shutil.rmtree(tmp_user_data_folder) + except: + pass print(f"Copying user data folder to: {tmp_user_data_folder}, please wait...") print(f"正在复制用户信息目录到: {tmp_user_data_folder},请稍等...") if os.path.exists(absolute_user_data_folder): - shutil.copytree(absolute_user_data_folder, tmp_user_data_folder) - print("User data folder copied successfully, if you exit the program before it finishes, please delete the temporary user data folder manually.") - print("用户信息目录复制成功,如果程序在运行过程中被手动退出,请手动删除临时用户信息目录。") + try: + shutil.copytree(absolute_user_data_folder, tmp_user_data_folder) + print("User data folder copied successfully, if you exit the program before it finishes, please delete the temporary user data folder manually.") + print("用户信息目录复制成功,如果程序在运行过程中被手动退出,请手动删除临时用户信息目录。") + except: + tmp_user_data_folder = absolute_user_data_folder + print("Copy user data folder failed, use the original folder.") + print("复制用户信息目录失败,使用原始目录。") else: tmp_user_data_folder = absolute_user_data_folder print("Cannot find user data folder, create a new folder.") diff --git a/ElectronJS/EasySpider_en.crx b/ElectronJS/EasySpider_en.crx index e274612fd582284aec9fade9f149c86922c329c4..6158de956679b88a10f942e4a56786defbf58eca 100644 GIT binary patch delta 1296 zcmXZWdpOez7zgn28)Gy=6s24$NoSPUg_Yx$Imi~exF(l)CeLOZE5O4PHc92`pIvRrcJcI-L*_4&Tv=Y8Ji&0NyXT++UBh{{XT?DpR6D|(22 zrGC-3gcOUIcK>y}MIt!0LQC`xG2O*!cp=SDY)W~R92>gdVI0F5H+sL;#W1w2U^q`7 zO?KMCLCew=4vkd=R#^ozOpc{syx>|9&Dw@ipLQE^F2~@8N&)<@C#BS_g>QWo{Q1`6 zQ=}cP9ad{#+1FI6eVpy*=9vRI`ZdI;uw88O>X|^4)1_}xosX79u4GURN7q^XHI_oA zjkBNC7rnY@ea|_;tS-G@?MO^o%e&B<_TF9Xcb7zdmgnc44@m4%PTFPEY|lD2&HM*9 zJvx0y3Rzj?az+NA#Oe}R?e@t)A|9s*r7!}fb1nl!?q#a0u;4eJGSQ798&zlKo%N$< z>+E}EF)?Q+3~|wgWs6sur3HP z71cAmrj1Y2g*QB;!kda>24k{=ozJwLqe%SEy13Mk>DM|A4!`sQ*zP=I(;a zds7CpZ9!j6{NCT$6cULITj)b22DKKMXX5l9T`(6fUO8Nk+HtA$M}JiHFSN2*gLRkU z;DU!9;?r}s(Y{|xtSi;hpT4^$pxE~G?_FZIfvCfQ7I;-a1*D>v367H6AB&eV5lb*u z7z4Sjjffg*%qUo~&E;qvsYv9oUV^Jj*y3oJY%eaq&V-#L7tCe;A$#>n-5r7kYzQ{0BlD= z{q1P{kozam@!9J|`|r$}pZMLY%%soJY$r4qf!**%srE@atjj7q=avuIdlC;($nTDd9_$OgVxm5S=CxDvKm0w3brl@9 zbprNurwiw9BfUK}T6GnMX3}?7gR3bLaSlB-^+8^zqd0a)LVu~(>nDOo3kg0jl763s zrszj)4n*$%K913}JgIxW{r(rD>II90F`B{=+v?YN7n-k^7U#w6^^4q+-2ygt%Z3o< zZt}Af_(qg$(IJZ_IY=j;JJ9gb_Y|*p_(YF&QpY7ZSP!bZPW+^`1wEsqgPWO=2Rq$A z?hSwqKpGkvAh;$s1e}Fcg=?175KPN4NI;zn@vDISEVzP@QJsy Cn@@ZI delta 1296 zcmXZWdpOez7zgn28^cD>8 zvhS>&YlqpzU))II@pq3s0>z%OR*+M%mH5PMC~m zkx~t{rVY&%`m2mX@ibQPNS?l)T zWKeN%jJm##Zz3!II4h|AQz>;xcg9r6xH0Y<8%?-ExhA}AgKwJiH_XW*Elyu>y}_;Q zlu|M*B&+c&Jz{Nf233I4lNdns)E#q*u%MU9VQ#g@^eV$XnKU{waEs5Y%qi_V`r+2S z@YE?@FuxB;KU7%WMsQ;~#WcV_ZHLZYRo~-J%k-IGk!!)X8STB|^9bss{`-*c9fW!0 z8o8fm17F|8qfX0jzo12gP&=kNp8S>98Ry5C>=LQzmwML^;O_Vov~n8w8`fc@8lZeg zW;K_kOJpazJTJ&v4BheukYpLRbgzUxJfW-i&~ zHy-_1*KBjJ{LhDFFpG7MkPvBAQg+!{D^`)*iLMMNL6i{5P{%#@wFlT_k=I1MCGpa3 z`>??Tv%DqijWAT&AOw#zAD6x3pL|M7CLUO4Min2DBA0SC_K#%vn=G3)5(Vq9VF3(d z*=YD)M-NPbVI)%~aK1Tv~#LA9>H(BA*qE|Kf; z?WWnJbpTqpIQ=p7EaloVt8F2OGHejOJ8qJK&&= z{%m(zv~~W0YfK{3eLVNvzRoJ=E(1^RzoT-626OecffJ8pBQFy4vPT6&n$c=|dlnx% z)^%eo)bpY(c&9m5>(cR7rP|Adlz{%G0Pd^F`xa-0eRqsGfaoJ{Zb!~FjS68s-^{kA zoWXZxO75zBnKBN|!92!PR5V85sT1x++I!BU$tlZFgu2#lqlS7|z)BRjvq#pwAe9CB z08m{B3ysS;ULy_WK2yR+Ii+Oi*h=sxg~dWPIv?3ESTXyU@{`!31@AE$I^JcGWX0K~rLsQ$L`2)oHoFaK? z!)=%N{;qa&hMe~}bk(jdHPrhYVIkRz{(X1Y`RXaG&Dctx0Ka@9SI3;Ao*2b$pmzxi zJNR>+_3jz>dwTb(CebSkcQl86O&_^NLT7yu$c`re?4NCOj@8*%1mxSVG><^dQbF3e zb>S++=>wP`tNPf7)a4d1G#Dwo*DD1~{O4Ytzu9VJ$zC)j5O)FU;QuO?C9PmSzIN!bcLO_wui?U9PdD#;z2Tvur#*AlPri^Kgz8lKen=)Bd zsIhnhV$8Os_MHpFd~)ul;JZuyZmx=AR<* z2SYh7y)nrf{C0-8MvKx8s-q-OBpHTUSMRw}5B=ew5pr^Ys(BL*ePdaA%fe>(Q&lT@ zIC;}$KQ-c6Bg+2sruRtvuPG&;S9Rx>djnNA$y`8aGd_F5wl|5@E&c)xfW3|J+>th`q1}0#W{3&+$8lZ4g`3_@0B9J(KDVjL|ZbIAR$@+f{n?y5OGRwLs2DhP6F{H7l?d6&4d>Ic%8D&69UBU)xgd zzJAW_dI0thns!`L^P+U@$t3AhLAbW8_@v!V9;|*BGwDXdqce-5)ET)tV&k}&!N++@j`(k?xshd|W>%}x7c&*lU#|JC zBsC`Ni~S90VSvvL@p{jOwDAJ9O+1ahA&}Q})9I?Vb7W&sUTa@8q<}i|@H$+YS&-`M zQ88-X&!mdN%jqkUUU>J7FEwaUdta2k4;ohbBqg9${SNwot#(V#+=ho;q#%A!Fspy@ z^1@J*MmN7as)-N)L$@S{#jGJZ9}!EDwR$y6-V$1C+eCKjgssEc*rh9RHZrnKp4j;g z3&VjB-@=Y1lP{K|PQ`Fe51oTF)wLDmpGNw;$q|Ef)pb(*35KMBphn*-1g|pF9R%&k-3~rEc*H&gU#g-ZS za0>ODfWr!Xw=LOr+zD_}^xDpVyTTLBfa1^cdS~D#h4an;Nud)Ka8pRd{=d)00{H&` D?8Q?l delta 1296 zcmXZWeKgYx7zc3n+Y7>K?QE%Zue>yQDU6y47ipJ5UJ9j1wREi^v9<1<&15Ux$>z>A zr&_LEMJdC&STAOhGt`WnTl90hMS9s%-gWKV{`!2M?|II19@eZmYu3EbgSp709*5Hu z%2H&iCatRcJa4gyD-1GYjjG-JQrMYvc_$>?{$<;b2S@5)KGYoFo3|bm*j#G7h<+tY z=C3J9QpIHl_PwB9avS8y&xk80K#$W+^^NpHnFWr$S&YbmRp2M7ENiCc?x5Xs&+Tsa zu*Ld4Cys+EmOcWitx+(ksa4%f`^#x?`i*!*(w1uW-arw#B45#3>sduxjM8rJ|5T3p zR)niL^VcWAipFO)R1q>PS2CuBkDCHcK6BRIV&)L)f;L zTWFLJf6VCL1*;#{FXW(AwZySjMb83?GA_Si5iuFVy;Q_xaH4lOm}`sipt#7`V?H`I zz>bUM7J!+)dHzt0)IE+T?Upq3RBzHss`U?5~04Yl;n|BEGub zUyt6#pb-pGG^}1t-ZoY8ZN~-G3H&|5W3>$);E+!@ZYlwW%Q43;hSi> z<=34ld3DK7`Ml0*v~R|HZ;Y(uwRG;5VsjRA_BJ#L0vH<^qjI2$g8e_}Z9>b&mA}Rg z<3q$?JQl0n7<`hYvl)2{jz1`5cdT0Kw3l7jlINte2&j4!Hy-O$Yzyo(Z=&RH?XRJb z9{X#0l1Vv8uSWOvWR9ZKjsf=7x&!17-5p&4ro$T{>)*on9Wj}VZO%|iW*k4?Wom8b zT0X;y8Ss{OzsFg=Rrki zx6^E^#nN_O;A>Jvcj^1)V`0yZ32T-M5A^@`Z5Iu!tuT@X{jN#1ZwWi`!3+5{*V9u# zFFQz0U90IMf}Hurf-Y+ox{W++8`NwC3X2Fb;k0NI!IFT$}C^N0_|popxO-VGaQhk-2t7kAt3O;Gw4bXX?6mB z2GD4{YE0N=RX2W BQ?vj8 diff --git a/ElectronJS/main.js b/ElectronJS/main.js index bfeed60..83cef2c 100644 --- a/ElectronJS/main.js +++ b/ElectronJS/main.js @@ -1,52 +1,52 @@ // Modules to control application life and create native browser window const { - app, - BrowserWindow, - dialog, - ipcMain, - screen, - session, + app, + BrowserWindow, + dialog, + ipcMain, + screen, + session, } = require("electron"); app.commandLine.appendSwitch("--disable-http-cache"); const { - Builder, - By, - Key, - until, - Select, - StaleElementReferenceException, + 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"); -const { exit } = require("process"); +const {ServiceBuilder} = require("selenium-webdriver/chrome"); +const {rootCertificates} = require("tls"); +const {exit} = require("process"); const path = require("path"); const fs = require("fs"); -const { exec, spawn, execFile } = require("child_process"); +const {exec, spawn, execFile} = require("child_process"); const iconPath = path.join(__dirname, "favicon.ico"); const task_server = require(path.join(__dirname, "server.js")); const util = require("util"); let config = fs.readFileSync( - path.join(task_server.getDir(), `config.json`), - "utf8" + path.join(task_server.getDir(), `config.json`), + "utf8" ); config = JSON.parse(config); let config_context = JSON.parse( - fs.readFileSync(path.join(task_server.getDir(), `config.json`), "utf8") + fs.readFileSync(path.join(task_server.getDir(), `config.json`), "utf8") ); //仅在当前进程中使用,不会写入文件 if (config.debug) { - let logPath = "info.log"; - 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 () { - logFile.write(util.format.apply(null, arguments) + "\n"); - process.stderr.write(util.format.apply(null, arguments) + "\n"); - }; + let logPath = "info.log"; + 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 () { + logFile.write(util.format.apply(null, arguments) + "\n"); + process.stderr.write(util.format.apply(null, arguments) + "\n"); + }; } let allWindowSockets = []; let allWindowScoketNames = []; @@ -60,46 +60,46 @@ let execute_path = ""; console.log(process.arch); exec(`wmic os get Caption`, function (error, stdout, stderr) { - if (error) { - console.error(`执行的错误: ${error}`); - return; - } - - if (stdout.includes("Windows 7")) { - console.log("Windows 7"); - let sys_arch = config.sys_arch; - if (sys_arch === "x64") { - dialog.showMessageBoxSync({ - type: "error", - title: "Error", - message: - "Windows 7系统请下载使用x32版本的软件,不论Win 7系统为x64还是x32版本。\nFor Windows 7, please download and use the x32 version of the software, regardless of whether the Win 7 system is x64 or x32 version.", - }); + if (error) { + console.error(`执行的错误: ${error}`); + return; + } + + if (stdout.includes("Windows 7")) { + console.log("Windows 7"); + let sys_arch = config.sys_arch; + if (sys_arch === "x64") { + dialog.showMessageBoxSync({ + type: "error", + title: "Error", + message: + "Windows 7系统请下载使用x32版本的软件,不论Win 7系统为x64还是x32版本。\nFor Windows 7, please download and use the x32 version of the software, regardless of whether the Win 7 system is x64 or x32 version.", + }); + } + } else { + console.log("Not Windows 7"); } - } else { - console.log("Not Windows 7"); - } }); if (process.platform === "win32" && process.arch === "ia32") { - driverPath = path.join(__dirname, "chrome_win32/chromedriver_win32.exe"); - chromeBinaryPath = path.join(__dirname, "chrome_win32/chrome.exe"); - execute_path = path.join(__dirname, "chrome_win32/execute.bat"); + driverPath = path.join(__dirname, "chrome_win32/chromedriver_win32.exe"); + chromeBinaryPath = path.join(__dirname, "chrome_win32/chrome.exe"); + execute_path = path.join(__dirname, "chrome_win32/execute.bat"); } else if (process.platform === "win32" && process.arch === "x64") { - driverPath = path.join(__dirname, "chrome_win64/chromedriver_win64.exe"); - chromeBinaryPath = path.join(__dirname, "chrome_win64/chrome.exe"); - execute_path = path.join(__dirname, "chrome_win64/execute.bat"); + driverPath = path.join(__dirname, "chrome_win64/chromedriver_win64.exe"); + chromeBinaryPath = path.join(__dirname, "chrome_win64/chrome.exe"); + execute_path = path.join(__dirname, "chrome_win64/execute.bat"); } else if (process.platform === "darwin") { - driverPath = path.join(__dirname, "chromedriver_mac64"); - chromeBinaryPath = path.join( - __dirname, - "chrome_mac64.app/Contents/MacOS/Google Chrome" - ); - execute_path = path.join(__dirname, ""); + driverPath = path.join(__dirname, "chromedriver_mac64"); + chromeBinaryPath = path.join( + __dirname, + "chrome_mac64.app/Contents/MacOS/Google Chrome" + ); + execute_path = path.join(__dirname, ""); } else if (process.platform === "linux") { - driverPath = path.join(__dirname, "chrome_linux64/chromedriver_linux64"); - chromeBinaryPath = path.join(__dirname, "chrome_linux64/chrome"); - execute_path = path.join(__dirname, "chrome_linux64/execute.sh"); + driverPath = path.join(__dirname, "chrome_linux64/chromedriver_linux64"); + chromeBinaryPath = path.join(__dirname, "chrome_linux64/chrome"); + execute_path = path.join(__dirname, "chrome_linux64/execute.sh"); } console.log(driverPath, chromeBinaryPath, execute_path); let language = "en"; @@ -130,691 +130,691 @@ let invoke_window = null; // testt(); function createWindow() { - // Create the browser window. - mainWindow = new BrowserWindow({ - width: 600, - height: 800, - webPreferences: { - preload: path.join(__dirname, "src/js/preload.js"), - }, - icon: iconPath, - // frame: false, //取消window自带的关闭最小化等 - resizable: false, //禁止改变主窗口尺寸 - }); + // Create the browser window. + mainWindow = new BrowserWindow({ + width: 600, + height: 800, + webPreferences: { + preload: path.join(__dirname, "src/js/preload.js"), + }, + icon: iconPath, + // frame: false, //取消window自带的关闭最小化等 + resizable: false, //禁止改变主窗口尺寸 + }); - // 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" } - ); - // 隐藏菜单栏 - const { Menu } = require("electron"); - Menu.setApplicationMenu(null); - mainWindow.on("close", function (e) { - if (process.platform !== "darwin") { - app.quit(); - } - }); - // mainWindow.webContents.openDevTools(); - // Open the DevTools. - // mainWindow.webContents.openDevTools() + // 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"} + ); + // 隐藏菜单栏 + const {Menu} = require("electron"); + Menu.setApplicationMenu(null); + mainWindow.on("close", function (e) { + if (process.platform !== "darwin") { + app.quit(); + } + }); + // mainWindow.webContents.openDevTools(); + // Open the DevTools. + // mainWindow.webContents.openDevTools() } 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; + 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; + } } - } - } 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`); + 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(); + // 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}` - ); + 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; } - 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, - notifyBrowser = true, - scrollIntoView = true + msg, + notifyBrowser = true, + scrollIntoView = true ) { - 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 { - //如果msg.pathList存在,说明是循环中的元素 - if ( - msg.pathList != undefined && - msg.pathList != null && - msg.pathList != "" - ) { - xpath = msg.pathList[0].trim(); + 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 { - xpath = msg.xpath; + content_handle = handle_pairs[id]; } - } - if (xpath.indexOf("Field(") >= 0 || xpath.indexOf("eval(") >= 0) { - //两秒后通知浏览器 - await new Promise((resolve) => setTimeout(resolve, 2000)); - notify_browser( - '检测到XPath中包含Field("")或eval(""),试运行时无法正常定位到包含此两项表达式的元素,请在任务正式运行阶段测试是否有效。', - 'Field("") or eval("") is detected in xpath, and the element containing these two expressions cannot be located normally during trial operation. Please test whether it is valid in the formal call stage.', - "warning" - ); - return null; - } - let notify = false; - while (true) { - // console.log("handles"); + // 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 { - 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; - } + iframe = msg.message.iframe; + } catch { + iframe = msg.iframe; } - } - if (element == null && notifyBrowser) { - notify_browser( - "无法找到元素,请检查XPath是否正确:" + xpath, - "Cannot find the element, please check if the XPath is correct: " + xpath, - "warning" - ); - } - if (element != null && scrollIntoView) { - // 浏览器切换到元素位置稍微靠上的位置 + // if (iframe) { + // notify_browser("在IFrame中执行操作可能需要较长时间,请耐心等待。", "Executing operations in IFrame may take a long time, please wait patiently.", "info"); + // } + let xpath = ""; try { - // let script = `arguments[0].scrollIntoView(true);`; - let script = `arguments[0].scrollIntoView({block: "center", inline: "center"});`; - await driver.executeScript(script, element); - } catch (e) { - console.log("Cannot scrollIntoView"); + xpath = msg.message.xpath; + } catch { + //如果msg.pathList存在,说明是循环中的元素 + if ( + msg.pathList != undefined && + msg.pathList != null && + msg.pathList != "" + ) { + xpath = msg.pathList[0].trim(); + } else { + xpath = msg.xpath; + } } - } - return element; + if (xpath.indexOf("Field(") >= 0 || xpath.indexOf("eval(") >= 0) { + //两秒后通知浏览器 + await new Promise((resolve) => setTimeout(resolve, 2000)); + notify_browser( + '检测到XPath中包含Field("")或eval(""),试运行时无法正常定位到包含此两项表达式的元素,请在任务正式运行阶段测试是否有效。', + 'Field("") or eval("") is detected in xpath, and the element containing these two expressions cannot be located normally during trial operation. Please test whether it is valid in the formal call stage.', + "warning" + ); + return null; + } + 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 && notifyBrowser) { + notify_browser( + "无法找到元素,请检查XPath是否正确:" + xpath, + "Cannot find the element, please check if the XPath is correct: " + xpath, + "warning" + ); + } + if (element != null && scrollIntoView) { + // 浏览器切换到元素位置稍微靠上的位置 + try { + // let script = `arguments[0].scrollIntoView(true);`; + let script = `arguments[0].scrollIntoView({block: "center", inline: "center"});`; + await driver.executeScript(script, element); + } catch (e) { + console.log("Cannot scrollIntoView"); + } + } + return element; } async function beginInvoke(msg, ws) { - if (msg.type == 1) { - if (msg.message.id != -1) { - let url = ""; - if (language == "zh") { - url = - server_address + - `/taskGrid/FlowChart_CN.html?id=${msg.message.id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + - server_address; - } else if (language == "en") { - 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" }); - } - 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 ( - config_context.user_data_folder == null || - config_context.user_data_folder == undefined || - config_context.user_data_folder == "" - ) { - const { windowManager } = require("node-window-manager"); - const window = windowManager.getActiveWindow(); - console.log(window); - windowManager.requestAccessibility(); - // Sets the active window's bounds. - let size = screen.getPrimaryDisplay().workAreaSize; - let width = parseInt(size.width); - let height = parseInt(size.height * 0.6); - window.setBounds({ - x: 0, - y: size.height * 0.4, - height: height, - width: width, - }); - } - } - flowchart_window.show(); - // flowchart_window.openDevTools(); - } else if (msg.type == 2) { - // 键盘输入事件 - // const robot = require("@jitsi/robotjs"); - let keyInfo = msg.message.keyboardStr; - let enter = false; - if (//i.test(keyInfo)) { - keyInfo = keyInfo.replace(//gi, ""); - enter = true; - } - let element = await findElementAcrossAllWindows( - msg, - (notifyBrowser = true), - (scrollIntoView = false) - ); - 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 { - if (msg.from == 0) { - socket_flowchart.send(msg.message.pipe); //直接把消息转接 - let message = JSON.parse(msg.message.pipe); - let type = message.type; - console.log("FROM Browser: ", message); - if (type.indexOf("Click") >= 0 || type.indexOf("Move") >= 0) { - let element = await findElementAcrossAllWindows( - message, - (notifyBrowser = true), - (scrollIntoView = false) - ); - if (type.indexOf("Click") >= 0) { - await click_element(element, type); - } else if (type.indexOf("Move") >= 0) { - await driver.actions().move({ origin: element }).perform(); - } - } - } else { - 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) { - //标记元素和试运行功能 - let node = JSON.parse(msg.message.node); - let type = msg.message.type; - if (type == 0) { - //标记元素 - let option = node.option; - let parameters = node.parameters; - //下面是让浏览器自动滚动到元素位置 - if (option == 2 || option == 4 || option == 6 || option == 7) { - let xpath = parameters.xpath; - let parent_node = JSON.parse(msg.message.parentNode); - if (parameters.useLoop && option != 4 && option != 6) { - let parent_xpath = parent_node.parameters.xpath; - if (parent_node.parameters.loopType == 2) { - parent_xpath = parent_node.parameters.pathList - .split("\n")[0] - .trim(); - } - xpath = parent_xpath + xpath; - } - if (xpath.includes("point(")) { - xpath = "//body"; - } - let elementInfo = { iframe: parameters.iframe, xpath: xpath, id: -1 }; - //用于跳转到元素位置 - let element = await findElementAcrossAllWindows(elementInfo); - } else if (option == 3) { - let params = parameters.params; //所有的提取数据参数 - let param = params[0]; - let xpath = param.relativeXPath; - if (param.relative) { - let parent_node = JSON.parse(msg.message.parentNode); - let parent_xpath = parent_node.parameters.xpath; - if (parent_node.parameters.loopType == 2) { - parent_xpath = parent_node.parameters.pathList - .split("\n")[0] - .trim(); - } - xpath = parent_xpath + xpath; - } - let elementInfo = { iframe: param.iframe, xpath: xpath, id: -1 }; - let element = await findElementAcrossAllWindows(elementInfo); - } else if (option == 11) { - let params = parameters.params; //所有的提取数据参数 - let i = parameters.index; - let param = params[i]; - let xpath = param.relativeXPath; - if (param.relative) { - let parent_node = JSON.parse(msg.message.parentNode); - let parent_xpath = parent_node.parameters.xpath; - if (parent_node.parameters.loopType == 2) { - parent_xpath = parent_node.parameters.pathList - .split("\n")[0] - .trim(); - } - xpath = parent_xpath + xpath; - } - let elementInfo = { iframe: param.iframe, xpath: xpath, id: -1 }; - let element = await findElementAcrossAllWindows(elementInfo); - } else if (option == 8) { - let loopType = parameters.loopType; - if (loopType <= 2) { - let xpath = ""; - if (loopType <= 1) { - xpath = parameters.xpath; - } else if (loopType == 2) { - xpath = parameters.pathList.split("\n")[0].trim(); - } - let elementInfo = { iframe: parameters.iframe, xpath: xpath, id: -1 }; - let element = await findElementAcrossAllWindows(elementInfo); - } else if (loopType == 5) { - //JavaScript命令返回值 - let code = parameters.code; - let waitTime = parameters.waitTime; - let element = await driver.findElement(By.tagName("body")); - let outcome = await execute_js(code, element, waitTime); - if (!outcome || outcome == -1) { - notify_browser( - "目前页面中,设置的循环“" + - node.title + - "”的JavaScript条件不成立", - "The condition of the loop " + - node.title + - " is not met, skip this loop.", - "warning" - ); - } else { - notify_browser( - "目前页面中,设置的循环“" + node.title + "”的JavaScript条件成立", - "The condition of the loop " + - node.title + - " is met, continue this loop.", - "success" - ); - } - } - } else if (option == 10) { - //条件分支 - let condition = parameters.class; //条件类型 - let result = -1; - let additionalInfo = ""; - if (condition == 5 || condition == 7) { - //JavaScript命令返回值 - let code = parameters.code; - let waitTime = parameters.waitTime; - let element = await driver.findElement(By.tagName("body")); - if (condition == 7) { - let parent_node = JSON.parse(msg.message.parentNode); - let parent_xpath = parent_node.parameters.xpath; - if (parent_node.parameters.loopType == 2) { - parent_xpath = parent_node.parameters.pathList - .split("\n")[0] - .trim(); + if (msg.type == 1) { + if (msg.message.id != -1) { + let url = ""; + if (language == "zh") { + url = + server_address + + `/taskGrid/FlowChart_CN.html?id=${msg.message.id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + + server_address; + } else if (language == "en") { + url = + server_address + + `/taskGrid/FlowChart.html?id=${msg.message.id}&wsport=${websocket_port}&backEndAddressServiceWrapper=` + + server_address; } - let elementInfo = { - iframe: parent_node.parameters.iframe, - xpath: parent_xpath, - id: -1, - }; - element = await findElementAcrossAllWindows(elementInfo); - } - let outcome = await execute_js(code, element, waitTime); - if (!outcome) { - msg.message.result = 0; //条件不成立传入扩展 - } else if (outcome == -1) { - msg.message.result = -1; //JS执行出错 - } else { - msg.message.result = 1; //条件成立传入扩展 - } + console.log(url); + flowchart_window.loadURL(url, {extraHeaders: "pragma: no-cache\n"}); } - } - send_message_to_browser(JSON.stringify({ type: "trial", message: msg })); - } else { - //试运行 - try { - let flowchart_url = flowchart_window.webContents.getURL(); - } catch { - flowchart_window = null; - } - if (flowchart_window == null) { - notify_flowchart( - "试运行功能只能在任务设计阶段,Chrome浏览器打开时使用!", - "The trial run function can only be used when designing tasks and opening in Chrome browser!", - "error" - ); - } else { - 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); + 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 ( + config_context.user_data_folder == null || + config_context.user_data_folder == undefined || + config_context.user_data_folder == "" + ) { + const {windowManager} = require("node-window-manager"); + const window = windowManager.getActiveWindow(); + console.log(window); + windowManager.requestAccessibility(); + // Sets the active window's bounds. + let size = screen.getPrimaryDisplay().workAreaSize; + let width = parseInt(size.width); + let height = parseInt(size.height * 0.6); + window.setBounds({ + x: 0, + y: size.height * 0.4, + height: height, + width: width, + }); + } } - 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]; - } - try { - await driver.get(url); - } catch (e) { - try { - await driver.switchTo().window(current_handle); - await driver.get(url); - } catch (e) { - let all_handles = await driver.getAllWindowHandles(); - let handle = all_handles[all_handles.length - 1]; - await driver.switchTo().window(handle); - await driver.get(url); - } - } - } else if (option == 2 || option == 7) { - //点击事件 - let xpath = parameters.xpath; - let point = parameters.xpath; - if (xpath.includes("point(")) { - xpath = "//body"; - } - let elementInfo = { iframe: parameters.iframe, xpath: xpath, id: -1 }; - if (parameters.useLoop && !parameters.xpath.includes("point(")) { - let parent_node = JSON.parse(msg.message.parentNode); - let parent_xpath = parent_node.parameters.xpath; - if (parent_node.parameters.loopType == 2) { - parent_xpath = parent_node.parameters.pathList - .split("\n")[0] - .trim(); - } - elementInfo.xpath = parent_xpath + elementInfo.xpath; - } - let element = await findElementAcrossAllWindows( - elementInfo, - (notifyBrowser = false) - ); //通过此函数找到元素并切换到对应的窗口 - await execute_js( - parameters.beforeJS, - element, - parameters.beforeJSWaitTime - ); - if (option == 2) { - if (parameters.xpath.includes("point(")) { - await click_element(element, point); - } else { - await click_element(element); - } - let alertHandleType = parameters.alertHandleType; - if (alertHandleType == 1) { - try { - await driver.switchTo().alert().accept(); - } catch (e) { - console.log("No alert"); - } - } else if (alertHandleType == 2) { - try { - await driver.switchTo().alert().dismiss(); - } catch (e) { - console.log("No alert"); - } - } - } else if (option == 7) { - await driver.actions().move({ origin: element }).perform(); - } - await execute_js( - parameters.afterJS, - element, - parameters.afterJSWaitTime - ); - send_message_to_browser(JSON.stringify({ type: "cancelSelection" })); - } else if (option == 3) { - //提取数据 - notify_browser( - "提示:提取数据操作只能试运行设置的JavaScript语句,且只针对第一个匹配的元素。", - "Hint: can only test JavaScript statement set in the data extraction operation, and only for the first matching element.", - "info" - ); - let params = parameters.params; //所有的提取数据参数 - let not_found_xpaths = []; - for (let i = 0; i < params.length; i++) { - let param = params[i]; - let xpath = param.relativeXPath; - if (param.relative) { - let parent_node = JSON.parse(msg.message.parentNode); - let parent_xpath = parent_node.parameters.xpath; - if (parent_node.parameters.loopType == 2) { - parent_xpath = parent_node.parameters.pathList - .split("\n")[0] - .trim(); - } - xpath = parent_xpath + xpath; - } - let elementInfo = { iframe: param.iframe, xpath: xpath, id: -1 }; - let element = await findElementAcrossAllWindows( - elementInfo, - (notifyBrowser = false) - ); - if (element != null) { - await execute_js(param.beforeJS, element, param.beforeJSWaitTime); - await execute_js(param.afterJS, element, param.afterJSWaitTime); - } else { - not_found_xpaths.push(xpath); - } - } - if (not_found_xpaths.length > 0) { - notify_browser( - "无法找到以下元素,请检查XPath是否正确:" + - not_found_xpaths.join("\n"), - "Cannot find the element, please check if the XPath is correct: " + - not_found_xpaths.join("\n"), - "warning" - ); - } - } 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 (//i.test(keyInfo)) { + flowchart_window.show(); + // flowchart_window.openDevTools(); + } else if (msg.type == 2) { + // 键盘输入事件 + // const robot = require("@jitsi/robotjs"); + let keyInfo = msg.message.keyboardStr; + let enter = false; + if (//i.test(keyInfo)) { keyInfo = keyInfo.replace(//gi, ""); enter = true; - } - if (keyInfo.indexOf("Field(") >= 0 || keyInfo.indexOf("eval(") >= 0) { - //两秒后通知浏览器 - await new Promise((resolve) => setTimeout(resolve, 2000)); - notify_browser( - '检测到文字中包含Field("")或eval(""),试运行时无法输入两项表达式的替换值,请在任务正式运行阶段测试是否有效。', - 'Field("") or eval("") is detected in the text, and the replacement value of the two expressions cannot be entered during trial operation. Please test whether it is valid in the formal call stage.', - "warning" - ); - } - let element = await findElementAcrossAllWindows( - elementInfo, - (notifyBrowser = false) - ); - await execute_js(beforeJS, element, beforeJSWaitTime); - await element.sendKeys( - Key.HOME, - Key.chord(Key.SHIFT, Key.END), - keyInfo - ); - if (enter) { + } + let element = await findElementAcrossAllWindows( + msg, + (notifyBrowser = true), + (scrollIntoView = false) + ); + await element.sendKeys(Key.HOME, Key.chord(Key.SHIFT, Key.END), keyInfo); + if (enter) { await element.sendKeys(Key.ENTER); - } - await execute_js(afterJS, element, afterJSWaitTime); - } else if (option == 5) { - //自定义操作的JS代码 - let code = parameters.code; - let codeMode = parameters.codeMode; - let waitTime = parameters.waitTime; - let element = await driver.findElement(By.tagName("body")); - if (codeMode == 0) { - await execute_js(code, element, waitTime); - } else if (codeMode == 8) { - //刷新页面 + } + } else if (msg.type == 3) { + try { + if (msg.from == 0) { + socket_flowchart.send(msg.message.pipe); //直接把消息转接 + let message = JSON.parse(msg.message.pipe); + let type = message.type; + console.log("FROM Browser: ", message); + if (type.indexOf("Click") >= 0 || type.indexOf("Move") >= 0) { + let element = await findElementAcrossAllWindows( + message, + (notifyBrowser = true), + (scrollIntoView = false) + ); + if (type.indexOf("Click") >= 0) { + await click_element(element, type); + } else if (type.indexOf("Move") >= 0) { + await driver.actions().move({origin: element}).perform(); + } + } + } else { + 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) { + //标记元素和试运行功能 + let node = JSON.parse(msg.message.node); + let type = msg.message.type; + if (type == 0) { + //标记元素 + let option = node.option; + let parameters = node.parameters; + //下面是让浏览器自动滚动到元素位置 + if (option == 2 || option == 4 || option == 6 || option == 7) { + let xpath = parameters.xpath; + let parent_node = JSON.parse(msg.message.parentNode); + if (parameters.useLoop && option != 4 && option != 6) { + let parent_xpath = parent_node.parameters.xpath; + if (parent_node.parameters.loopType == 2) { + parent_xpath = parent_node.parameters.pathList + .split("\n")[0] + .trim(); + } + xpath = parent_xpath + xpath; + } + if (xpath.includes("point(")) { + xpath = "//body"; + } + let elementInfo = {iframe: parameters.iframe, xpath: xpath, id: -1}; + //用于跳转到元素位置 + let element = await findElementAcrossAllWindows(elementInfo); + } else if (option == 3) { + let params = parameters.params; //所有的提取数据参数 + let param = params[0]; + let xpath = param.relativeXPath; + if (param.relative) { + let parent_node = JSON.parse(msg.message.parentNode); + let parent_xpath = parent_node.parameters.xpath; + if (parent_node.parameters.loopType == 2) { + parent_xpath = parent_node.parameters.pathList + .split("\n")[0] + .trim(); + } + xpath = parent_xpath + xpath; + } + let elementInfo = {iframe: param.iframe, xpath: xpath, id: -1}; + let element = await findElementAcrossAllWindows(elementInfo); + } else if (option == 11) { + let params = parameters.params; //所有的提取数据参数 + let i = parameters.index; + let param = params[i]; + let xpath = param.relativeXPath; + if (param.relative) { + let parent_node = JSON.parse(msg.message.parentNode); + let parent_xpath = parent_node.parameters.xpath; + if (parent_node.parameters.loopType == 2) { + parent_xpath = parent_node.parameters.pathList + .split("\n")[0] + .trim(); + } + xpath = parent_xpath + xpath; + } + let elementInfo = {iframe: param.iframe, xpath: xpath, id: -1}; + let element = await findElementAcrossAllWindows(elementInfo); + } else if (option == 8) { + let loopType = parameters.loopType; + if (loopType <= 2) { + let xpath = ""; + if (loopType <= 1) { + xpath = parameters.xpath; + } else if (loopType == 2) { + xpath = parameters.pathList.split("\n")[0].trim(); + } + let elementInfo = {iframe: parameters.iframe, xpath: xpath, id: -1}; + let element = await findElementAcrossAllWindows(elementInfo); + } else if (loopType == 5) { + //JavaScript命令返回值 + let code = parameters.code; + let waitTime = parameters.waitTime; + let element = await driver.findElement(By.tagName("body")); + let outcome = await execute_js(code, element, waitTime); + if (!outcome || outcome == -1) { + notify_browser( + "目前页面中,设置的循环“" + + node.title + + "”的JavaScript条件不成立", + "The condition of the loop " + + node.title + + " is not met, skip this loop.", + "warning" + ); + } else { + notify_browser( + "目前页面中,设置的循环“" + node.title + "”的JavaScript条件成立", + "The condition of the loop " + + node.title + + " is met, continue this loop.", + "success" + ); + } + } + } else if (option == 10) { + //条件分支 + let condition = parameters.class; //条件类型 + let result = -1; + let additionalInfo = ""; + if (condition == 5 || condition == 7) { + //JavaScript命令返回值 + let code = parameters.code; + let waitTime = parameters.waitTime; + let element = await driver.findElement(By.tagName("body")); + if (condition == 7) { + let parent_node = JSON.parse(msg.message.parentNode); + let parent_xpath = parent_node.parameters.xpath; + if (parent_node.parameters.loopType == 2) { + parent_xpath = parent_node.parameters.pathList + .split("\n")[0] + .trim(); + } + let elementInfo = { + iframe: parent_node.parameters.iframe, + xpath: parent_xpath, + id: -1, + }; + element = await findElementAcrossAllWindows(elementInfo); + } + let outcome = await execute_js(code, element, waitTime); + if (!outcome) { + msg.message.result = 0; //条件不成立传入扩展 + } else if (outcome == -1) { + msg.message.result = -1; //JS执行出错 + } else { + msg.message.result = 1; //条件成立传入扩展 + } + } + } + send_message_to_browser(JSON.stringify({type: "trial", message: msg})); + } else { + //试运行 try { - await driver.navigate().refresh(); - } catch (e) { - try { - await driver.switchTo().window(current_handle); - await driver.navigate().refresh(); - } catch (e) { - let all_handles = await driver.getAllWindowHandles(); - let handle = all_handles[all_handles.length - 1]; - await driver.switchTo().window(handle); - await driver.navigate().refresh(); - } + let flowchart_url = flowchart_window.webContents.getURL(); + } catch { + flowchart_window = null; } - } - } 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, - (notifyBrowser = false) - ); - execute_js(beforeJS, element, beforeJSWaitTime); - let dropdown = new Select(element); - // Interacting with dropdown element based on optionMode - switch (optionMode) { - case 0: //切换到下一个选项 - let script = `var options = arguments[0].options; + if (flowchart_window == null) { + notify_flowchart( + "试运行功能只能在任务设计阶段,Chrome浏览器打开时使用!", + "The trial run function can only be used when designing tasks and opening in Chrome browser!", + "error" + ); + } else { + 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]; + } + try { + await driver.get(url); + } catch (e) { + try { + await driver.switchTo().window(current_handle); + await driver.get(url); + } catch (e) { + let all_handles = await driver.getAllWindowHandles(); + let handle = all_handles[all_handles.length - 1]; + await driver.switchTo().window(handle); + await driver.get(url); + } + } + } else if (option == 2 || option == 7) { + //点击事件 + let xpath = parameters.xpath; + let point = parameters.xpath; + if (xpath.includes("point(")) { + xpath = "//body"; + } + let elementInfo = {iframe: parameters.iframe, xpath: xpath, id: -1}; + if (parameters.useLoop && !parameters.xpath.includes("point(")) { + let parent_node = JSON.parse(msg.message.parentNode); + let parent_xpath = parent_node.parameters.xpath; + if (parent_node.parameters.loopType == 2) { + parent_xpath = parent_node.parameters.pathList + .split("\n")[0] + .trim(); + } + elementInfo.xpath = parent_xpath + elementInfo.xpath; + } + let element = await findElementAcrossAllWindows( + elementInfo, + (notifyBrowser = false) + ); //通过此函数找到元素并切换到对应的窗口 + await execute_js( + parameters.beforeJS, + element, + parameters.beforeJSWaitTime + ); + if (option == 2) { + if (parameters.xpath.includes("point(")) { + await click_element(element, point); + } else { + await click_element(element); + } + let alertHandleType = parameters.alertHandleType; + if (alertHandleType == 1) { + try { + await driver.switchTo().alert().accept(); + } catch (e) { + console.log("No alert"); + } + } else if (alertHandleType == 2) { + try { + await driver.switchTo().alert().dismiss(); + } catch (e) { + console.log("No alert"); + } + } + } else if (option == 7) { + await driver.actions().move({origin: element}).perform(); + } + await execute_js( + parameters.afterJS, + element, + parameters.afterJSWaitTime + ); + send_message_to_browser(JSON.stringify({type: "cancelSelection"})); + } else if (option == 3) { + //提取数据 + notify_browser( + "提示:提取数据操作只能试运行设置的JavaScript语句,且只针对第一个匹配的元素。", + "Hint: can only test JavaScript statement set in the data extraction operation, and only for the first matching element.", + "info" + ); + let params = parameters.params; //所有的提取数据参数 + let not_found_xpaths = []; + for (let i = 0; i < params.length; i++) { + let param = params[i]; + let xpath = param.relativeXPath; + if (param.relative) { + let parent_node = JSON.parse(msg.message.parentNode); + let parent_xpath = parent_node.parameters.xpath; + if (parent_node.parameters.loopType == 2) { + parent_xpath = parent_node.parameters.pathList + .split("\n")[0] + .trim(); + } + xpath = parent_xpath + xpath; + } + let elementInfo = {iframe: param.iframe, xpath: xpath, id: -1}; + let element = await findElementAcrossAllWindows( + elementInfo, + (notifyBrowser = false) + ); + if (element != null) { + await execute_js(param.beforeJS, element, param.beforeJSWaitTime); + await execute_js(param.afterJS, element, param.afterJSWaitTime); + } else { + not_found_xpaths.push(xpath); + } + } + if (not_found_xpaths.length > 0) { + notify_browser( + "无法找到以下元素,请检查XPath是否正确:" + + not_found_xpaths.join("\n"), + "Cannot find the element, please check if the XPath is correct: " + + not_found_xpaths.join("\n"), + "warning" + ); + } + } 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 (//i.test(keyInfo)) { + keyInfo = keyInfo.replace(//gi, ""); + enter = true; + } + if (keyInfo.indexOf("Field(") >= 0 || keyInfo.indexOf("eval(") >= 0) { + //两秒后通知浏览器 + await new Promise((resolve) => setTimeout(resolve, 2000)); + notify_browser( + '检测到文字中包含Field("")或eval(""),试运行时无法输入两项表达式的替换值,请在任务正式运行阶段测试是否有效。', + 'Field("") or eval("") is detected in the text, and the replacement value of the two expressions cannot be entered during trial operation. Please test whether it is valid in the formal call stage.', + "warning" + ); + } + let element = await findElementAcrossAllWindows( + elementInfo, + (notifyBrowser = false) + ); + await execute_js(beforeJS, element, beforeJSWaitTime); + await element.sendKeys( + Key.HOME, + Key.chord(Key.SHIFT, Key.END), + keyInfo + ); + if (enter) { + await element.sendKeys(Key.ENTER); + } + await execute_js(afterJS, element, afterJSWaitTime); + } else if (option == 5) { + //自定义操作的JS代码 + let code = parameters.code; + let codeMode = parameters.codeMode; + let waitTime = parameters.waitTime; + let element = await driver.findElement(By.tagName("body")); + if (codeMode == 0) { + await execute_js(code, element, waitTime); + } else if (codeMode == 8) { + //刷新页面 + try { + await driver.navigate().refresh(); + } catch (e) { + try { + await driver.switchTo().window(current_handle); + await driver.navigate().refresh(); + } catch (e) { + let all_handles = await driver.getAllWindowHandles(); + let handle = all_handles[all_handles.length - 1]; + await driver.switchTo().window(handle); + await driver.navigate().refresh(); + } + } + } + } 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, + (notifyBrowser = false) + ); + execute_js(beforeJS, element, 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; @@ -826,633 +826,636 @@ async function beginInvoke(msg, ws) { 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"); - } - execute_js(afterJS, element, afterJSWaitTime); - } else if (option == 11) { - //单个提取数据参数 - notify_browser( - "提示:提取数据操作只能试运行设置的JavaScript语句,且只针对第一个匹配的元素。", - "Hint: can only test JavaScript statement set in the data extraction operation, and only for the first matching element.", - "info" - ); - let params = parameters.params; //所有的提取数据参数 - let i = parameters.index; - let param = params[i]; - let xpath = param.relativeXPath; - if (param.relative) { - let parent_node = JSON.parse(msg.message.parentNode); - let parent_xpath = parent_node.parameters.xpath; - if (parent_node.parameters.loopType == 2) { - parent_xpath = parent_node.parameters.pathList - .split("\n")[0] - .trim(); + 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"); + } + execute_js(afterJS, element, afterJSWaitTime); + } else if (option == 11) { + //单个提取数据参数 + notify_browser( + "提示:提取数据操作只能试运行设置的JavaScript语句,且只针对第一个匹配的元素。", + "Hint: can only test JavaScript statement set in the data extraction operation, and only for the first matching element.", + "info" + ); + let params = parameters.params; //所有的提取数据参数 + let i = parameters.index; + let param = params[i]; + let xpath = param.relativeXPath; + if (param.relative) { + let parent_node = JSON.parse(msg.message.parentNode); + let parent_xpath = parent_node.parameters.xpath; + if (parent_node.parameters.loopType == 2) { + parent_xpath = parent_node.parameters.pathList + .split("\n")[0] + .trim(); + } + xpath = parent_xpath + xpath; + } + let elementInfo = {iframe: param.iframe, xpath: xpath, id: -1}; + let element = await findElementAcrossAllWindows( + elementInfo, + (notifyBrowser = false) + ); + if (element != null) { + await execute_js(param.beforeJS, element, param.beforeJSWaitTime); + await execute_js(param.afterJS, element, param.afterJSWaitTime); + } + } } - xpath = parent_xpath + xpath; - } - let elementInfo = { iframe: param.iframe, xpath: xpath, id: -1 }; - let element = await findElementAcrossAllWindows( - elementInfo, - (notifyBrowser = false) - ); - if (element != null) { - await execute_js(param.beforeJS, element, param.beforeJSWaitTime); - await execute_js(param.afterJS, element, param.afterJSWaitTime); - } } - } - } - } 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 - // var parameters = [msg.message.id, server_address]; - let parameters = []; - console.log(msg.message); - if ( - msg.message.user_data_folder == null || - msg.message.user_data_folder == undefined || - msg.message.user_data_folder == "" - ) { - parameters = [ - "--ids", - "[" + msg.message.id + "]", - "--server_address", - server_address, - "--user_data", - 0, - ]; - } else { - let user_data_folder_path = path.join( - task_server.getDir(), - msg.message.user_data_folder - ); - parameters = [ - "--ids", - "[" + msg.message.id + "]", - "--server_address", - server_address, - "--user_data", - 1, - ]; - config.user_data_folder = msg.message.user_data_folder; - 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") { - config.mysql_config_path = msg.message.mysql_config_path; - } - fs.writeFileSync( - path.join(task_server.getDir(), "config.json"), - JSON.stringify(config) - ); - // child('Chrome/easyspider_executestage.exe', parameters, function(err,stdout, stderr) { - // console.log(stdout); - // }); + } 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 + // var parameters = [msg.message.id, server_address]; + let parameters = []; + console.log(msg.message); + if ( + msg.message.user_data_folder == null || + msg.message.user_data_folder == undefined || + msg.message.user_data_folder == "" + ) { + parameters = [ + "--ids", + "[" + msg.message.id + "]", + "--server_address", + server_address, + "--user_data", + 0, + ]; + } else { + let user_data_folder_path = path.join( + task_server.getDir(), + msg.message.user_data_folder + ); + parameters = [ + "--ids", + "[" + msg.message.id + "]", + "--server_address", + server_address, + "--user_data", + 1, + ]; + config.user_data_folder = msg.message.user_data_folder; + 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") { + config.mysql_config_path = msg.message.mysql_config_path; + } + fs.writeFileSync( + path.join(task_server.getDir(), "config.json"), + JSON.stringify(config) + ); + // child('Chrome/easyspider_executestage.exe', parameters, function(err,stdout, stderr) { + // console.log(stdout); + // }); - let spawn = require("child_process").spawn; - if ( - process.platform != "darwin" && - msg.message.execute_type == 1 && - msg.message.id != -1 - ) { - let child_process = spawn(execute_path, parameters); - child_process.stdout.on("data", function (data) { - console.log(data.toString()); - }); + let spawn = require("child_process").spawn; + if ( + process.platform != "darwin" && + msg.message.execute_type == 1 && + msg.message.id != -1 + ) { + let child_process = spawn(execute_path, parameters); + child_process.stdout.on("data", function (data) { + console.log(data.toString()); + }); + } + ws.send( + JSON.stringify({ + config_folder: task_server.getDir() + "/", + easyspider_location: task_server.getEasySpiderLocation(), + }) + ); + } else if (msg.type == 6) { + try { + flowchart_window.openDevTools(); + } catch { + console.log("open devtools error"); + } + try { + invoke_window.openDevTools(); + } catch { + console.log("open devtools error"); + } + } else if (msg.type == 7) { + // 获得当前页面Cookies + try { + let cookies = await driver.manage().getCookies(); + console.log("Cookies: ", cookies); + let cookiesText = cookies + .map((cookie) => `${cookie.name}=${cookie.value}`) + .join("\n"); + socket_flowchart.send( + JSON.stringify({type: "GetCookies", message: cookiesText}) + ); + } catch { + console.log("Cannot get Cookies"); + } } - ws.send( - JSON.stringify({ - config_folder: task_server.getDir() + "/", - easyspider_location: task_server.getEasySpiderLocation(), - }) - ); - } else if (msg.type == 6) { - try { - flowchart_window.openDevTools(); - } catch { - console.log("open devtools error"); - } - try { - invoke_window.openDevTools(); - } catch { - console.log("open devtools error"); - } - } else if (msg.type == 7) { - // 获得当前页面Cookies - try { - let cookies = await driver.manage().getCookies(); - console.log("Cookies: ", cookies); - let cookiesText = cookies - .map((cookie) => `${cookie.name}=${cookie.value}`) - .join("\n"); - socket_flowchart.send( - JSON.stringify({ type: "GetCookies", message: cookiesText }) - ); - } catch { - console.log("Cannot get Cookies"); - } - } } async function click_element(element, type = "click") { - try { - if (type == "loopClickEvery") { - await driver - .actions() - .keyDown(Key.CONTROL) - .click(element) - .keyUp(Key.CONTROL) - .perform(); - } else if (type.includes("point(")) { - //point(10, 20)表示点击坐标为(10, 20)的位置 - let point = type.substring(6, type.length - 1).split(","); - let x = parseInt(point[0]); - let y = parseInt(point[1]); - // let actions = driver.actions(); - // await actions.move({origin: element}).perform(); - // await actions.move({x: x, y: y}).perform(); - // await actions.click().perform(); - let script = `document.elementFromPoint(${x}, ${y}).click();`; - await driver.executeScript(script); - } else { - await element.click(); + try { + if (type == "loopClickEvery") { + await driver + .actions() + .keyDown(Key.CONTROL) + .click(element) + .keyUp(Key.CONTROL) + .perform(); + } else if (type.includes("point(")) { + //point(10, 20)表示点击坐标为(10, 20)的位置 + let point = type.substring(6, type.length - 1).split(","); + let x = parseInt(point[0]); + let y = parseInt(point[1]); + // let actions = driver.actions(); + // await actions.move({origin: element}).perform(); + // await actions.move({x: x, y: y}).perform(); + // await actions.click().perform(); + let script = `document.elementFromPoint(${x}, ${y}).click();`; + await driver.executeScript(script); + } else { + await element.click(); + } + } catch (e) { + console.log(e); + await driver.executeScript("arguments[0].click();", element); } - } catch (e) { - console.log(e); - await driver.executeScript("arguments[0].click();", element); - } } async function execute_js(js, element, wait_time = 3) { - let outcome = 0; - if (js.length != 0) { - try { - outcome = await driver.executeScript(js, element); - if (wait_time == 0) { - wait_time = 30000; - } - // await new Promise(resolve => setTimeout(resolve, wait_time)); - } catch (e) { - // await new Promise(resolve => setTimeout(resolve, 2000)); - notify_browser( - "执行JavaScript出错,请检查JavaScript语句是否正确:" + - js + - "\n错误信息:" + - e, - "Error executing JavaScript, please check if the JavaScript statement is correct: " + - js + - "\nError message: " + - e, - "error" - ); - outcome = -1; + let outcome = 0; + if (js.length != 0) { + try { + outcome = await driver.executeScript(js, element); + if (wait_time == 0) { + wait_time = 30000; + } + // await new Promise(resolve => setTimeout(resolve, wait_time)); + } catch (e) { + // await new Promise(resolve => setTimeout(resolve, 2000)); + notify_browser( + "执行JavaScript出错,请检查JavaScript语句是否正确:" + + js + + "\n错误信息:" + + e, + "Error executing JavaScript, please check if the JavaScript statement is correct: " + + js + + "\nError message: " + + e, + "error" + ); + outcome = -1; + } + if (js.indexOf("Field(") >= 0 || js.indexOf("eval(") >= 0) { + //两秒后通知浏览器 + await new Promise((resolve) => setTimeout(resolve, 2000)); + notify_browser( + '检测到JavaScript中包含Field("")或eval(""),试运行时无法执行两项表达式,请在任务正式运行阶段测试是否有效。', + 'Field("") or eval("") is detected in JavaScript, and the two expressions cannot be executed during trial operation. Please test whether it is valid in the formal call stage.', + "warning" + ); + } } - if (js.indexOf("Field(") >= 0 || js.indexOf("eval(") >= 0) { - //两秒后通知浏览器 - await new Promise((resolve) => setTimeout(resolve, 2000)); - notify_browser( - '检测到JavaScript中包含Field("")或eval(""),试运行时无法执行两项表达式,请在任务正式运行阶段测试是否有效。', - 'Field("") or eval("") is detected in JavaScript, and the two expressions cannot be executed during trial operation. Please test whether it is valid in the formal call stage.', - "warning" - ); - } - } - return outcome; + return outcome; } 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, - }) - ); + 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, - }) - ); + 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]); + 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"); -const { copy } = require("selenium-webdriver/io"); -let wss = new WebSocket.Server({ port: websocket_port }); +const {all} = require("express/lib/application"); +const {copy} = require("selenium-webdriver/io"); +let wss = new WebSocket.Server({port: websocket_port}); wss.on("connection", function (ws) { - ws.on("message", async function (message, isBinary) { - let msg = JSON.parse(message.toString()); - // console.log("\n\nGET A MESSAGE: ", msg); - // console.log(msg, msg.type, msg.message); - 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 at time: ", new Date()); - } else if (msg.message.id == 1) { - socket_start = ws; - console.log("set socket_start at time: ", new Date()); - } 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 at time: ", new Date()); - } else { - //其他的ID是用来标识不同的浏览器标签页的 - // await new Promise(resolve => setTimeout(resolve, 200)); - let handles = await driver.getAllWindowHandles(); - if (arrayDifference(handles, old_handles).length > 0) { - old_handles = handles; - current_handle = handles[handles.length - 1]; - await driver.switchTo().window(current_handle); - console.log( - "New tab opened, change current_handle to: ", - current_handle - ); - // 调整浏览器窗口大小,不然扩展会白屏 - let size = await driver.manage().window().getRect(); - let width = size.width; - let height = size.height; - await driver - .manage() - .window() - .setRect({ width: width, height: height + 10 }); - // height = height - 1; - await driver - .manage() - .window() - .setRect({ width: width, height: height }); + ws.on("message", async function (message, isBinary) { + let msg = JSON.parse(message.toString()); + // console.log("\n\nGET A MESSAGE: ", msg); + // console.log(msg, msg.type, msg.message); + 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 at time: ", new Date()); + } else if (msg.message.id == 1) { + socket_start = ws; + console.log("set socket_start at time: ", new Date()); + } 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 at time: ", new Date()); + } else { + //其他的ID是用来标识不同的浏览器标签页的 + // await new Promise(resolve => setTimeout(resolve, 200)); + let handles = await driver.getAllWindowHandles(); + if (arrayDifference(handles, old_handles).length > 0) { + old_handles = handles; + current_handle = handles[handles.length - 1]; + await driver.switchTo().window(current_handle); + console.log( + "New tab opened, change current_handle to: ", + current_handle + ); + // 调整浏览器窗口大小,不然扩展会白屏 + let size = await driver.manage().window().getRect(); + let width = size.width; + let height = size.height; + await driver + .manage() + .window() + .setRect({width: width, height: height + 10}); + // height = height - 1; + await driver + .manage() + .window() + .setRect({width: width, height: height}); + } + await new Promise((resolve) => setTimeout(resolve, 2000)); + 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}}) + ); + allWindowSockets.push(ws); + allWindowScoketNames.push(msg.message.id); + console.log( + "set socket for id: ", + msg.message.id, + " at time: ", + new Date() + ); + ws.on("close", async function (event) { + let index = allWindowSockets.indexOf(ws); + if (index > -1) { + allWindowSockets.splice(index, 1); + allWindowScoketNames.splice(index, 1); + } + let handles = await driver.getAllWindowHandles(); + if (handles.length < old_handles.length) { + old_handles = handles; + current_handle = handles[handles.length - 1]; + await driver.switchTo().window(current_handle); + console.log( + "Current tab closed, change current_handle to: ", + current_handle + ); + } + console.log( + "socket for id: ", + msg.message.id, + " closed at time: ", + new Date() + ); + }); + // 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 != "" + ) { + await driver.switchTo().window(leave_handle); + console.log("Switch to handle: ", leave_handle); + current_handle = leave_handle; + } + } else { + await beginInvoke(msg, ws); } - await new Promise((resolve) => setTimeout(resolve, 2000)); - 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 } }) - ); - allWindowSockets.push(ws); - allWindowScoketNames.push(msg.message.id); - console.log( - "set socket for id: ", - msg.message.id, - " at time: ", - new Date() - ); - ws.on("close", async function (event) { - let index = allWindowSockets.indexOf(ws); - if (index > -1) { - allWindowSockets.splice(index, 1); - allWindowScoketNames.splice(index, 1); - } - let handles = await driver.getAllWindowHandles(); - if (handles.length < old_handles.length) { - old_handles = handles; - current_handle = handles[handles.length - 1]; - await driver.switchTo().window(current_handle); - console.log( - "Current tab closed, change current_handle to: ", - current_handle - ); - } - console.log( - "socket for id: ", - msg.message.id, - " closed at time: ", - new Date() - ); - }); - // 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 != "" - ) { - await driver.switchTo().window(leave_handle); - console.log("Switch to handle: ", leave_handle); - current_handle = leave_handle; - } - } else { - await beginInvoke(msg, ws); - } - }); + }); }); console.log(process.platform); async function runBrowser(lang = "en", user_data_folder = "", mobile = false) { - const serviceBuilder = new ServiceBuilder(driverPath); - let options = new chrome.Options(); - options.addArguments("--disable-blink-features=AutomationControlled"); - options.addArguments("--disable-infobars"); - // 添加实验性选项以排除'enable-automation'开关 - options.set("excludeSwitches", ["enable-automation"]); - options.excludeSwitches("enable-automation"); + const serviceBuilder = new ServiceBuilder(driverPath); + let options = new chrome.Options(); + options.addArguments("--disable-blink-features=AutomationControlled"); + options.addArguments("--disable-infobars"); + // 添加实验性选项以排除'enable-automation'开关 + options.set("excludeSwitches", ["enable-automation"]); + options.excludeSwitches("enable-automation"); - // 添加实验性选项来禁用自动化扩展 - options.set("useAutomationExtension", false); - // options.addArguments('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36'); - options.set; - language = lang; - if (lang == "en") { - options.addExtensions(path.join(__dirname, "EasySpider_en.crx")); - } else if (lang == "zh") { - options.addExtensions(path.join(__dirname, "EasySpider_zh.crx")); - } - options.addExtensions(path.join(__dirname, "XPathHelper.crx")); - options.setChromeBinaryPath(chromeBinaryPath); - - if (user_data_folder != "") { - let dir = path.join(task_server.getDir(), user_data_folder); - console.log(dir); - options.addArguments("--user-data-dir=" + dir); - config.user_data_folder = user_data_folder; - config_context.user_data_folder = user_data_folder; - fs.writeFileSync( - path.join(task_server.getDir(), "config.json"), - JSON.stringify(config) - ); - } else { - config_context.user_data_folder = ""; - } - if (mobile) { - const mobileEmulation = { - deviceName: "iPhone XR", - }; - options.addArguments( - `--user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"` - ); - options.setMobileEmulation(mobileEmulation); - } - driver = new Builder() - .forBrowser("chrome") - .setChromeOptions(options) - .setChromeService(serviceBuilder) - .build(); - await driver - .manage() - .setTimeouts({ implicit: 3, pageLoad: 10000, script: 10000 }); - await driver.executeScript( - "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})" - ); - // await driver.executeScript("localStorage.clear();"); //重置参数数量 - const cdpConnection = await driver.createCDPConnection("page"); - let stealth_path = path.join(__dirname, "stealth.min.js"); - let stealth = fs.readFileSync(stealth_path, "utf8"); - await cdpConnection.execute("Page.addScriptToEvaluateOnNewDocument", { - source: stealth, - }); - if (config_context.user_data_folder == "") { - //调整浏览器窗口大小 - let size = await driver.manage().window().getRect(); - let width = size.width; - let height = size.height; - await driver - .manage() - .window() - .setRect({ width: width * 1.2, height: height }); - } - try { - 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 - ); + // 添加实验性选项来禁用自动化扩展 + options.set("useAutomationExtension", false); + // options.addArguments('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36'); + options.set; + language = lang; + if (lang == "en") { + options.addExtensions(path.join(__dirname, "EasySpider_en.crx")); + } else if (lang == "zh") { + options.addExtensions(path.join(__dirname, "EasySpider_zh.crx")); + } + options.addExtensions(path.join(__dirname, "XPathHelper.crx")); + options.setChromeBinaryPath(chromeBinaryPath); + + if (user_data_folder != "") { + let dir = path.join(task_server.getDir(), user_data_folder); + console.log(dir); + options.addArguments("--user-data-dir=" + dir); + config.user_data_folder = user_data_folder; + config_context.user_data_folder = user_data_folder; + fs.writeFileSync( + path.join(task_server.getDir(), "config.json"), + JSON.stringify(config) + ); + } else { + config_context.user_data_folder = ""; + } + if (mobile) { + const mobileEmulation = { + deviceName: "iPhone XR", + }; + options.addArguments( + `--user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"` + ); + options.setMobileEmulation(mobileEmulation); + } + driver = new Builder() + .forBrowser("chrome") + .setChromeOptions(options) + .setChromeService(serviceBuilder) + .build(); + await driver + .manage() + .setTimeouts({implicit: 3, pageLoad: 10000, script: 10000}); + await driver.executeScript( + "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})" + ); + // await driver.executeScript("localStorage.clear();"); //重置参数数量 + const cdpConnection = await driver.createCDPConnection("page"); + let stealth_path = path.join(__dirname, "stealth.min.js"); + let stealth = fs.readFileSync(stealth_path, "utf8"); + await cdpConnection.execute("Page.addScriptToEvaluateOnNewDocument", { + source: stealth, + }); + if (config_context.user_data_folder == "") { + //调整浏览器窗口大小 + let size = await driver.manage().window().getRect(); + let width = size.width; + let height = size.height; + await driver + .manage() + .window() + .setRect({width: width * 1.2, height: height}); + } + try { + 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 + ); + } + old_handles = await driver.getAllWindowHandles(); + current_handle = old_handles[old_handles.length - 1]; + } finally { + // await driver.quit(); // 退出浏览器 } - old_handles = await driver.getAllWindowHandles(); - current_handle = old_handles[old_handles.length - 1]; - } finally { - // await driver.quit(); // 退出浏览器 - } } function handleOpenBrowser( - event, - lang = "en", - user_data_folder = "", - mobile = false + event, + lang = "en", + user_data_folder = "", + mobile = false ) { - const webContents = event.sender; - const win = BrowserWindow.fromWebContents(webContents); - runBrowser(lang, user_data_folder, mobile); - let size = screen.getPrimaryDisplay().workAreaSize; - let width = parseInt(size.width); - let height = parseInt(size.height * 0.5); - flowchart_window = new BrowserWindow({ - x: 0, - y: 0, - width: width, - height: height, - icon: iconPath, - maximizable: true, - resizable: true, - }); - let url = ""; - let id = -1; - 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(); - } - // and load the index.html of the app. - flowchart_window.loadURL(url, { extraHeaders: "pragma: no-cache\n" }); - if (process.platform != "darwin") { - flowchart_window.hide(); - } - flowchart_window.on("close", function (event) { - mainWindow.show(); - driver.quit(); - }); + const webContents = event.sender; + const win = BrowserWindow.fromWebContents(webContents); + runBrowser(lang, user_data_folder, mobile); + let size = screen.getPrimaryDisplay().workAreaSize; + let width = parseInt(size.width); + let height = parseInt(size.height * 0.5); + flowchart_window = new BrowserWindow({ + x: 0, + y: 0, + width: width, + height: height, + icon: iconPath, + maximizable: true, + resizable: true, + }); + let url = ""; + let id = -1; + 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(); + } + // and load the index.html of the app. + flowchart_window.loadURL(url, {extraHeaders: "pragma: no-cache\n"}); + if (process.platform != "darwin") { + flowchart_window.hide(); + } + flowchart_window.on("close", function (event) { + mainWindow.show(); + driver.quit(); + }); } function handleOpenInvoke(event, lang = "en") { - invoke_window = new BrowserWindow({ icon: iconPath }); - let url = ""; - language = lang; - if (lang == "en") { - url = - server_address + - `/taskGrid/taskList.html?type=1&wsport=${websocket_port}&backEndAddressServiceWrapper=` + - server_address; - } else if (lang == "zh") { - 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.maximize(); - mainWindow.hide(); - invoke_window.on("close", function (event) { - mainWindow.show(); - }); + invoke_window = new BrowserWindow({icon: iconPath}); + let url = ""; + language = lang; + if (lang == "en") { + url = + server_address + + `/taskGrid/taskList.html?type=1&wsport=${websocket_port}&backEndAddressServiceWrapper=` + + server_address; + } else if (lang == "zh") { + 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.maximize(); + mainWindow.hide(); + invoke_window.on("close", function (event) { + mainWindow.show(); + }); } // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.whenReady().then(() => { - session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => { - details.requestHeaders["Accept-Language"] = "zh"; - callback({ cancel: false, requestHeaders: details.requestHeaders }); - }); - ipcMain.on("start-design", handleOpenBrowser); - ipcMain.on("start-invoke", handleOpenInvoke); - ipcMain.on("accept-agreement", function (event, arg) { - config.copyright = 1; - fs.writeFileSync( - path.join(task_server.getDir(), "config.json"), - JSON.stringify(config) - ); - }); - createWindow(); - - app.on("activate", function () { - // On MacOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } - }); - // 获取Chrome版本 - execFile(chromeBinaryPath, ["--version"], (error, chromeStdout) => { - if (error) { - dialog.showErrorBox("Chrome Error", "Failed to retrieve Chrome version."); - return; - } - - // Chrome的版本输出通常是 "Google Chrome xx.x.xxx.x" - const chromeVersionMatch = chromeStdout.match(/\d+/); - if (!chromeVersionMatch) { - dialog.showErrorBox("Chrome Error", "Unable to parse Chrome version."); - return; - } else { - console.log("\n\n\nChrome version: ", chromeVersionMatch[0]); - } - const chromeVersion = chromeVersionMatch[0]; - - // 获取ChromeDriver版本 - execFile(driverPath, ["--version"], (error, chromedriverStdout) => { - if (error) { - dialog.showErrorBox( - "ChromeDriver Error", - "Failed to retrieve ChromeDriver version." - ); - return; - } else { - console.log("\n\n\nChromeDriver version: ", chromedriverStdout); - } - - // ChromeDriver的版本输出通常是 "ChromeDriver xx.x.xxx.x (更多信息)" - const chromedriverVersionMatch = - chromedriverStdout.match(/\d+\.\d+\.\d+\.\d+/); - if (!chromedriverVersionMatch) { - dialog.showErrorBox( - "ChromeDriver Error", - "Unable to parse ChromeDriver version." - ); - return; - } - const chromedriverVersion = chromedriverVersionMatch[0]; - - // 检查主版本号是否匹配 - if (chromeVersion.split(".")[0] !== chromedriverVersion.split(".")[0]) { - dialog.showErrorBox( - "ChromeDriver版本不匹配|ChromeDriver Version Mismatch", - ` Chrome的版本(${chromeVersion})与ChromeDriver的版本(${chromedriverVersion})不匹配,软件将无法正常使用。请阅读文件夹下的“浏览器闪退解决方案.txt”升级ChromeDriver到${chromeVersion}.*版本以正常使用软件。\n\nThe version of Chrome (${chromeVersion}) does not match the version of ChromeDriver (${chromedriverVersion}), this will cause the software to be unable to run normally. Please read the "If Chrome exits when desigining a task.txt" in the folder to upgrade ChromeDriver to ${chromeVersion}.* version to use the software normally.` - ); - } else { - // 版本匹配,继续应用流程 - } + session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => { + details.requestHeaders["Accept-Language"] = "zh"; + callback({cancel: false, requestHeaders: details.requestHeaders}); }); - }); + ipcMain.on("start-design", handleOpenBrowser); + ipcMain.on("start-invoke", handleOpenInvoke); + ipcMain.on("accept-agreement", function (event, arg) { + config.copyright = 1; + fs.writeFileSync( + path.join(task_server.getDir(), "config.json"), + JSON.stringify(config) + ); + }); + createWindow(); + + app.on("activate", function () { + // On MacOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } + }); + if (process.platform === "darwin") { + // 获取Chrome版本 + execFile(chromeBinaryPath, ["--version"], (error, chromeStdout) => { + if (error) { + dialog.showErrorBox("Chrome Error", "Failed to retrieve Chrome version."); + return; + } + + // Chrome的版本输出通常是 "Google Chrome xx.x.xxx.x" + const chromeVersionMatch = chromeStdout.match(/\d+/); + if (!chromeVersionMatch) { + dialog.showErrorBox("Chrome Error", "Unable to parse Chrome version."); + return; + } else { + console.log("\n\n\nChrome version: ", chromeVersionMatch[0]); + } + const chromeVersion = chromeVersionMatch[0]; + + // 获取ChromeDriver版本 + execFile(driverPath, ["--version"], (error, chromedriverStdout) => { + if (error) { + dialog.showErrorBox( + "ChromeDriver Error", + "Failed to retrieve ChromeDriver version." + ); + return; + } else { + console.log("\n\n\nChromeDriver version: ", chromedriverStdout); + } + + // ChromeDriver的版本输出通常是 "ChromeDriver xx.x.xxx.x (更多信息)" + const chromedriverVersionMatch = + chromedriverStdout.match(/\d+\.\d+\.\d+\.\d+/); + if (!chromedriverVersionMatch) { + dialog.showErrorBox( + "ChromeDriver Error", + "Unable to parse ChromeDriver version." + ); + return; + } + const chromedriverVersion = chromedriverVersionMatch[0]; + + // 检查主版本号是否匹配 + if (chromeVersion.split(".")[0] !== chromedriverVersion.split(".")[0]) { + dialog.showErrorBox( + "ChromeDriver版本不匹配|ChromeDriver Version Mismatch", + ` Chrome的版本(${chromeVersion})与ChromeDriver的版本(${chromedriverVersion})不匹配,软件将无法正常使用。请阅读文件夹下的“浏览器闪退解决方案.txt”升级ChromeDriver到${chromeVersion}.*版本以正常使用软件。\n\nThe version of Chrome (${chromeVersion}) does not match the version of ChromeDriver (${chromedriverVersion}), this will cause the software to be unable to run normally. Please read the "If Chrome exits when desigining a task.txt" in the folder to upgrade ChromeDriver to ${chromeVersion}.* version to use the software normally.` + ); + } else { + // 版本匹配,继续应用流程 + } + }); + }); + } + }); // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on("window-all-closed", function () { - if (process.platform !== "darwin") { - app.quit(); - } + if (process.platform !== "darwin") { + app.quit(); + } }); // In this file you can include the rest of your app's specific main process // code. You can also put them in separate files and require them here. function arrayDifference(arr1, arr2) { - return arr1.filter((item) => !arr2.includes(item)); + return arr1.filter((item) => !arr2.includes(item)); }