2017-10-09 152 views
1

據我瞭解,ChromeDriver本身並沒有設定CSS的背景。因此,如果背景是透明的,爲什麼我沒有獲得透明的截圖?透過Selenium的無頭ChromeDriver的透明屏幕截圖

這就是所謂透明網站的截圖: Transparent background 相同的屏幕截圖,但在後臺紅色div來展現,其中透明度應在於: Red background

這裏是我的代碼:

from selenium import webdriver 
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC 
from selenium.webdriver.common.by import By 
from datetime import datetime 

options = webdriver.ChromeOptions() 
options.add_argument('headless') 
driver = webdriver.Chrome(chrome_options=options) 

driver.set_window_size(2560, 1600) 
driver.get('https://twitter.com/realDonaldTrump/status/516382177798680576') 
# driver.execute_script("$('body').append(`<div style='background: red; width: 100%; height: 100%;'></div>`);") 
driver.save_screenshot('screenshots/' + str(datetime.now()) + '.png') 

driver.quit() 

我如何能夠創建該截圖的透明版本?

*編輯* 我做了一個如何完成這一點的要點。接受的答案幫助我達到了我可以弄明白的地步,這正是我想要的。然而,這個要點正確的解決了我的問題: https://gist.github.com/colexyz/f58834ff09ab07e3c1164667b753e77a

+0

有這條線,你有評論,你有沒有嘗試改變,以這樣的:'driver.execute_script (「$('body').css('background-color','transparent');」)'?注意所有div層必須是'background-color:transparent'纔能有真正透明的背景,所以如果僅僅通過改變主體背景就不能工作,那麼你就必須用開發工具做一些測試和調整顏色。另外請記住,該網頁必須有jQuery,我不認爲Twitter的確如此,但我並不確定。 –

+0

@ChristosLytras我試着將'background-color'設置爲'transparent',它仍然產生白色背景。 Twitter使用jQuery。我將如何去調整開發者工具? – Cole

+0

只需在瀏覽twitter時點擊F12,轉到* Elements *選項卡,然後檢查內容的每個DIV子元素的樣式以獲取背景顏色屬性。 –

回答

2

的一種方法是由阿爾法字節設置爲0,每個白色像素從截圖轉換成透明像素:

from selenium import webdriver 
from PIL import Image 
from io import BytesIO # python 3 
import numpy as np 

def remove_color(img, rgba): 
    data = np.array(img.convert('RGBA'))  # rgba array from image 
    pixels = data.view(dtype=np.uint32)[...,0] # pixels as rgba uint32 
    data[...,3] = np.where(pixels == np.uint32(rgba), np.uint8(0), np.uint8(255)) # set alpha channel 
    return Image.fromarray(data) 

driver = webdriver.Chrome() 
driver.get("http://www.bbc.co.uk/news") 

# take screenshot with a transparent background 
with Image.open(BytesIO(driver.get_screenshot_as_png())) as img : 
    with remove_color(img, 0xffffffff) as img2: 
    img2.save(r"C:\temp\screenshot.png") 

然而,你可能最終與如此我意外的透明像素,如果頁面內容有一些白色的像素,antialiassing可能會看到。

另一種解決方案是使用Chrome瀏覽器的API DevTool排除從截圖背景:

from selenium import webdriver 
import json 

def send(cmd, params={}): 
    resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id 
    url = driver.command_executor._url + resource 
    body = json.dumps({'cmd':cmd, 'params': params}) 
    response = driver.command_executor._request('POST', url, body) 
    if response['status']: raise Exception(response.get('value')) 
    return response.get('value') 

options = webdriver.ChromeOptions() 
options.add_argument("disable-gpu") 
options.add_argument("disable-infobars") 

driver = webdriver.Chrome(chrome_options=options) 
driver.get("http://www.bbc.co.uk/news") 

# take screenshot with a transparent background 
send("Emulation.setDefaultBackgroundColorOverride", {'color': {'r': 0, 'g': 0, 'b': 0, 'a': 0}}) 
driver.get_screenshot_as_file(r"C:\temp\screenshot.png") 
send("Emulation.setDefaultBackgroundColorOverride") # restore 
+0

是的,第二個解決方案是爲我工作的。我想到了Tabun的評論,但我會將其標記爲未來發現的正確答案。 – Cole

+1

@Cole,我是導致此解決方案的評論的作者。 –

+0

我的錯誤,現在我明白了。非常感謝你! – Cole

3

一個PNG可以有透明的像素,但截圖不能。無論何時渲染某些東西時,都會混合呈現透明度級別的渲染,但合成圖層總是會有背景。

屏幕截圖是屏幕上呈現的內容,它永遠不會透明。如何在桌面上顯示真實的透明圖像?你不能因爲桌面或其他東西的背景總是必須在那裏。

所以你所要求的與Chrome,ChromeDriver無關。任何截圖採取工具不能採取透明的截圖,沒有你告訴它掩蓋什麼。

即使像Photoshop這樣的工具使用特殊的方式(灰度顏色框有小的變化)來顯示透明背景,但如果你使用屏幕截圖工具來捕捉該圖像,結果將是一個具有實際像素和像下面一樣的透明度的圖像

Transparent image

+0

偉大的觀點和我理解這一點,但只要沒有定義的背景或背景本身被定義爲透明,使用PhantomJS驅動程序將導致透明圖像。因此,我知道這是可能的,這只是ChromeDriver與其他驅動程序無法正確呈現頁面的問題。 – Cole

+0

嘗試使用無頭的chrome,看看它是否發生了變化,因爲所有在屏幕上實際呈現的圖像都會給你一個背景顏色。作爲內存渲染器的PhantomJS不需要有背景容器來呈現並散開透明度 –

+0

屏幕截圖可以具有透明背景。例如[puppeteer](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagescreenshotoptions)提供了該選項。使用Selenium可以通過從PNG中刪除背景或使用Chrome自定義命令調用Emulation.setDefaultBackgroundColorOverride來實現。 –