java 实现网址的截图
maven 引入
<!--自动化测试工具,需要去其他网址下第三方包--> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.141.59</version> <exclusions> <exclusion> <artifactId>guava</artifactId> <groupId>com.google.guava</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency>
下载相关浏览器chrome
(windows)https://www.chromedownloads.net/chrome64win/
windows会自己更新,需要自己去禁止更新,不然测着测着,浏览器升级了(除非你旧版本打开以后,就不要关闭),导致代码报错
(linux)https://www.chromedownloads.net/chrome64linux/
linux系统不会自动更新的,不要担心
下载相关浏览器chromedriver驱动
我这边下载的也是98.0.4758.102版本
https://registry.npmmirror.com/binary.html?path=chromedriver/98.0.4758.102/
测试代码
import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.epoint.third.apache.commons.io.FileUtils; import com.linewell.gov.hoox.utils.log.LogUtil; import org.openqa.selenium.Cookie; import org.openqa.selenium.Dimension; import org.openqa.selenium.OutputType; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeDriverService; import org.openqa.selenium.chrome.ChromeOptions; import java.io.File; import java.io.IOException; import java.sql.Timestamp; import java.util.Date; import java.util.concurrent.TimeUnit; /** * 条件:需要谷歌浏览器版本和驱动版本一张 */ public class SeleniumTools { public static void main(String[] args) { long startTime = System.currentTimeMillis(); Timestamp now1 = new Timestamp(startTime); System.out.println("now1:" + now1); for (int i = 0; i < 3; i++) { try { guge("D:/guge/img"+"/"+System.currentTimeMillis()+".png", "https://mpage.taobao.com/hd/download.html", "123"); } catch (Exception e) { e.printStackTrace(); } } long between = DateUtil.between(new Date(startTime), new Date(), DateUnit.SECOND); System.out.println("相差秒"+between); System.out.println("相差分钟"+between/60); } //解决如下: 模拟浏览器滚动滚动条 解决懒加载问题 public static void guge(String hzdtpwzPath, String url, String nhhzdtoken) throws IOException { LogUtil.info("=====guge========="); LogUtil.info(hzdtpwzPath); LogUtil.info(url); LogUtil.info(nhhzdtoken); // 根据系统来添加不同的驱动路径 String os = System.getProperty("os.name"); LogUtil.info(os); String driverPath =""; if (StrUtil.containsIgnoreCase(os, "Windows")) {//微软系统 driverPath+="D:\\chromedriver_win32 (98.0.4758.102)\\chromedriver.exe"; //程序执行,核心代码 processCMD("taskkill /F /im chromedriver.exe",1); } else {//linux系统 driverPath+="/usr/local/xxxx/ChromeDriver/chromedriver_linux64/chromedriver"; //程序执行,核心代码 processCMD("ps -ef | grep Chrome | grep -v grep | awk '{print \"kill -9 \"$2}' | sh",2); } //频繁的启动关闭,会增加一个比较明显的延时导致浏览器进程不被关闭的情况发生, // 为了避免这一状况我们可以通过ChromeDriverService来控制ChromeDriver进程的生死, // 达到用完就关闭的效果避免进程占用情况出现(Running the server in a child process) ChromeDriverService service =new ChromeDriverService.Builder().usingDriverExecutable(new File(driverPath)).usingAnyFreePort().build(); // 新建service 方便后面关闭chromedriver service.start(); // 开启服务 ChromeOptions options = new ChromeOptions(); //ssl证书支持 options.setCapability("acceptSslCerts", true); //截屏支持 options.setCapability("takesScreenshot", true); //css搜索支持 options.setCapability("cssSelectorsEnabled", true); //设置浏览器参数 // 设置无轨 开发时还是不要加,可以看到浏览器效果 options.addArguments("--headless"); options.addArguments("--no-sandbox"); options.addArguments("--disable-gpu"); options.addArguments("--disable-dev-shm-usage"); //处理僵尸进程 options.addArguments("--no-zygote"); //设置无头模式,一定要设置headless,否则只能截出电脑屏幕大小的图!!! options.setHeadless(true); WebDriver driver = new ChromeDriver(service,options); //设置超时,避免有些内容加载过慢导致截不到图 driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.MINUTES); driver.manage().timeouts().implicitlyWait(1, TimeUnit.MINUTES); driver.manage().timeouts().setScriptTimeout(1, TimeUnit.MINUTES); try { //设置需要访问的地址 driver.get(url); //先登录,再设置cookies Cookie c1 = new Cookie("token", nhhzdtoken); driver.manage().addCookie(c1); //设置需要访问的地址 driver.get(url); //获取高度和宽度一定要在设置URL之后,不然会导致获取不到页面真实的宽高; Long width = (Long) ((ChromeDriver) driver).executeScript("return document.documentElement.scrollWidth"); Long height = (Long) ((ChromeDriver) driver).executeScript("return document.documentElement.scrollHeight"); LogUtil.info("宽带:" + width); LogUtil.info("高度:" + height); //这里需要模拟滑动,有些是滑动的时候才加在的 long temp_height = 0; while (true) { //每次滚动500个像素,因为懒加载所以每次等待2S 具体时间可以根据具体业务场景去设置 Thread.sleep(1000); ((ChromeDriver) driver).executeScript("window.scrollBy(0,500)"); temp_height += 500; if (temp_height >= height) { break; } } //设置窗口宽高,设置后才能截全 driver.manage().window().setSize(new Dimension(width.intValue()+1120, height.intValue()+303)); //设置截图文件保存的路径 String screenshotPath = hzdtpwzPath; File srcFile = ((ChromeDriver) driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(srcFile, new File(screenshotPath)); LogUtil.info("设置浏览器截图文件保存的路径:" + screenshotPath); } catch (Exception e) { throw new RuntimeException("截图失败", e); } finally { //close仅仅关闭了当前页面,并未关闭chrome。 //使用quit则会真正退出chrome,结束进程。 //两者一起使用,才能避免频繁的启动关闭出现的卡住现象(重点) driver.close(); driver.quit(); service.stop(); } } //直接杀进程 public static int processCMD(String commend,int type) { //正常写 linux命令即可 、比如:mkdir xx/touch b.txt/sh start.sh/sh stop.sh int i = 0; Process process =null; //程序执行,核心代码 try { if(type==1){ //cmd /c dir 是执行完dir命令后关闭命令窗口。看需调整 String[] cmd = new String[]{"cmd","/c",commend}; process = Runtime.getRuntime().exec(cmd); //也可以直接使用 process = Runtime.getRuntime().exec(commend) }else{ //要想保证linux环境下命令能够执行成功,必须使用String[] String[] cmd = new String[]{"sh","-c",commend}; process = Runtime.getRuntime().exec(cmd); } i = process.waitFor(); System.out.println("执行kill进程命令结果:" + i); } catch (Exception e) { e.printStackTrace(); } return i; } //通常,安全编码规范中都会指出:使用Process.waitFor()的时候, //可能导致进程阻塞,甚至死锁。 //使用java代码执行shell脚本,执行后会发现Java进程和Shell进程都会挂起,无法结束。 public static int processCMD2(String commend) { //正常写 linux命令即可 、比如:mkdir xx/touch b.txt/sh start.sh/sh stop.sh int i = 0; Process process = null; try { process = Runtime.getRuntime().exec(commend); //获取进程的标准输入流 final InputStream is1 = process.getInputStream(); //获取进城的错误流 final InputStream is2 = process.getErrorStream(); //启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流 new Thread(() -> { BufferedReader br1 = new BufferedReader(new InputStreamReader(is1)); try { String line1 = null; while ((line1 = br1.readLine()) != null) { if (line1 != null) { } } } catch (IOException e) { e.printStackTrace(); } finally { try { is1.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); new Thread(() -> { BufferedReader br2 = new BufferedReader(new InputStreamReader(is2)); try { String line2 = null; while ((line2 = br2.readLine()) != null) { if (line2 != null) { } } } catch (IOException e) { e.printStackTrace(); } finally { try { is2.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); //可能导致进程阻塞,甚至死锁 i = process.waitFor(); } catch (Exception ex) { ex.printStackTrace(); try { process.getErrorStream().close(); process.getInputStream().close(); process.getOutputStream().close(); } catch (Exception ee) { } } LogUtil.info("CMD2-执行kill进程命令:" + commend); System.out.println("CMD2-执行kill进程命令:" + commend); LogUtil.info("CMD2-执行kill进程命令结果:" + i); System.out.println("CMD2-执行kill进程命令结果:" + i); return i; } }
转自 https://blog.csdn.net/qq_20236937/article/details/132231095