您好,登錄后才能下訂單哦!
前言
最近工作中遇到一個(gè)需求,需要實(shí)現(xiàn)截圖功能,斷斷續(xù)續(xù)查找資料、驗(yàn)證不同的實(shí)現(xiàn)方法終于算基本搞定了頁面截圖,因?yàn)橹虚g過程曲折花費(fèi)較多時(shí)間,分享出來幫助大家快速實(shí)現(xiàn)截圖
為什么選用phantomjs進(jìn)行截圖
截圖可以實(shí)現(xiàn)的方式有很多,比如:
PlantomJs提供了如 CSS 選擇器、DOM操作、JSON、HTML5、Canvas、SVG 等。PhantomJS 的用處很廣泛,如網(wǎng)絡(luò)監(jiān)控、網(wǎng)頁截屏、頁面訪問自動化、無需瀏覽器的 Web 測試等,這里只用到網(wǎng)頁截屏。
前期準(zhǔn)備
安裝phantomjs。mac os
brew install phantomjs
命令行的方式進(jìn)行截圖
安裝以后我們就可以小試牛刀了
打開終端,輸入以下命令:
/Users/hetiantian/SoftWares/phantomjs/bin/phantomjs /Users/hetiantian/SoftWares/phantomjs/examples/rasterize.js https://juejin.im/post/5bb24bafe51d450e4437fd96 /Users/hetiantian/Desktop/juejin-command.png
查看效果
發(fā)現(xiàn)圖片沒有加載好
來看以下剛剛的命令行:
/Users/hetiantian/SoftWares/phantomjs/bin/phantomjs:phantomjs可執(zhí)行文件保存地址
/Users/hetiantian/SoftWares/phantomjs/examples/rasterize.js:rasterize.js文件地址
這段命令可以理解為用phantomjs去運(yùn)行rasterize.js文件,所以要想解決圖片空白的問題我們需要去看一下rasterize.js文件。
"use strict"; var page = require('webpage').create(), system = require('system'), address, output, size, pageWidth, pageHeight; if (system.args.length < 3 || system.args.length > 5) { console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]'); console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"'); console.log(' image (png/jpg output) examples: "1920px" entire page, window width 1920px'); console.log(' "800px*600px" window, clipped to 800x600'); phantom.exit(1); } else { address = system.args[1]; output = system.args[2]; page.viewportSize = { width: 600, height: 600 }; if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") { size = system.args[3].split('*'); page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' } : { format: system.args[3], orientation: 'portrait', margin: '1cm' }; } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") { size = system.args[3].split('*'); if (size.length === 2) { pageWidth = parseInt(size[0], 10); pageHeight = parseInt(size[1], 10); page.viewportSize = { width: pageWidth, height: pageHeight }; page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight }; } else { console.log("size:", system.args[3]); pageWidth = parseInt(system.args[3], 10); pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any console.log ("pageHeight:",pageHeight); page.viewportSize = { width: pageWidth, height: pageHeight }; } } if (system.args.length > 4) { page.zoomFactor = system.args[4]; } page.open(address, function (status) { if (status !== 'success') { console.log('Unable to load the address!'); phantom.exit(1); } else { window.setTimeout(function () { page.render(output); phantom.exit(); }, 200); } }); }
嘗試一:
對page.viewportSize = { width: 600, height: 600 };產(chǎn)生了疑問🤔️
把height調(diào)大十倍,發(fā)現(xiàn)基本是完美截圖了,但是如果頁面的篇幅特別短,會發(fā)現(xiàn)有瑕疵,下面留有一大片空白。原因:page.viewportSize = { width: 600, height: 600 };設(shè)置的是初始打開瀏覽器的大小,通過增大這個(gè)值可以加載js。如果我們能拿到實(shí)際頁面的大小在設(shè)置height大小,但是不,我不能。
并且不能接受預(yù)先設(shè)定一個(gè)很大的height值,比如30000,因?yàn)椴荒芙邮艿紫铝舭椎男Ч?br />
嘗試二:
在window.setTimeout方法之前加入以下代碼
page.evaluate(function(){ scrollBy(0, 18000); });
無奈evaluate里不能在用for循環(huán)了,前端渣渣真的不知道如何改,遂放棄
java代碼方式進(jìn)行截圖
需要的依賴
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.45.0</version> </dependency> <dependency> <groupId>com.codeborne</groupId> <artifactId>phantomjsdriver</artifactId> <version>1.2.1</version> <!-- this will _always_ be behind --> <exclusions> <exclusion> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> </exclusion> <exclusion> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-remote-driver</artifactId> </exclusion> </exclusions> </dependency>
代碼實(shí)現(xiàn)
public class PhantomjsTest2 { public static void main(String[] args) throws InterruptedException, IOException { //設(shè)置必要參數(shù) DesiredCapabilities dcaps = new DesiredCapabilities(); //ssl證書支持 dcaps.setCapability("acceptSslCerts", true); //截屏支持 dcaps.setCapability("takesScreenshot", true); //css搜索支持 dcaps.setCapability("cssSelectorsEnabled", true); //js支持 dcaps.setJavascriptEnabled(true); //驅(qū)動支持(第二參數(shù)表明的是你的phantomjs引擎所在的路徑) dcaps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, "/Users/hetiantian/SoftWares/phantomjs/bin/phantomjs"); //創(chuàng)建無界面瀏覽器對象 PhantomJSDriver driver = new PhantomJSDriver(dcaps); //設(shè)置隱性等待(作用于全局) driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS); long start = System.currentTimeMillis(); //打開頁面 driver.get("https://juejin.im/post/5bb24bafe51d450e4437fd96"); Thread.sleep(30 * 1000); JavascriptExecutor js = driver; for (int i = 0; i < 33; i++) { js.executeScript("window.scrollBy(0,1000)"); //睡眠10s等js加載完成 Thread.sleep(5 * 1000); } //指定了OutputType.FILE做為參數(shù)傳遞給getScreenshotAs()方法,其含義是將截取的屏幕以文件形式返回。 File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); Thread.sleep(3000); //利用FileUtils工具類的copyFile()方法保存getScreenshotAs()返回的文件對象 FileUtils.copyFile(srcFile, new File("/Users/hetiantian/Desktop/juejin-01.png")); System.out.println("耗時(shí):" + (System.currentTimeMillis() - start) + " 毫秒"); } }
注釋已經(jīng)夠詳細(xì)了不多說了。唯一說一點(diǎn):通過去執(zhí)行js代碼實(shí)現(xiàn)頁面滑動,并且每次滑動都會通過睡眠保證有時(shí)間可以將 js加載進(jìn)來。會調(diào)用33次滑動,因?yàn)閜hantomjs截取最大的高度為32767px(int 32位的最大整數(shù)),所以滑動33次可以保證能夠截取到的最大頁面部分其js已經(jīng)是加載完成了的
附:window.scrollBy(0,1000)、window.scrollTo(0,1000)的區(qū)別
window.scrollBy(0,1000)
window.scrollBy(0,1000)
執(zhí)行到這里頁面滑動1000+1000px
window.scrollTo(0,1000)
window.scrollTo(0,1000)
執(zhí)行到這里頁面滑動到1000px處
window.scrollTo(0, document.body.scrollHeight可以滑動到頁面底部,不選擇有兩個(gè)原因:
1)一下子滑動到底部js會來不及被加載
2)有些頁面沒有底部,可以一直滑動加載
注:這里所說的js來不及加載指的是:想要截取頁面的js來不及加載
該方式的缺點(diǎn):比較費(fèi)時(shí)間。果然熊和魚掌不可兼得也,統(tǒng)計(jì)了一下截取一張圖片大概需要四分多鐘
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。