截取网站的屏幕截图

常见的抓取任务是创建网站的屏幕截图。 在 Python 中,我们可以使用 selenium 和 webdriver 创建缩略图。

准备工作

本菜谱的脚本是 04/08_create_website_screenshot.py。 另外,请确保路径中有 selenium 并安装了 Python 库。

怎么做

运行示例的脚本。 脚本中的代码如下:

from core.website_screenshot_generator import WebsiteScreenshotGenerator
from core.file_blob_writer import FileBlobWriter
from os.path import expanduser

# get the screenshot
image_bytes = WebsiteScreenshotGenerator().capture("http://espn.go.com",500, 500).image_bytes

# save it to a file
FileBlobWriter(expanduser("~")).write("website_screenshot.png", image_bytes)

创建 WebsiteScreenshotGenerator 对象,然后调用其捕获方法,传递要捕获的网站的 URL 以及所需的图像宽度(以像素为单位)。

这将创建一个可以使用 .image 属性访问的 Pillow 图像,并且可以使用 .image_bytes 直接访问图像的字节。 该脚本获取这些字节并将它们写入您主目录中的 website_screenshot.png 文件。

您将看到该脚本的以下输出:

Connected to pydev debugger (build 162.1967.10)
Capturing website screenshot of: http://espn.go.com
Got a screenshot with the following dimensions: (500, 7416)
Cropped the image to: 500 500
Attempting to write 217054 bytes to website_screenshot.png:
The write was successful

我们得到的图像如下(图像的内容会有所不同):

image 2024 01 29 15 03 39 271

工作原理

以下是 WebsiteScreenshotGenerator 类的代码:

class WebsiteScreenshotGenerator():
    def __init__(self):
        self._screenshot = None

    def capture(self, url, width, height, crop=True):
        print ("Capturing website screenshot of: " + url)
        driver = webdriver.PhantomJS()

        if width and height:
            driver.set_window_size(width, height)

        # go and get the content at the url
        driver.get(url)

        # get the screenshot and make it into a Pillow Image
        self._screenshot = Image.open(io.BytesIO(driver.get_screenshot_as_png()))
        print("Got a screenshot with the following dimensions: {0}".format(self._screenshot.size))
        if crop:
            # crop the image
            self._screenshot = self._screenshot.crop((0,0, width, height))
            print("Cropped the image to: {0} {1}".format(width, height))

        return self

    @property
    def image(self):
        return self._screenshot

    @property
    def image_bytes(self):
        bytesio = io.BytesIO()
        self._screenshot.save(bytesio, "PNG")
        bytesio.seek(0)
        return bytesio.getvalue()

对 driver.get_screenshot_as_png() 的调用完成了繁重的工作。 它将页面渲染为 PNG 格式的图像并返回图像的字节。 然后该数据被转换为 Pillow Image 对象。

请注意,在输出中,从 webdriver 返回的图像的高度是 7416 像素,而不是我们指定的 500。 PhantomJS 渲染器将尝试处理无限滚动的网站,并且通常不会将屏幕截图限制为给定窗口的高度。

要实际使屏幕截图达到指定高度,请将裁剪参数设置为 True(默认值)。 然后这段代码将使用 Pillow Image 的 crop 方法来设置所需的高度。 如果您使用 Crop=False 运行此代码,则结果将是高度为 7416 像素的图像。