使用ChromeDriver下载图片(jpeg、png)或PDF的Python Selenium方法

3
我是一名能翻译文本的助手。
我有一个使用ChromeDriver在Windows系统上编写的Python Selenium脚本,它可以从网页中获取各种附件(不同类型的文件)的下载链接,并打开这些链接以下载这些附件。对于那些ChromeDriver不能预览的文件类型,这个脚本可以正常工作并自动下载。但是对于图片(JPEG、PNG)和PDF文件,默认情况下会进行预览,因此不会自动下载。
目前我正在使用的ChromeDriver选项只适用于无法预览的文件。
chrome_options = webdriver.ChromeOptions()
prefs = {'download.default_directory' : 'custom_download_dir'}
chrome_options.add_experimental_option('prefs', prefs)
driver = webdriver.Chrome("./chromedriver.exe", chrome_options=chrome_options)

这将文件下载到“custom_download_dir”,没有问题。但是可以预览的文件只在ChromeDriver实例中预览,而不会下载。
是否有ChromeDriver设置可以禁用此预览行为并直接下载所有文件,而不考虑扩展名?
如果没有,例如可以使用Firefox完成吗?
3个回答

5

不要依赖特定的浏览器/驱动程序选项,我会使用图像URL实现更通用的解决方案来执行下载操作。

您可以使用类似的代码获取图像URL:

driver.find_element_by_id("your-image-id").get_attribute("src")

然后我会使用例如urllib这样的工具来下载图片。

以下是Python2的伪代码:

import urllib

url = driver.find_element_by_id("your-image-id").get_attribute("src")
urllib.urlretrieve(url, "local-filename.jpg")

这是Python3相同的操作:

import urllib.request

url = driver.find_element_by_id("your-image-id").get_attribute("src")
urllib.request.urlretrieve(url, "local-filename.jpg")

在评论后进行编辑,这是另一个关于如何在知道文件URL后下载文件的示例:

import requests
from PIL import Image
from io import StringIO

image_name = 'image.jpg'
url = 'http://example.com/image.jpg'

r = requests.get(url)

i = Image.open(StringIO(r.content))
i.save(image_name)

3
问题是要查看图片,我需要进行身份验证。我尝试使用Python Requests库并且它需要Kerberos身份验证,我尝试提供凭据和使用Python Kerberos库,但它就是不起作用。我可以通过Selenium WebDriver查看它,因此我正在寻找通过WebDriver实例本身下载的方法。 - animesharma
禁用Google Chrome上的图像自动打开怎么样?这可能会触发自动下载... http://www.presentermedia.com/blog/2013/10/my-file-automatically-opens-instead-of-saving-with-chrome/ - Pitto
1
在Python中的Chrome WebDriver设置中是否有禁用自动打开选项的选项? - animesharma
@halfer 看起来 urlretrieve 已经过时了。有没有更新、更好的方法来完成这个任务? - oldboy
2
没问题,@oldboy。Pitto,感谢您的编辑 - 不要忘记引起人们的注意。只有订阅您的答案的人才会看到更改,所以在这种情况下可能已经被忽略了。 - halfer

3
通过使用 selenium-wire 库,可以通过 ChromeDriver 下载图片。
我已经定义了以下函数来解析每个请求,并在必要时将请求正文保存到文件中。
import os
from mimetypes import guess_extension
from seleniumwire import webdriver

def download_assets(requests, asset_dir="temp", default_fname="untitled", exts=[".png", ".jpeg", ".jpg", ".svg", ".gif", ".pdf", ".ico"]):
    asset_list = {}
    for req_idx, request in enumerate(requests):
        # request.headers
        # request.response.body is the raw response body in bytes
        ext = guess_extension(request.response.headers['Content-Type'].split(';')[0].strip())
        if ext is None or ext not in exts:
            #Don't know the file extention, or not in the whitelist
            continue

        # Construct a filename
        fname = os.path.basename(request.url.split('?')[0])
        fname = "".join(x for x in fname if (x.isalnum() or x in "._- "))
        if fname == "":
            fname = f"{default_fname}_{req_idx}"
        if not fname.endswith(ext):
            fname = f"{fname}{ext}"
        fpath = os.path.join(asset_dir, fname)

        # Save the file
        print(f"{request.url} -> {fpath}")
        asset_list[fpath] = request.url
        with open(fpath, "wb") as file:
            file.write(request.response.body)
    return asset_list

让我们从Google主页下载一些图像到temp文件夹中。

# Create a new instance of the Chrome/Firefox driver
driver = webdriver.Chrome()

# Go to the Google home page
driver.get('https://www.google.com')

# Download content to temp folder
asset_dir = "temp"
os.makedirs(asset_dir, exist_ok=True)
download_assets(driver.requests, asset_dir=asset_dir)

driver.close()

请注意,该函数可以进行改进,以便保留目录结构。

1

这里还有另一种简单的方法,但是@Pitto's answer above更加简洁。

import requests

webelement_img = ff.find_element(By.XPATH, '//img')
url = webelement_img.get_attribute('src') or 'https://someimages.com/path-to-image.jpg'
data = requests.get(url).content
local_filename = 'filename_on_your_computer.jpg'

with open (local_filename, 'wb') as f:
    f.write(data)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接