7

nach dem Ausprobieren verschiedener Ansätze ... Ich bin auf diese Seite gestoßen, um Fullpage Screenshot mit Chromedriver, Selen und Python zu nehmen.Screenshot Vollseite mit Selenium Python (chromedriver)

Original-Code hier: http://seleniumpythonqa.blogspot.com/2015/08/generate-full-page-screenshot-in-chrome.html (und ich kopieren Sie den Code in diesem Beitrag unten)

Es nutzt PIL und es funktioniert super !!!!! Es gibt jedoch ein Problem ... das ist, dass es feste Header und Wiederholungen für die ganze Seite erfasst und auch einige Teile der Seite während des Seitenwechsels vermisst. Beispiel-URL-Screenshot zu nehmen:

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

Wie die wiederholten Header mit diesem Code zu vermeiden ... Oder gibt es eine bessere Möglichkeit, den Python verwendet nur ...(ich weiß nicht, Java und möchte nicht Java verwenden).

Bitte sehen Sie sich den Screenshot des aktuellen Ergebnisses und den folgenden Beispielcode an.

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 

Antwort

4

Sie können dies erreichen, indem Sie die CSS des Headers vor dem Screenshot zu ändern:

EDIT: Setzen Sie diese Zeile nach dem Fenster blättern:

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

Also in Ihrem util.py wird es sein:

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

Wenn die Site die header verwendet Tag, Sie können es mit find_element_by_tag_name("header")

+0

hi danke .. nur oben zu Skript hinzufügen löst nicht das Problem .. aber ich verstehe die Bedeutung .. und deaktiviert die topnav .. mit Inspektor .. und müssen um das Javascript finden (nicht die CSS, die die CSS ändert .. und änderte das auf absolute .. manuell. und es hat funktioniert. (aber der Skript-Screenshot funktioniert immer noch nicht). Gibt es eine Möglichkeit, Ihr Skript zu verbessern, das die JavaScript-CSS-Änderung deaktiviert .. und für jede neue Website .. muss ich wieder um die #id der Header suchen .. und ändern Sie es. – ihightower

+0

Sie können nicht im Voraus wissen, wie jede Website ihren Header implementiert hat. Aber Sie können raten. Ich füge ein Beispiel hinzu. – Moshisho

+0

Ihr Code funktionierte, aber mit einigen kleineren Störungen .. das ist die Überschrift auf einigen Seiten enthalten. Also, nach dem Hinzufügen von Schlaf 0,2 Sekunden .. es hat perfekt funktioniert. Ich habe den Code aktualisiert und auch Ihre Antwort markiert. Ich hoffe, die Bearbeitung in Ihrer Antwort ist für Stackoverflow korrekt. – ihightower

5

tun, nachdem der Ansatz von @ kennen Moshisho.

Mein volles eigenständiges Arbeits Skript ... (hinzugefügt Schlaf 0,2 nach jeder Rolle und Position)

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

Ich änderte Code für Python 3.6, vielleicht wird es für jemanden nützlich sein:

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) 

Das funktioniert für mich. Es speichert die gesamte Seite als Screenshot. Für weitere Informationen können Sie die API-Dokumentation nachlesen: 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) 

Es gab einen Fehler in dem Code bereits in Zeile vorgeschlagen 2. Hier ist die eine korrigierte ist. Als Noob hier, nicht in der Lage, meinen eigenen Beitrag noch zu bearbeiten.

Manchmal werden die besten Ergebnisse nicht erzielt. So kann eine andere Methode verwenden, um Höhe aller Elemente zu erhalten und summieren sie die Aufnahmebildhöhe einzustellen, wie unten:

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) 

BTW, es auf FF funktioniert.

Verwandte Themen