在python中拍摄完整的页面截图,无需分页符

2024-04-20 16:34:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图拍摄整页截图,但不知怎么的,它不起作用

第一次尝试:

 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


Tags: pathinselfimgforifsavedriver
1条回答
网友
1楼 · 发布于 2024-04-20 16:34:43

第一次尝试失败,因为Selenium仅拍摄视图端口的屏幕截图。您可以使用对driver.command_executor的请求获取完整页面或特定元素的屏幕截图。在<body>上使用take_element_screenshot将产生与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()

相关问题 更多 >