7

でフルスクリーンのスクリーンショットを取っています...このページでは、chromedriver、selenium、およびpythonで全画面のスクリーンショットをとられました。ここでさまざまなアプローチを試してみて、Selenium Python(chromedriver)

元のコード:http://seleniumpythonqa.blogspot.com/2015/08/generate-full-page-screenshot-in-chrome.html(と私は下のこの投稿のコードをコピー)

それはPILを使用し、それは素晴らしい作品!!!!!しかし、1つの問題があります...ページ全体の固定ヘッダーとリピートをキャプチャし、ページが変更されている間にページの一部が失われます。スクリーンショット取るためのサンプルURL:

http://www.w3schools.com/js/default.asp

このコードで繰り返さヘッダを回避するための方法

...それともだけのpythonを使用して任意のより良いオプションがありますが...(私は、Javaを知りませんjavaを使用したくない場合)。

下記の現在の結果とサンプルコードのスクリーンショットをご覧ください。

full page screenshot with repeated headers

test.py

""" 
This script uses a simplified version of the one here: 
https://snipt.net/restrada/python-selenium-workaround-for-full-page-screenshot-using-chromedriver-2x/ 

It contains the *crucial* correction added in the comments by Jason Coutu. 
""" 

import sys 

from selenium import webdriver 
import unittest 

import util 

class Test(unittest.TestCase): 
    """ Demonstration: Get Chrome to generate fullscreen screenshot """ 

    def setUp(self): 
     self.driver = webdriver.Chrome() 

    def tearDown(self): 
     self.driver.quit() 

    def test_fullpage_screenshot(self): 
     ''' Generate document-height screenshot ''' 
     #url = "http://effbot.org/imagingbook/introduction.htm" 
     url = "http://www.w3schools.com/js/default.asp" 
     self.driver.get(url) 
     util.fullpage_screenshot(self.driver, "test.png") 


if __name__ == "__main__": 
    unittest.main(argv=[sys.argv[0]]) 

util.py

import os 
import time 

from PIL import Image 

def fullpage_screenshot(driver, file): 

     print("Starting chrome full page screenshot workaround ...") 

     total_width = driver.execute_script("return document.body.offsetWidth") 
     total_height = driver.execute_script("return document.body.parentNode.scrollHeight") 
     viewport_width = driver.execute_script("return document.body.clientWidth") 
     viewport_height = driver.execute_script("return window.innerHeight") 
     print("Total: ({0}, {1}), Viewport: ({2},{3})".format(total_width, total_height,viewport_width,viewport_height)) 
     rectangles = [] 

     i = 0 
     while i < total_height: 
      ii = 0 
      top_height = i + viewport_height 

      if top_height > total_height: 
       top_height = total_height 

      while ii < total_width: 
       top_width = ii + viewport_width 

       if top_width > total_width: 
        top_width = total_width 

       print("Appending rectangle ({0},{1},{2},{3})".format(ii, i, top_width, top_height)) 
       rectangles.append((ii, i, top_width,top_height)) 

       ii = ii + viewport_width 

      i = i + viewport_height 

     stitched_image = Image.new('RGB', (total_width, total_height)) 
     previous = None 
     part = 0 

     for rectangle in rectangles: 
      if not previous is None: 
       driver.execute_script("window.scrollTo({0}, {1})".format(rectangle[0], rectangle[1])) 
       print("Scrolled To ({0},{1})".format(rectangle[0], rectangle[1])) 
       time.sleep(0.2) 

      file_name = "part_{0}.png".format(part) 
      print("Capturing {0} ...".format(file_name)) 

      driver.get_screenshot_as_file(file_name) 
      screenshot = Image.open(file_name) 

      if rectangle[1] + viewport_height > total_height: 
       offset = (rectangle[0], total_height - viewport_height) 
      else: 
       offset = (rectangle[0], rectangle[1]) 

      print("Adding to stitched image with offset ({0}, {1})".format(offset[0],offset[1])) 
      stitched_image.paste(screenshot, offset) 

      del screenshot 
      os.remove(file_name) 
      part = part + 1 
      previous = rectangle 

     stitched_image.save(file) 
     print("Finishing chrome full page screenshot workaround...") 
     return True 

答えて

4

あなたはスクリーンショットの前に、ヘッダーのCSSを変更することによって、これを達成することができます

topnav = driver.find_element_by_id("topnav") 
driver.execute_script("arguments[0].setAttribute('style', 'position: absolute; top: 0px;')", topnav) 

EDIT:あなたのウィンドウのスクロールした後、この行を入れて:

driver.execute_script("document.getElementById('topnav').setAttribute('style', 'position: absolute; top: 0px;');") 

をだからあなたのutil.pyで、それは次のようになります。

driver.execute_script("window.scrollTo({0}, {1})".format(rectangle[0], rectangle[1])) 
driver.execute_script("document.getElementById('topnav').setAttribute('style', 'position: absolute; top: 0px;');") 

サイトがheaderを使用している場合タグを使用して行うことができますfind_element_by_tag_name("header")

+0

こんにちは感謝..上記のスクリプトに追加するだけで問題を解決することはできません..しかし、私は意味を理解していますし、topnavを無効にしました..インスペクタを使用して..とjavascriptを見つけるために掘る必要がありますcss)を修正して、それを絶対的なものに変更しました。それは働いた。 (ただし、スクリプトのスクリーンショットはまだ動作しません)。 javascriptのCSSの変更を無効にするURLスクリプトを改善する方法はありますか?また、新しいウェブサイトについても、ヘッダの#idを見つけて変更する必要があります。 – ihightower

+0

どのウェブサイトがどのようにヘッダを実装したかを事前に知ることはできません。しかし、あなたは推測することができます。私は例を追加します。 – Moshisho

+0

あなたのコードはうまくいきましたが、いくつかの小さな問題があります。だから、睡眠0.2秒を追加した後..それは完全に働いた。私はコードを更新し、またあなたの答えをマークしました。あなたの答えに編集をしたいと思っているのは、stackoverflowにとって正しいです。 – ihightower

5

@モシショ

私の完全なスタンドアロンの作業スクリプトが...私は、Python 3.6のコードを変更し

import sys 
from selenium import webdriver 
import util 
import os 
import time 
from PIL import Image 

def fullpage_screenshot(driver, file): 

     print("Starting chrome full page screenshot workaround ...") 

     total_width = driver.execute_script("return document.body.offsetWidth") 
     total_height = driver.execute_script("return document.body.parentNode.scrollHeight") 
     viewport_width = driver.execute_script("return document.body.clientWidth") 
     viewport_height = driver.execute_script("return window.innerHeight") 
     print("Total: ({0}, {1}), Viewport: ({2},{3})".format(total_width, total_height,viewport_width,viewport_height)) 
     rectangles = [] 

     i = 0 
     while i < total_height: 
      ii = 0 
      top_height = i + viewport_height 

      if top_height > total_height: 
       top_height = total_height 

      while ii < total_width: 
       top_width = ii + viewport_width 

       if top_width > total_width: 
        top_width = total_width 

       print("Appending rectangle ({0},{1},{2},{3})".format(ii, i, top_width, top_height)) 
       rectangles.append((ii, i, top_width,top_height)) 

       ii = ii + viewport_width 

      i = i + viewport_height 

     stitched_image = Image.new('RGB', (total_width, total_height)) 
     previous = None 
     part = 0 

     for rectangle in rectangles: 
      if not previous is None: 
       driver.execute_script("window.scrollTo({0}, {1})".format(rectangle[0], rectangle[1])) 
       time.sleep(0.2) 
       driver.execute_script("document.getElementById('topnav').setAttribute('style', 'position: absolute; top: 0px;');") 
       time.sleep(0.2) 
       print("Scrolled To ({0},{1})".format(rectangle[0], rectangle[1])) 
       time.sleep(0.2) 

      file_name = "part_{0}.png".format(part) 
      print("Capturing {0} ...".format(file_name)) 

      driver.get_screenshot_as_file(file_name) 
      screenshot = Image.open(file_name) 

      if rectangle[1] + viewport_height > total_height: 
       offset = (rectangle[0], total_height - viewport_height) 
      else: 
       offset = (rectangle[0], rectangle[1]) 

      print("Adding to stitched image with offset ({0}, {1})".format(offset[0],offset[1])) 
      stitched_image.paste(screenshot, offset) 

      del screenshot 
      os.remove(file_name) 
      part = part + 1 
      previous = rectangle 

     stitched_image.save(file) 
     print("Finishing chrome full page screenshot workaround...") 
     return True 


driver = webdriver.Chrome() 

''' Generate document-height screenshot ''' 
url = "http://effbot.org/imagingbook/introduction.htm" 
url = "http://www.w3schools.com/js/default.asp" 
driver.get(url) 
fullpage_screenshot(driver, "test1236.png") 
4

(各スクロールおよび位置の後に睡眠0.2追加)され、多分それは誰かのために有用であろう:

from selenium import webdriver 
from sys import stdout 
from selenium.webdriver.common.by import By 
from selenium.webdriver.common.keys import Keys 
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC 
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 
import unittest 
#from Login_Page import Login_Page 
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary 
from io import BytesIO 
from PIL import Image 

def testdenovoUIavailable(self): 
     binary = FirefoxBinary("C:\\Mozilla Firefox\\firefox.exe") 
     self.driver = webdriver.Firefox(firefox_binary=binary) 
     verbose = 0 

     #open page 
     self.driver.get("http://yandex.ru") 

     #hide fixed header   
     #js_hide_header=' var x = document.getElementsByClassName("topnavbar-wrapper ng-scope")[0];x[\'style\'] = \'display:none\';' 
     #self.driver.execute_script(js_hide_header) 

     #get total height of page 
     js = 'return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);' 

     scrollheight = self.driver.execute_script(js) 
     if verbose > 0: 
      print(scrollheight) 

     slices = [] 
     offset = 0 
     offset_arr=[] 

     #separate full screen in parts and make printscreens 
     while offset < scrollheight: 
      if verbose > 0: 
       print(offset) 

      #scroll to size of page 
      if (scrollheight-offset)<offset: 
       #if part of screen is the last one, we need to scroll just on rest of page 
       self.driver.execute_script("window.scrollTo(0, %s);" % (scrollheight-offset)) 
       offset_arr.append(scrollheight-offset) 
      else: 
       self.driver.execute_script("window.scrollTo(0, %s);" % offset) 
       offset_arr.append(offset) 

      #create image (in Python 3.6 use BytesIO) 
      img = Image.open(BytesIO(self.driver.get_screenshot_as_png())) 


      offset += img.size[1] 
      #append new printscreen to array 
      slices.append(img) 


      if verbose > 0: 
       self.driver.get_screenshot_as_file('screen_%s.jpg' % (offset)) 
       print(scrollheight) 

     #create image with 
     screenshot = Image.new('RGB', (slices[0].size[0], scrollheight)) 
     offset = 0 
     offset2= 0 
     #now glue all images together 
     for img in slices: 
      screenshot.paste(img, (0, offset_arr[offset2])) 
      offset += img.size[1] 
      offset2+= 1  

     screenshot.save('test.png') 
0
element=driver.find_element_by_tag_name('body') 
element_png = element.screenshot_as_png 
with open("test2.png", "wb") as file: 
    file.write(element_png) 

これは私のために働く。ページ全体をスクリーンショットとして保存します。あなたはAPIドキュメントを読むことができます詳細については : http://selenium-python.readthedocs.io/api.html

0
element=driver.find_element_by_tag_name('body') 
element_png = element.screenshot_as_png 
with open("test2.png", "wb") as file: 
    file.write(element_png) 

ここでは、以前の2行目で推奨コードのエラーが訂正さ1でした。ここにはノブがいて、自分の投稿をまだ編集することはできません。

時々baoveは最良の結果を得られません。ところで、それはFFで動作

element=driver.find_elements_by_xpath("/html/child::*/child::*") 
    eheight=set() 
    for e in element: 
     eheight.add(round(e.size["height"])) 
    print (eheight) 
    total_height = sum(eheight) 
    driver.execute_script("document.getElementsByTagName('html')[0].setAttribute('style', 'height:"+str(total_height)+"px')") 
    element=driver.find_element_by_tag_name('body') 
    element_png = element.screenshot_as_png 
    with open(fname, "wb") as file: 
     file.write(element_png) 

:だから、すべての要素の高さを取得し、以下のようにキャプチャの高さを設定し、それらを合計する別の方法を使用することができます。

関連する問題