7

после опробования различных подходов ... Я наткнулся на эту страницу, чтобы сделать полный скриншот с хромированными ребрами, селеном и питоном.Выполнение скриншота полной страницы с Selenium Python (chromedriver)

исходный код здесь: http://seleniumpythonqa.blogspot.com/2015/08/generate-full-page-screenshot-in-chrome.html (и скопировать код в этой публикации ниже)

Он использует PIL и он прекрасно работает !!!!! Однако есть одна проблема ... которая фиксирует заголовки и повторы для всей страницы, а также пропускает некоторые части страницы во время смены страницы. Пример URL взять скриншот:

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

Как избежать повторяющихся заголовков с помощью этого кода ... Или есть лучший вариант, который использует питон только ...(я не знаю 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), который изменяет css .. и изменил это на абсолютное .. вручную. и это сработало. (но скриншот скрипта все равно не работает). Есть ли способ улучшить ur-скрипт, который отключает модификацию javascript css .. и для любого нового веб-сайта .. мне нужно снова копаться, чтобы найти #id заголовка .. и изменить его. – ihightower

+0

Вы не можете заранее знать, как каждый сайт реализовал свой заголовок. Но вы можете предположить. Я добавлю пример. – Moshisho

+0

ваш код работал, но с небольшим сбоем .. то есть он включал заголовок на некоторых страницах. Итак, после добавления сна 0,2 секунды .. он работал отлично. Я обновил код и также отметил ваш ответ. Надежда, сделавшая редактирование в вашем ответе, верна для stackoverflow. – ihightower

5

Узнав подход @ Moshisho.

Мой полный автономный рабочий сценарий ... (добавлен сон 0,2 после каждого свитка и положения)

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

Я изменил код для Python 3.6, может быть, это будет полезно для кого-то:

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) 

Это работает для меня. Он сохраняет всю страницу как снимок экрана. Для получения дополнительной информации вы можете прочитать АНИ документы: 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. Вот исправленный один. Будучи здесь noob, я пока не могу редактировать свой собственный пост.

Иногда baove не получает лучших результатов. Таким образом, можно использовать другой метод, чтобы получить высоту всех элементов и суммировать их, чтобы установить высоту захвата, как показано ниже:

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) 

Кстати, он работает на FF.

 Смежные вопросы

  • Нет связанных вопросов^_^