首页 > 编程语言 >java+selenium+autoIt 实现下载(打印)功能

java+selenium+autoIt 实现下载(打印)功能

时间:2024-07-09 17:43:00浏览次数:18  
标签:exe 浏览器 driver selenium robot autoIt java 窗口

java+selenium+autoIt 实现下载(打印)功能

selenium是一个开源的自动化测试框架,它可以模拟用户对浏览器的操作,进行自动化的测试。但是,它不仅仅只能用来做测试。

AutoIt 是一个使用类似BASIC脚本语言免费软件,它设计用于Windows GUI(图形用户界面)中进行自动化操作。它利用模拟键盘按键,鼠标移动和窗口/控件的组合来实现自动化任务。而这是其它语言不可能做到或无可靠方法实现的(例如VBScriptSendKeys)。在这个项目中AutoIt 主要用于在浏览器中点击下载后,保存文件时,对windos弹框进行操作。

因为业务需求,需要把一个html网页转化成PDF,本来准备考虑用iText来对html转为PDF,但是我们已经拥有html的网页了,用iText感觉太麻烦,然后又找了一个第三方html->pdf,结果需要收费等一些其它原因,最终决定采用selenium+chrome+java+autol对网页进行导出PDF。

即使这个是打印成PDF,也可用于下载

环境:springboot v2.1.2 + maven + selenium 3.141.59 + chrome 71.0.3578.98

1 selenium

1.1 关于selenium

selenium是一个自动化测试框架,可以模拟用户的浏览器操作,可以和几门热门的语言相结合,例如java,python,接下来我将使用selenuim来操作chrome来模拟用户将网页保存为PDF。

1.2 selenium连接chrome

1.2.1 添加selenium的jar包
				<!-- Selenium dependency -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-server</artifactId>
            <version>3.141.59</version>
        </dependency>
1.2.2 下载谷歌浏览器驱动

谷歌浏览器驱动下载

因为我用的是最新的chrome,所以下载的也是暂时最新的驱动,每个驱动对应的谷歌浏览器版本也不一样,你们可以查看相应的文档,查看自己所对应的驱动

下载完驱动之后,将驱动放置于resource目录下的driver文件夹内

1.2.3 加载WebDriver

    /*获取浏览器的连接*/
    public static WebDriver openAccess() {

        //在idea运行的谷歌驱动路径
        System.setProperty("webdriver.chrome.driver",
                "src/main/resources/driver/chromedriver.exe");
        //打jar包后的谷歌驱动路径
		/*String driverPath = System.getProperty("user.dir")+File.separator+"driver"+ File.separator+"chromedriver.exe";*/
        HashMap<String, Object> chromePrefs = new HashMap<>();
        chromePrefs
                .put("profile.default_content_settings.popups", 0);//设置为禁止弹出下载窗口
        chromePrefs
                .put("download.default_directory", downloadFilepath);//设置为文件下载路径
        ChromeOptions options = new ChromeOptions();
        HashMap<String, Object> chromeOptionsMap = new HashMap<>();
        options.setExperimentalOption("prefs", chromePrefs);
        options.addArguments("--test-type");
        options.addArguments("disable-infobars");//取消Chrome正在受到自动测试软件的控制
       /*
        用户浏览器地址,用于加载浏览器的用户信息,
        这一步将增加浏览器的性能消耗,
        如果不加这一行,浏览器默认已访客模式进入浏览器,
        可根据自己的需求来选择是否使用
         */
        options.addArguments("user-data-dir=C:\\Users\\onegene\\AppData\\Local\\Google\\Chrome\\User Data");
        DesiredCapabilities cap = DesiredCapabilities.chrome();
        cap.setCapability(ChromeOptions.CAPABILITY, chromeOptionsMap);
        cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
        cap.setCapability(ChromeOptions.CAPABILITY, options);
        WebDriver driver = null;
        boolean flag = true;
        while (flag) {
            try {
                flag = false;
                driver = new ChromeDriver(cap);
                //响应时间超过8秒,则重新开启浏览器连接
                driver.manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS);
                driver.manage().window().maximize();
//                driver.get(url);

            } catch (Exception e) {
                flag = true;
                if (driver != null) {
                    driver.quit();
                }
                log.info("wait for connection browser ");
            }
        }
        return driver;
    }

System.setProperty("webdriver.chrome.driver","src/main/resources/driver/chromedriver.exe");这一步用于在IDEA中运行的是否加载驱动,如果,打成jar包之后,加载驱动的话,应该用下面一行加载驱动,驱动放在与jar包同目录的dreiver目录下

String driverPath = System.getProperty("user.dir")+File.separator+"driver"+ File.separator+"chromedriver.exe";
System.setProperty("webdriver.chrome.driver",driverPath);

options.addArguments("user-data-dir=" + DriverPathUtils.getChromePath());用户浏览器地址,用于加载浏览器的用户信息,这一步将增加浏览器的性能消耗,如果不加这一行,浏览器默认已访客模式进入浏览器,可根据自己的需求来选择是否使用

1.3 加载url,进行元素操作

        webDriver.get(url);//自己定义
        Thread.sleep(1000);
				//根绝class寻找元素,并且点击
        WebElement addpBtn = webDriver.findElement(By.className("addp"));
        addpBtn.click();

        Thread.sleep(1000);
				//根据id寻找元素,并且点击
        WebElement genLayoutBtn = webDriver.findElement(By.id("genLayout"));
        genLayoutBtn.click();

注:selenium切换tab,并且关闭

String currentWin = webDriver.getWindowHandle();
Set<String> handles = webDriver.getWindowHandles();
for (String handle : handles) {
   if (currentWin.equals(handle)) continue;
   webDriver = webDriver.switchTo().window(handle);
}
webDriver.close();

1.4调起打印事件

调起如下的谷歌浏览器打印事件

1705566125502.png

调起浏览器的打印事件有以下两种方法:

① 点击鼠标右键,然后点击打印按钮

②按住键盘的Ctrl+P

显而易见,第②中方法更实用,所以我们采用第②种

我查看了selenium的键盘事件,发现是有键盘事件的,调起方法如下:

Actions action = new Actions(driver); 
action.keyDown(Keys.CONTROL);// 按下 Ctrl 键
action.sednKeys("p")//按下P键
action.keyUp(Keys.CONTROL);// 释放 Ctrl 键
action.perform()//发送组合按键

本来以为操作键盘的方法很简单,但是不知道为啥chrome一直无法调起键盘事件,谷歌了很久,也没有找到原因,网上也有很多人说无法调起。于是查看jdk文档,发现java提供了一个操作键盘事件的类。如下

1705566183887.png

所以,我就用以下方法来实现键盘事件Ctrl+P

        Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_CONTROL);
        robot.keyPress(KeyEvent.VK_P);
        robot.keyRelease(KeyEvent.VK_P);
        robot.keyRelease(KeyEvent.VK_CONTROL);

本以为事情终于解决了,然后才发现,SpringBoot无法启动这个键盘事件,百度之后,才发现有两种实现的办法

①启动SpringBoot钱,给虚拟机添加参数-ea -Djava.awt.headless=false

②在SpringBoot启动类中添加代码,开启awt

public static void main(String[] args) {
		System.setProperty("java.awt.headless", "false");
		SpringApplication.run(SeleniumApplication.class, args);
}

1.5 进入保存界面

打印界面进入保存界面只需要按下回车键,所以只需按照上一步操作键盘点击回车键就好了

		Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_CONTROL);
        robot.keyPress(KeyEvent.VK_P);
        robot.keyRelease(KeyEvent.VK_P);
        robot.keyRelease(KeyEvent.VK_CONTROL);

		//睡眠7S,因为谷歌浏览器进入打印要先进行渲染,这个需要一段时间
        Thread.sleep(7000);
        robot.keyPress(KeyEvent.VK_ENTER);
        robot.keyRelease(KeyEvent.VK_ENTER);

2 autolt

AutoIt 目前最新是v3版本,这是一个使用类似BASIC脚本语言免费软件,它设计用于Windows GUI(图形用户界面)中进行自动化操作。它利用模拟键盘按键,鼠标移动和窗口/控件的组合来实现自动化任务。而这是其它语言不可能做到或无可靠方法实现的

2.1 autolt基本脚本语法

进入到了另存为得界面,这个时候selenium就基本上无法进行操作了,因为selenium只对谷歌浏览器进行操作,不对window窗口进行操作,所以这个时候就需要autolt进行处理了。autolt是一个脚本语言,因为我们只需要保存一个文件,所以并不需要那么深入,所以下面我讲下autolt基本使用方法

2.1.1 安装完软件之后,各个文件的作用

1705566213838.png

  • 编辑器:用于编写脚本语言,并且进行调试,按住F5进行调试
  • 运行器:将脚本语言进行运行
  • 转脚本为exe:将编写的脚本转换成exe文件,用于java或者python直接运行
  • 查看窗口信息:用于获取将要操作窗口的基本信息,例如将要操作按钮和编辑框的信息等等
2.1.2 查看窗口信息

1705566259920.png

查看窗口信息的方法:按住Finder Tool的,然后拖拽到你要操作的位置,这个时候查看Control窗口,就能得到你要操作的元素信息

  • Title:当前窗口的标题
  • Calss:当前元素的类型,例如当前窗口为编辑框,则这里显示Edit
  • Instance:这个是这个窗口的第一个Edit,所以Instance为1
  • ClassnameNN:可以作为当前元素的唯一id,但是没有AdvancedModel准确

2.2 autolt保存文件

#该脚本的语法是:  ;分号代表注释,为了博客好看,我先把;换成#
##ControlFocus ( "title", "窗口文本", controlID)   设置输入焦点到指定窗口的某个控件上
#WinWait ( "title题" , "窗口文本" , 超时时间 )  暂停脚本的执行直至指定窗口存在(出现)为止
#ControlSetText ( "title", "窗口文本", controlID, "新文本" )   修改指定控件的文本
#Sleep ( 延迟 )   使脚本暂停指定时间段
#ControlClick ( "title", "窗口文本", 控件ID , 按钮 , 点击次数 )   向指定控件发送鼠标点击命令
#其中,title即AutoIt Window Info识别出的Title字段,controlID即AutoIt Window Info识别
#出的Class和Instance的拼接,如上图拼接后的结果应为:Button1
#ControlClick(
#ControlClick("另存为","保存","Button2")

ControlFocus("另存为","text","1001")
WinWait("[CLASS:#32770]","",100)
ControlSetText("另存为","","[CLASS:Edit; INSTANCE:1]","$CmdLine[1]")
Sleep(1500)
ControlClick("另存为","保存","Button2")



2.3 autolt打包成exe

运行转脚本为exe的文件,将其转换成exe文件,放入resource目录下的driver下面

2.4 java运行exe文件

//第一个参数是exe路径,后面是执行cmd得参数,这个也就是对应保存PDF的名称
String[] commandArray = {"src/main/resources/driver/pdf.exe", sample.getCode() + ".pdf"};
runtime.exec(commandArray);

3 结尾

虽然我写的这个博客是关于java+selenium+autolt将html打印成PDF,但是也可以用到下载文件里边,原理是一样的。在进行爬虫的时候,经常要遇到下载文件的业务,这样可以很好的完成。

标签:exe,浏览器,driver,selenium,robot,autoIt,java,窗口
From: https://www.cnblogs.com/booleandev/p/18292448/java-selenium-autoit-implement-the-download-

相关文章

  • [Java SE] Java-文件系统-常用文件路径的获取方法
    1获取相对路径/***获取相对路径【推荐】*使用Java提供的Path类和Paths类来获取相对路径。*例如,假设有两个路径a和b,我们可以使用Path类的relativize()方法来获取相对路径,该方法返回一个相对路径的Path对象。*/@TestpublicvoidgetRelativePathTest1(){ Pathpath......
  • JAVA-二维数组-要求计算出每个季度的总营业额和全年的总营业额-求指导
            二维数组的练习某商城每个季度的营业额如下:单位(万元)第一季度:22,66,44第二季度:77,33,88第三季度:25,45,65第四季度:11,66,99要求计算出每个季度的总营业额和全年的总营业额package_exercis;publicclassTwoArray{publicstaticvoidmain(S......
  • [深入理解Java虚拟机]Java内存模型
    Java内存模型概述多任务处理在现代计算机操作系统中几乎已是一项必备的功能了。在许多场景下,让计算机同时去做几件事情,不仅是因为计算机的运算能力强大了,还有一个很重要的原因是计算机的运算速度与它的存储和通信子系统的速度差距太大,大量的时间都花费在磁盘I/O、网络通信或者数......
  • Javase-3.运算符
    3.运算符1.算术运算符1.基本运算符:加减乘除模(+-*/%)inta=2;intb=1;System.out.println(a+b);//3System.out.println(a-b);//1System.out.println(a*b);//2System.out.println(b/a);//0int/int结果还是int类型,而且会向下取整System.out.print......
  • Java泛型的定义与运用
    泛型泛型的作用从使用层面上来说是统一数据类型,防止将来的数据转换异常。从定义层面上来说,定义带泛型的类,方法等,将来使用的时候给泛型确定什么类型,泛型就会变成什么类型,凡是涉及到泛型的都会变成确定的类型,代码更灵活。不使用泛型,少了限制,则在集合添加数据就不会类型异常......
  • 简单的Java面向对象小游戏并使用三层架构(表示层、业务逻辑层、数据访问层)
    本人详解作者:王文峰,参加过CSDN2020年度博客之星,《Java王大师王天师》公众号:JAVA开发王大师,专注于天道酬勤的Java开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯山峯转载说明:务必注明来源(注明:作者:王文峰哦)简单的Java面......
  • Java Executors类的9种创建线程池的方法及应用场景分析
    在Java中,Executors类提供了多种静态工厂方法来创建不同类型的线程池。在学习线程池的过程中,一定避不开Executors类,掌握这个类的使用、原理、使用场景,对于实际项目开发时,运用自如,以下是一些常用的方法,V哥来一一细说:newCachedThreadPool():创建一个可缓存的线程池,如果线程池中......
  • Java 中的泛型 集合(List,Set) Map
    泛型集合(List,Set)Map泛型泛型的本质是参数化类型,即允许在编译时对集合进行类型检查,从而避免安全问题,提高代码的复用性泛型的具体定义与作用定义:泛型是一种在编译阶段进行类型检查的机制,它允许在类,方法,接口后通过<>来声明类型参数.这些参数在编译时会被具体的类......
  • Java token穷举id造假 jwt token伪造
    一、JWT简介1、简介JSONWebToken(JSONWeb令牌)是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地传输信息。通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据 加密、签名......
  • Java实现消球游戏
    消球游戏设计一个程序实现消球游戏:在棋盘内,一开始随机初始化三个不同色小球,一次可移动一个小球至空白位置,当同色5个小球连成直线,横、竖、对角均可,则小球消除并得分。消除1个小球得1分,当小球移动1次没有消除时,系统会自动随机产生三个小球。基本要求:(1)要求实现图形化界......