Сделайте полный скриншот страницы в python без разрыва страницы - PullRequest
1 голос
/ 30 января 2020

Я пытаюсь сделать полный снимок экрана, но как-то не получается.

Первая попытка:

 def screenshot(self):
        self.driver.set_window_size(1920, 1080)
        self.driver.save_screenshot("screen_1")
        self.driver.get_screenshot_as_png()

Что я получаю:

enter image description here

Вторая попытка:

Я также попробовал приведенный ниже код, но кажется, что он разбивает изображения между ними при большой длине страницы.

def save_fullpage_screenshot(self):

        time.sleep(3)

        # get dimensions
        window_height = self.driver.execute_script('return window.innerHeight')
        scroll_height = self.driver.execute_script('return document.body.parentNode.scrollHeight')
        num = int(math.ceil(float(scroll_height) / float(window_height)))

        # get temp files
        tempfiles = []
        for i in range(num):
            fd, path = tempfile.mkstemp(prefix='{0}-{1:02}-'.format("ss_", i + 1), suffix=".png")
            os.close(fd)
            tempfiles.append(path)
            pass
        tempfiles_len = len(tempfiles)

        try:
            # take screenshots
            for i, path in enumerate(tempfiles):
                if i > 0:
                    self.driver.execute_script('window.scrollBy(%d,%d)' % (0, window_height))

                self.driver.save_screenshot(path)
                pass

            # stitch images together
            stiched = None
            for i, path in enumerate(tempfiles):
                img = Image.open(path)

                w, h = img.size
                y = i * window_height

                if i == (tempfiles_len - 1) and num > 1:
                    img = img.crop((
                        0,
                        h - (scroll_height % h),
                        w,
                        h
                    ))

                    w, h = img.size
                    pass

                if stiched is None:
                    stiched = Image.new('RGB', (w, scroll_height))

                stiched.paste(img, (
                    0,  # x0
                    y,  # y0
                    w,  # x1
                    y + h  # y1
                ))
                pass
            stiched.save("Y:\\ss\\s.png")
        finally:
            # cleanup
            for path in tempfiles:
                if os.path.isfile(path):
                    os.remove(path)
            pass

То, что я получаю в результате вывода вышеуказанный код:

enter image description here

1 Ответ

1 голос
/ 30 января 2020

Первая попытка не удалась, потому что Selenium делает снимки экрана только для порта просмотра. Вы можете получить полную страницу или указать скриншот элемента c, используя запрос к driver.command_executor. Использование take_element_screenshot на <body> даст те же результаты, что и take_full_page_screenshot

def __take_screenshot(self, clip=None):

    def send(cmd, params):
        url = f'{self.__driver.command_executor._url}/session/{self.__driver.session_id}/chromium/send_command_and_get_result'
        body = json.dumps({'cmd': cmd, 'params': params})
        return self.__driver.command_executor._request('POST', url, body).get('value')

    script = '({width: Math.max(window.innerWidth, document.body.scrollWidth, document.documentElement.scrollWidth)|0,' \
             'height: Math.max(innerHeight, document.body.scrollHeight, document.documentElement.scrollHeight)|0,' \
             'deviceScaleFactor: window.devicePixelRatio || 1, mobile: typeof window.orientation !== "undefined"})'

    data = {'format': 'png', 'fromSurface': True}
    if clip:
        data['clip'] = clip

    response = send('Runtime.evaluate', {'returnByValue': True, 'expression': script})
    send('Emulation.setDeviceMetricsOverride', response['result']['value'])
    screenshot = send('Page.captureScreenshot', data)
    send('Emulation.clearDeviceMetricsOverride', {})

    to_save = base64.b64decode(screenshot['data']) # same object as returned by driver.get_screenshot_as_png()
    im = Image.open(BytesIO(to_save))
    im.save('screenshot.png')

def take_element_screenshot(self, element):

    clip = self.__driver.execute_script('rect = arguments[0].getBoundingClientRect();'
                                        'docRect = arguments[0].ownerDocument.documentElement.getBoundingClientRect();'
                                        'return {x: rect.left - docRect.left, y: rect.top - docRect.top, width: rect.width, height: rect.height, scale: 1};', element)

    self.__take_screenshot(clip)

def take_full_page_screenshot(self):
    self.__take_screenshot()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...