单独从网页下载所有图像可能是一件令人头痛且耗时的事情。创建简短的 Python 脚本可以使工作变得更轻松。网站的图像通常采用 .jpg、.jpeg 或 .png 格式。这是有用的信息,因为它将有助于建立代码。网页中的图像通常使用HTML的<img>标签来实现。代码中使用的工具是BeautifulSoup和Python的requests库。BeautifulSoup是一个著名的网页抓取库,它解析网页的HTML内容,并根据HTML标签获取网页中的所有内容。requests库可用于获取网页的HTML文本,也称为源代码。
代码中使用的网站是Yoast上的博客。该博客教用户使用图像开发更好的 SEO 算法。之所以选择该网站是因为它包含大量图像。
这是网站的屏幕截图:
该代码将首先使用 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> 标签中找不到任何属性,则跳过该标签。源链接将附加到在第一个代码片段中创建的图像列表中。
可以使用 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 从网页下载所有图像比手动下载更容易。