java浏览器控件jxbrowser(简单demo模拟自动登录与点击)
写在前面:
老大让我写个脚本自动给他写dms有一段时间了,说实话当时不知道老大指的这个脚本是什么?毕竟是做web的,难道是写个数据库sql语句脚本吗?也就放在了一边。巧了,最近一个朋友说他之前写了个程式,我就问了一下。哇,这不正是我想要的!他是做了一个可以自动登录网站,然后自动填写日报的程式。看了之后感觉很棒,于是请教了一下。
朋友的程式是用的c#做的,然后内嵌了一个浏览器控件webbrowser。一下子恍然大悟,还可以这么玩。平时工作也没有接触到浏览器控件,于是赶紧去搜索java的浏览器控件。然后最后也花了点时间,还好,马马虎虎的完成了任务。
思路:
使用javase做一个桌面应用程序,弹出一个框,然后里面内嵌一个浏览器,可以模拟自动登录网站,并可以自动填写日报,达到想要的效果。
对于使用java弹出一个应用框是很好实现的,使用JFrame来实现就好了,主要是如何在弹出框里面内嵌一个浏览器?
首先百度,java浏览器控件,出来的就是jxbrowser,于是去查资料了解
想要做一个自动登录网站的应用,使用javase,内嵌一个浏览器是很好的选择。这样就避免了一些cookie之类的设置。
jxbrowser是什么?
jxbrowser是一个java浏览器控件,是基于chromium内核的。(如果要自动登录的系统是适应ie浏览器的,那么有可能使用此款浏览器控件,在有些功能上不兼容适用。这里稍微注意下,以免踩坑)
如何使用?
首先去下载,http://www.pc0359.cn/downinfo/95385.html,下载下来后进行解压
对于如何破解,可以参考对应的资料,https://blog.csdn.net/Jumenglo/article/details/79459102
下面简单看下项目的破解步骤:
1.创建java项目,导入相关的jxbrowser需要的jar包,(在解压的目录下就可以复制);然后在解压文件里找对对应的demo,复制META-INF文件夹(证书),到自己的项目目录下。然后这个时候如果对应的证书的期限到了,是无法使用的,所以要破解。
2.打开证书teamdev.licenses,直接复制下面的代码,即可。
Product: JxBrowser
Version: 6.x
Licensed to:
License type: Enterprise
License info: JxBrowser Demo License
Expiration date: 01-01-9999
Support expiration date: NO SUPPORT
Generation date: 01-01-9999
Platforms: win32/x86;win32/x64;mac/x86;mac/x64;linux/x86;linux/x64
Company name: TeamDev Ltd.
SigB: 1
SigA: 1
3.在代码中添加破解的代码块
/*破解jxbrowser的代码块 导入下面的包是关键 * import com.teamdev.jxbrowser.chromium.ba; * */ static { try { Field e = ba.class.getDeclaredField("e"); e.setAccessible(true); Field f = ba.class.getDeclaredField("f"); f.setAccessible(true); Field modifersField = Field.class.getDeclaredField("modifiers"); modifersField.setAccessible(true); modifersField.setInt(e, e.getModifiers() & ~Modifier.FINAL); modifersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); e.set(null, new BigInteger("1")); f.set(null, new BigInteger("1")); modifersField.setAccessible(false); } catch (Exception e1) { e1.printStackTrace(); } }
注意,此时添加代码块后,可能找不到ba,因为还需要导入对应的包,这里我导入的是import com.teamdev.jxbrowser.chromium.ba; 有可能jxbrowser的版本不同,这里导入的包也不同,即使用的ba的名字会有变化,这里可以在网上查看下,这里我的版本是6.21。
此时,不出意外就已经破解好了,可以开始编码了。然后这里我做的是程序启动,弹出一个框,框里内嵌了jxbrowser浏览器,然后会打开一个网站系统,实现自动登录并填写东西,并提交。(这里我的系统是公司内部系统,如果要做其他的仿照即可,大概思路与原理是一个样子的)
下面直接上代码:
import com.teamdev.jxbrowser.chromium.Browser; import com.teamdev.jxbrowser.chromium.ba; import com.teamdev.jxbrowser.chromium.dom.*; import com.teamdev.jxbrowser.chromium.events.FinishLoadingEvent; import com.teamdev.jxbrowser.chromium.events.LoadAdapter; import com.teamdev.jxbrowser.chromium.swing.BrowserView; import javax.swing.*; import java.awt.*; import java.io.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.math.BigInteger; import java.util.List; import java.util.Properties; /** * Description:PACKAGE_NAME * Author: Eleven * Date: 2019/1/9 9:15 */ public class Demo { /*破解jxbrowser的代码块 导入下面的包是关键 * import com.teamdev.jxbrowser.chromium.ba; * */ static { try { Field e = ba.class.getDeclaredField("e"); e.setAccessible(true); Field f = ba.class.getDeclaredField("f"); f.setAccessible(true); Field modifersField = Field.class.getDeclaredField("modifiers"); modifersField.setAccessible(true); modifersField.setInt(e, e.getModifiers() & ~Modifier.FINAL); modifersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); e.set(null, new BigInteger("1")); f.set(null, new BigInteger("1")); modifersField.setAccessible(false); } catch (Exception e1) { e1.printStackTrace(); } } /*正式程序编写*/ private static InputStream in = null; private static Properties properties =new Properties(); ///累计加载的次数 static int num = 0; public static void main(String[] args) { File directory = new File("");// 参数为空,获取所在的路径 String courseFile = ""; try { //加载读取config.properties文件,配置文件主要存放了一些登陆用户名与密码还有一些其他的参数设置 /*获取项目的根路径,因为这里我是将配置文件与项目放在同级的*/ courseFile = directory.getCanonicalPath(); System.out.println(courseFile); String configPath = courseFile+"/config.properties"; in = new BufferedInputStream(new FileInputStream(configPath)); properties.load(new InputStreamReader(in, "UTF-8")); } catch (IOException e) { e.printStackTrace(); } /*系统的访问地址*/ final String url = "http://10.202.10.94/DMS/index.jsp"; final String title = "DMS"; Browser browser = new Browser(); BrowserView view = new BrowserView(browser); /*窗口制作,设置相关的属性*/ JFrame frame = new JFrame("DMS自动-V1.0"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //不显示标题栏,最大化,最小化,退出按钮 frame.setSize(600, 500); frame.add(view, BorderLayout.CENTER); frame.setLocationRelativeTo(null); frame.setVisible(true); /*使用浏览器控件加载访问系统网站地址*/ browser.loadURL(url); /*添加一个完成加载的事件:这里当每次加载一个新的页面的时候(browser.loadURL(...)),都会进来此方法*/ browser.addLoadListener(new LoadAdapter() { @Override public void onFinishLoadingFrame(FinishLoadingEvent event) { if (event.isMainFrame()) { /*因为当加载新的页面时,都会进来此方法,所以,这里要用数字做一个判断,判断是哪个页面,第几次加载,根据自己的需求来*/ if(num == 0){ DOMDocument doc = event.getBrowser().getDocument(); /*找到页面name为personcode的对象,并给它设置值*/ DOMElement username = doc.findElement(By.name("personcode")); //找到对应的输入框元素(这里的By类提供了多种查找的方式) /*这里我设置的值是从配置文件中加载的,这里可以直接设置也可以*/ username.setAttribute("value", properties.getProperty("personcode")); //在输入框中输入内容 DOMElement password = doc.findElement(By.name("password")); password.setAttribute("value",properties.getProperty("password")); /*找到页面name为Submit的按钮,然后模拟点击*/ DOMElement loginBtn = doc.findElement(By.name("Submit")); loginBtn.click();//模拟点击 num++; }else if(num == 1){ Browser browser1 = event.getBrowser(); //模拟跳转到点击input Daily Record后的页面 browser1.loadURL("http://10.202.10.94/DMS/dailyreport/dailyRecordMaintain.jsp"); num++; }else if(num == 2){ DOMDocument doc = event.getBrowser().getDocument(); /*找到页面指定id的下拉框*/ DOMSelectElement dDateFrom = (DOMSelectElement) doc.findElement(By.id("dDateFrom")); DOMSelectElement dDateTo = (DOMSelectElement) doc.findElement(By.id("dDateTo")); /*获取下拉框的options集合*/ List<DOMOptionElement> optionElementList = dDateFrom.getOptions(); List<DOMOptionElement> optionElementList2 = dDateTo.getOptions(); for(DOMOptionElement opt:optionElementList){ /*模拟下拉框选中时间*/ if(opt.getAttribute("value").equals(properties.getProperty("startTime"))){ opt.setSelected(true); } } for(DOMOptionElement opt:optionElementList2){ /*模拟下拉框选中时间*/ if(opt.getAttribute("value").equals(properties.getProperty("endTime"))){ opt.setSelected(true); } } /*由于dms系统是兼容ie的,在谷歌上点击对应的study按钮是没有反应的,故这里直接使用给iframe设置src的方式来模拟用户点击study按钮*/ DOMFrameElement workitemFrame = (DOMFrameElement) doc.findElement(By.name("workitem")); String tempSrc = workitemFrame.getAttribute("src"); workitemFrame.setAttribute("src","http://10.202.10.94/DMS/dailyreport/addStudyRecordInformation.jsp"); /*特别特别要注意!!!有可能父页面加载子iframe加载完成需要一定的时间,故需要做延迟,特别注意,别踩坑!!!! * 刚开始获取不到,还以为自己写的问题!!!!! * */ /*这里要延迟,不然后面可能无法获取到对应的组件元素*/ try { Thread.sleep(1000*1); } catch (InterruptedException e) { e.printStackTrace(); } DOMDocument wkDocument = workitemFrame.getContentDocument(); DOMElement workitemname = wkDocument.findElement(By.name("workitemname")); DOMElement content = wkDocument.findElement(By.name("content")); workitemname.setAttribute("value",properties.getProperty("workitemname")); content.setTextContent(properties.getProperty("content")); //模拟点击提交 DOMElement b_save = wkDocument.findElement(By.name("b_save")); b_save.click(); num++; }else if(num == 3){ //System.out.println("到这里了"); } } } }); } }
下面是我自己的配置文件,这个根据自己的需求就好了:
代码中注释已经写得很清楚了,应该大概都可以看得懂把~~~~~~~。
这里还是要提及一下,一定要注意,当页面有子页面iframe,加载iframe设置的时候,有的页面加载需要一定的时间,故需要做一定的延迟!!!不然无法获取到加载页面的元素,这里一定要注意,至于需要延迟多久,就需要自己测试一下子!
到这里程序就写完了,然后我们可以将项目打成jar包,然后使用exe4j打成exe可执行文件。这样子就方便多啦。对于如何打成jar包以及如果使用exe4j,就不多说了,可以网上参考相关的资料。
对了,如果需要知道更多有关jxbrowser的一些方法事件,可以去解压文件里找到api文档,不过是全英文的。
还有要稍微注意下,使用exe4j生成的可执行程式后,需要配置对应的EXE4J_JAVA_HOME环境变量,不然会报错的。
参考博客:
http://ciika.com/2018/05/java-jxbrowser-helloworld/--------JxBrowser的初步使用和证书
https://www.cnblogs.com/chevin/p/10029256.html------JxBrowser之二:常用函数addLoadListener
https://blog.csdn.net/weixin_42273374/article/details/80405456------properties文件第一行获取的值为null
https://blog.csdn.net/qq_30730419/article/details/78041133------No JVM could be found on your system.please define ESE4J_JAVA_HOME to point to an installed 32-bit o
https://blog.csdn.net/zzzgd_666/article/details/80757194------exe4j打成的exe文件运行时弹窗this executable was created with an evaluation version of exe4j问题解决