使用firefox瀏覽器無頭模式在內(nèi)存里渲染頁面,然后用selenium操作瀏覽器并解析截圖。需要安裝firefox(也支持chrome)颈畸,然后下載firefox 驅(qū)動(dòng) 詳見:https://github.com/mozilla/geckodriver/releases峻厚。下載完成后存放任意路徑,然后將代碼中的geckoDriver 改為驅(qū)動(dòng)的實(shí)際路徑即可焕毫。
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import sun.misc.BASE64Decoder;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* 網(wǎng)頁截圖
*/
public class WebPageScreenShot {
/**
* fireFox驅(qū)動(dòng)路徑
*/
String geckoDriver = "C:\\Program Files\\Python37\\geckodriver.exe";
String type="png";
public void loadPage(String logonUrl,String actionUrl,String resultPath) throws IOException, InterruptedException {
System.setProperty("webdriver.gecko.driver", geckoDriver);//chromedriver服務(wù)地址
FirefoxOptions firefoxOptions = new FirefoxOptions();
firefoxOptions.addArguments("-headless");
//firefoxOptions.addArguments("--start-maximized");
//firefoxOptions.addArguments("--start-fullscreen");
firefoxOptions.setHeadless(true);
FirefoxDriver driver = new FirefoxDriver(firefoxOptions); //新建一個(gè)WebDriver 的對(duì)象,但是new 的是FirefoxDriver的驅(qū)動(dòng)
driver.get(logonUrl);//打開指定的網(wǎng)站
driver.findElement(By.id("J_username")).sendKeys(new String[]{"***"});
driver.findElement(By.id("J_password")).sendKeys(new String[]{"***"});
driver.findElement(By.id("loginBtn")).click();//登錄
(new WebDriverWait(driver, 20)).until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".index-welcome-info")));//檢查到登錄成功
driver.get(actionUrl);//打開指定的網(wǎng)站
driver.manage().window().setSize(new Dimension(1900, 800));
//driver.manage().window().maximize();
String js1 = "return document.body.clientHeight.toString()";
String js1_result = driver.executeScript(js1) + "";
int height = Integer.parseInt(js1_result);
List<String> files = new ArrayList<String>();
int last_t = 0;
for (int i = 0; i < 20; ) {
int currentHeight = (i * height);
String js = "window.scrollTo(0," + currentHeight + ");";
driver.executeScript(js);
js1 = "return document.body.scrollHeight.toString()+','+document.body.scrollTop.toString()";
js1_result = driver.executeScript(js1) + "";
/**
* real_scroll_h, real_top = js1_result.split(',')[0], js1_result.split(',')[1]
* 22 #real_scroll_h, real_top 是當(dāng)前滾動(dòng)條長度和當(dāng)前滾動(dòng)條的top驶乾,作為是否繼續(xù)執(zhí)行的依據(jù)邑飒,由于存在滾動(dòng)條向下拉動(dòng)后會(huì)加載新內(nèi)容的情況,所以需要以下的判斷
* 23 #如果這次設(shè)置的top成功级乐,則繼續(xù)滾屏
*/
int real_scroll_h = Integer.parseInt(js1_result.split(",")[0]);
int real_top = Integer.parseInt(js1_result.split(",")[1]);
//#real_scroll_h, real_top 是當(dāng)前滾動(dòng)條長度和當(dāng)前滾動(dòng)條的top疙咸,作為是否繼續(xù)執(zhí)行的依據(jù),由于存在滾動(dòng)條向下拉動(dòng)后會(huì)加載新內(nèi)容的情況唇牧,所以需要以下的判斷
if (real_top == currentHeight) {
// #如果這次設(shè)置的top成功罕扎,則繼續(xù)滾屏
i++;
files.add(screenshot(driver).getAbsolutePath());
last_t = real_top;
} else {
// #如果本次設(shè)置失敗,看這次的top和上一次記錄的top值是否相等丐重,相等則說明沒有新加載內(nèi)容腔召,且已到頁面底,跳出循環(huán)
if (real_top != last_t) {
last_t = real_top;
} else {
files.add(screenshot(driver).getAbsolutePath());
break;
}
}
}
driver.quit();//退出瀏覽器
merge(files.toArray(new String[]{}), type, resultPath);
}
private File screenshot(WebDriver driver) throws InterruptedException, IOException {
try {
/**
* WebDriver自帶了一個(gè)智能等待的方法扮惦。
dr.manage().timeouts().implicitlyWait(arg0, arg1)臀蛛;
Arg0:等待的時(shí)間長度,int 類型 崖蜜;
Arg1:等待時(shí)間的單位 TimeUnit.SECONDS 一般用秒作為單位浊仆。
*/
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
Thread.sleep(10000);//等等頁面加載完成
/**
* dr.quit()和dr.close()都可以退出瀏覽器,簡單的說一下兩者的區(qū)別:第一個(gè)close,
* 如果打開了多個(gè)頁面是關(guān)不干凈的豫领,它只關(guān)閉當(dāng)前的一個(gè)頁面抡柿。第二個(gè)quit,
* 是退出了所有Webdriver所有的窗口等恐,退的非常干凈洲劣,所以推薦使用quit最為一個(gè)case退出的方法。
*/
byte[] imageBytes = (byte[]) ((FirefoxDriver) driver).getScreenshotAs(new OutputType<Object>() {
public Object convertFromBase64Png(String s) {
try {
return (new BASE64Decoder()).decodeBuffer(s);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public Object convertFromPngBytes(byte[] bytes) {
return bytes;
}
});
ByteArrayInputStream bytes = new ByteArrayInputStream(imageBytes);
BufferedImage image = ImageIO.read(bytes);
File file = File.createTempFile((new Random()).nextInt()+"",type);
ImageIO.write(image, "png", file);
return file;
}
/**
* Java拼接多張圖片
*
* @param pics
* @param type
* @param dst_pic
* @return
*/
public static boolean merge(String[] pics, String type, String dst_pic) {
int len = pics.length;
if (len < 1) {
System.out.println("pics len < 1");
return false;
}
File[] src = new File[len];
BufferedImage[] images = new BufferedImage[len];
int[][] ImageArrays = new int[len][];
for (int i = 0; i < len; i++) {
try {
src[i] = new File(pics[i]);
images[i] = ImageIO.read(src[i]);
} catch (Exception e) {
e.printStackTrace();
return false;
}
int width = images[i].getWidth();
int height = images[i].getHeight();
ImageArrays[i] = new int[width * height];// 從圖片中讀取RGB
ImageArrays[i] = images[i].getRGB(0, 0, width, height,
ImageArrays[i], 0, width);
}
int dst_height = 0;
int dst_width = images[0].getWidth();
for (int i = 0; i < images.length; i++) {
dst_width = dst_width > images[i].getWidth() ? dst_width
: images[i].getWidth();
dst_height += images[i].getHeight();
}
if (dst_height < 1) {
System.out.println("dst_height < 1");
return false;
}
// 生成新圖片
try {
// dst_width = images[0].getWidth();
BufferedImage ImageNew = new BufferedImage(dst_width, dst_height,
BufferedImage.TYPE_INT_RGB);
int height_i = 0;
for (int i = 0; i < images.length; i++) {
ImageNew.setRGB(0, height_i, dst_width, images[i].getHeight(),
ImageArrays[i], 0, dst_width);
height_i += images[i].getHeight();
}
File outFile = new File(dst_pic);
ImageIO.write(ImageNew, type, outFile);// 寫圖片
} catch (Exception e) {
e.printStackTrace();
return false;
}finally {
/*
刪除臨時(shí)文件
*/
for(String tempFile:pics){
File t=new File(tempFile);
t.delete();
}
}
return true;
}
public static void main(String[] args) throws IOException, InterruptedException {
WebPageScreenShot screenShot=new WebPageScreenShot();
screenShot.loadPage("******","*******","D:\\TEST.png");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xx.xx</groupId>
<artifactId>java-selenium</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
</dependencies>
</project>