使用 Python 从网站下载所有图像

单独从网页下载所有图像可能是一件令人头痛且耗时的事情。创建简短的 Python 脚本可以使工作变得更轻松。网站的图像通常采用 .jpg、.jpeg 或 .png 格式。这是有用的信息,因为它将有助于建立代码。网页中的图像通常使用HTML的<img>标签来实现。代码中使用的工具是BeautifulSoup和Python的requests库。BeautifulSoup是一个著名的网页抓取库,它解析网页的HTML内容,并根据HTML标签获取网页中的所有内容。requests库可用于获取网页的HTML文本,也称为源代码。

代码中使用的网站是Yoast上的博客。该博客教用户使用图像开发更好的 SEO 算法。之所以选择该网站是因为它包含大量图像。

这是网站的屏幕截图:

使用网站截图2

该代码将首先使用 requests 模块获取 HTML 页面。BeautifulSoup 将从 <img> 标签中提取所有详细信息。使用 get() 方法,图像的来源将存储在列表中。这些图像的内容将使用 BeautifulSoup 提取,并使用 Python 中的文件处理将其写入图像文件。

requests 模块和 BeautifulSoup 可以在 Command Shell 中使用 pip 安装:

>>> pip install requests
>>> pip install bs4

从网站中提取内容

该代码首先会以字符串形式从网站中提取 HTML 内容。然后,<img> 标签内容将使用 BeautifulSoup 存储在列表中。其内容将包含整个 <img> 标记及其规范和内容值。HTML 提取将使用请求输出的内容属性来完成。以下代码演示了相同的内容:

1
2
3
4
5
6
7
8
from bs4 import BeautifulSoup
import requests
import os
os.mkdir('images')
images=[]
url='https://yoast.com/using-images-in-your-blog-post/'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36', 'Referer': 'https://www.google.com/', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8'}
cont=requests.get(url,headers=headers).content

应该注意的是, headers 属性也被传递给请求的 get() 方法。这样做是为了确保我们的代码的 IP 地址不会被视为机器人而被阻止,并且可以访问网页 HTML。os 模块也被导入,它的 mkdir() 函数用于创建一个名为“images”的文件夹。在此文件夹中,将保存所有下载的图像。requests.get() 方法的 content 属性以字符串格式向用户提供整个网页 HTML 的内容。这是作为 BeautifulSoup 的输入提供的,如下所示:

9
10
soup=BeautifulSoup(cont,'html.parser')
imgall=soup.find_all('img')

应该注意的是,BeautifulSoup 函数有两个输入,第一个是前面讨论的网页 HTML,第二个是 HTML 解析器。在 BeautifulSoup 中,“html.parser”是默认的解析器,但它还提供其他解析选项。imgall 变量是一个列表,其中包含 BeautifulSoup 的 find_all() 函数找到的所有 <img> 标签。但必须提取 imgall 中值的属性才能获得精确的图像。

另请阅读:Python Beautiful Soup for Easy Web Scraping

从网页中提取并保存图像

从 HTML 中获取所有 <img> 标签后,下一步的工作是在每个 <img> 标签中搜索图像的源链接。图像可以直接从Google、Pixabay、Unsplash等免费图像存储库复制,或上传到网页服务器上。如果它是 WordPress 管理的页面,WordPress 会为其用户上传图像。所有此类图像都可以使用 Python 下载。源码提取如下图所示:

11
12
13
14
15
16
17 号
18
19
20
21
22
23
24
25
for img in imgall:
    try:
        imgsrc=img['data-srcset']
    except:
        try:
            imgsrc=img['data-src']
        except:
            try:
                imgsrc=img['data-fallback-src']
            except:
                try:
                    imgsrc=img['src']
                except:
                    pass
    images.append(imgsrc)

需要注意的是,上面的代码片段使用了嵌套的 try- except 来查找图像的源链接。源链接通常存储在 <img> 标记中的四个源属性之一中:

  • 数据源集
  • 数据源
  • 数据后备-src
  • 源代码

imgall 列表中每个 <img> 标记的所有这四个属性都会检查源链接。如果在data-srcset属性中找到了源链接,则无需检查data-src属性等。这将创建一个优先级树来选择最干净、最直接的可用源链接。如果在 <img> 标签中找不到任何属性,则跳过该标签。源链接将附加到在第一个代码片段中创建的图像列表中。

另请阅读:Python 异常处理——尝试、例外、最后

可以使用 requests 模块将图像下载为二进制图像。requests.get() 方法的 content 属性以图像作为 URL,提供图像的二进制内容。这些内容可以写入文件以生成下载的图像。它如下面的代码片段所示:

26
27
28
29
30
31
32
33
34
35
36
37
38
imgsdownloaded=0
imgsnotdownloaded=0
for image in images:
    if '.svg' in image:
        imgsnotdownloaded=imgsnotdownloaded+1
    else:
     r=requests.get(image).content
     filename='images/image'+str(imgsdownloaded)+'.jpg'
     with open(filename,'wb+') as f:
        f.write(r)
     imgsdownloaded=imgsdownloaded+1
print(f'{imgsdownloaded} Images Downloaded')
print(f'{imgsnotdownloaded} Images failed to Download')

创建 imgsdownloaded 变量是因为它有助于命名下载的图像。该代码获取图像列表中的每个链接,获取其二进制内容,并将其写入文件。文件存放在新建的images文件夹中,每张图片依次命名,第一张图片为image0.jpg,第二张图片为image1.jpg,依此类推。应该注意的是,所有图像都转换为 .jpg 格式。唯一不支持的格式是 .svg 格式,如果遇到该格式,则会跳过该格式。

图像的二进制内容是使用 Python 文件处理中的“wb+”属性写入的。该属性允许用户在文件中写入和编辑二进制值。程序最后打印下载的图像数量和下载失败的图像数量。运行代码后可以看到如下输出:

编码端子输出

左侧的列显示图像文件夹中新生成的图像的列表。终端显示代码输出为 54 个图像已成功下载,而 2 个图像下载失败。

输出到计算机目录

博客中还附加了两张图像,供用户查看从网站提取的输出图像。这些图像可以在网站上轻松看到。

代码的输出图像
代码的另一个输出图像

从网站下载所有图像的完整代码

下面给出完整代码,供参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 号
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from bs4 import BeautifulSoup
import requests
import os
os.mkdir('images')
images=[]
url='https://yoast.com/using-images-in-your-blog-post/'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36', 'Referer': 'https://www.google.com/', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8'}
cont=requests.get(url,headers=headers).content
soup=BeautifulSoup(cont,'html.parser')
imgall=soup.find_all('img')
for img in imgall:
    try:
        imgsrc=img['data-srcset']
    except:
        try:
            imgsrc=img['data-src']
        except:
            try:
                imgsrc=img['data-fallback-src']
            except:
                try:
                    imgsrc=img['src']
                except:
                    pass
    images.append(imgsrc)
imgsdownloaded=0
imgsnotdownloaded=0
for image in images:
    if '.svg' in image:
        imgsnotdownloaded=imgsnotdownloaded+1
    else:
     r=requests.get(image).content
     filename='images/image'+str(imgsdownloaded)+'.jpg'
     with open(filename,'wb+') as f:
        f.write(r)
     imgsdownloaded=imgsdownloaded+1
print(f'{imgsdownloaded} Images Downloaded')
print(f'{imgsnotdownloaded} Failed to download')

结论

BeautifulSoup 和 requests 模块可以被认为是 Web Scraper 武器库中最强大的武器。使用网页抓取从网站下载所有图像是一项简单的任务。只需几行代码即可将繁琐的任务减少为少量工作。因此可以得出结论,使用 Python 从网页下载所有图像比手动下载更容易。