文章目录
前言
如果你需要大量图像,而一张一张保存的想法已经让你感到厌烦,那你并不孤单。在为机器学习项目准备数据集时,这种工作尤其令人疲惫。好消息是,网页抓取通过让你在几个步骤内收集大量图像,使整个过程更快、更易于管理。在这篇博文中,我们将指导你通过一种直接的方法从静态网站抓取图像。我们将使用 Python、几个便捷的库以及代理来保持一切顺利运行。

一、Python 图像抓取的工作原理
在抓取图像之前,了解底层实际发生的事情会很有帮助。在大多数情况下,工作流程如下:
- 使用 HTTP 请求访问目标页面
- 解析 HTML 以提取图像 URL
- 将图像下载到你的计算机供后续使用
当网站向每个访问者提供相同的 HTML 时,这个流程是直接的。当页面的某些部分由 JavaScript 生成时,事情会变得更复杂,这就引出了一个重要的区别。
1.1. 静态网站与动态网站
静态网站提供固定的 HTML。你看到的内容正是服务器上存储的内容,其他人看到的也是同样的东西。这使得静态网站成为抓取的理想选择,因为 HTML 已经包含了你需要的所有图像 URL。
**动态网站则动态生成内容。**服务器或客户端 JavaScript 会为每个访问者定制页面,通常基于账户数据、浏览历史、位置或天气、股票更新等实时信息等因素。动态网站需要不同的方法,因为这些页面可能不会在初始 HTML 中暴露图像 URL,这意味着你需要能够完全渲染页面后再提取任何内容的工具。
这两种类型都很常见,尽早了解区别将帮助你为抓取器选择正确的方法。
1.2. 判断网站是静态还是动态
识别动态网站的快速方法是,当它用个性化内容向你打招呼时,从"欢迎回来"到关于你之前查看过的项目的提醒。这种定制行为表明页面是动态生成的,而不是作为固定 HTML 提供的。
更一般地说,你可以查看几个简单的指标。静态网站倾向于向每个访问者提供相同的不变内容,通常存储为直接的 HTML 文件。动态网站混合了用户登录、个性化推荐、搜索驱动的结果或根据你输入的内容更新的表单等元素。你还可能注意到 URL 行为的差异:静态页面通常保持相同的地址,而动态页面通常在你与它们交互时生成新的查询参数或更改 URL。
考虑内容本身的性质也很有帮助。频繁更新的页面(如天气服务、新闻源或股票信息)几乎总是动态的,因为数据每次都是从数据库或 API 中提取的。相比之下,静态网站仅在有人手动更新时才会更改。
二、为 Python 图像抓取选择正确的工具
Python 为你提供了多种获取和处理图像的方法。每种工具都有其优势,因此选择正确的工具取决于网站的行为方式。让我们概述几个流行的库以及何时使用它们。
2.1. Requests + Beautiful Soup
对于抓取静态网站,这个组合通常是最高效的选择。Requests 获取页面的 HTML,而 Beautiful Soup 使导航该 HTML 并直接提取图像 URL 变得容易。当你需要的内容已经存在于初始源代码中而没有任何 JavaScript 操作时,这个过程快速、轻量且理想。
2.2. urllib
如果你想将依赖项保持在最低限度,urllib 可以仅使用 Python 的标准库处理页面请求和文件下载。它不如 requests 和 BeautifulSoup 流畅,但当你需要一种简单的方式访问页面并保存图像而不引入额外的包时,它可以完成工作。
2.3. Selenium
动态或 JavaScript 驱动的网站通常仅在脚本运行或用户操作发生后才加载图像。在这些情况下,Selenium 是最可靠的解决方案。它自动化真实的浏览器环境,允许页面在你提取图像 URL 之前完全渲染。这使其适用于更复杂的抓取任务,在这些任务中,单独的请求无法揭示必要的内容。
2.4. Playwright
Playwright 是浏览器自动化的更现代化替代方案,特别适用于动态、JavaScript 密集的页面。与 Selenium 一样,它控制真实浏览器,但它提供了更快的执行速度、对无头浏览的内置支持,以及用于等待网络活动、处理多个页面和使用经过身份验证的代理等任务的更清晰 API。如果你从头开始或关心可靠性和开发者体验,Playwright 通常是从动态网站抓取图像的更好选择。
2.5. Pillow
Pillow 不是抓取工具,但在图像下载后很有用。你可以使用它调整大小、转换格式、检查尺寸或在存储或进一步处理文件之前进行其他调整。它完全是可选的,但如果你的工作流程涉及为数据集、机器学习模型或进一步分析准备图像,它会很有帮助。
三、构建简单 Python 图像抓取器所需的内容
让我们使用 Python 构建两个脚本:一个用于从静态网站抓取图像,另一个用于从动态页面收集图像。但在运行脚本之前,你需要准备一些必需品。以下是需要准备的内容:
- **Python 3.7 或更高版本。**确保你的系统上安装了 Python。你可以从官方 Python 网站下载。要验证安装,打开终端并运行:
python --version
- **文本编辑器或 IDE。**你需要一个地方来编写和运行代码。Visual Studio Code、PyCharm,甚至是与系统终端配对的简单文本编辑器都可以。
- **Requests。**这个库发送 HTTP 请求来获取网页。它轻量且非常适合从静态网站抓取 HTML。
- **Beautiful Soup。**一旦你有了 HTML,Beautiful Soup 会解析它并让你提取特定元素,如图像标签。它是导航 HTML 结构的首选工具。
- **Playwright。**对于使用 JavaScript 加载内容的动态网站,Playwright 自动化真实的浏览器会话。它在你抓取之前完全渲染页面,确保你捕获不会显示在原始 HTML 中的图像。
使用单个命令安装这三个库:
pip install requests beautifulsoup4 playwright
安装 Playwright 后,你还需要下载它使用的浏览器二进制文件:
playwright install
- **代理。**两个脚本都使用动态住宅代理来掩盖你的 IP 地址,并在抓取多个页面时避免被阻止。如果没有代理,网站可能会检测到你的自动化活动并限制访问。住宅或轮换代理最适合此用途。
Decodo 提供成功率为 99.86%、平均响应时间低于 0.6 秒的住宅代理,并提供 3 天免费试用。以下是入门方法:
- 在 Decodo 仪表板上创建账户
- 在左侧面板上,选择动态住宅代理
- 选择订阅、Pay As You Go计划或申请 3 天免费试用
- 在代理设置标签中,配置你的位置和会话偏好
- 复制你的代理凭据以集成到抓取脚本中
四、如何从静态网站抓取图像
我们将从一个基本的抓取器开始,它专为公开显示图像而不涉及任何脚本的页面设计。这种方法使用轻量级工具,如 Requests 获取页面和 Beautiful Soup 解析它,使其成为一个干净、适合初学者的起点。由于不需要动态加载任何内容,这是学习图像提取工作原理的直接方法。
4.1. 检查目标网站
静态网站很直接,因为所有内容都已经嵌入到页面的 HTML 中。要确认这一点,你可以在浏览器中打开网站,右键单击图像,并使用开发者工具检查其 标签。检查它是否包含 src 或 srcset 等属性,以及显示的图像是使用完整 URL 还是相对路径。对于静态页面,你在 DevTools 中看到的正是你将要抓取的内容。
4.2. 提取图像 URL
静态脚本向网站发送简单的 GET 请求,然后将其 HTML 输入到专门搜索 标签的解析器中。每个标签都包含指向图像文件托管位置的属性。脚本循环遍历这些标签并收集它们的 URL。不需要动态加载任何内容,因此不需要渲染页面或触发 JavaScript。HTML 源代码已经告诉我们一切。
4.3. 下载图像
收集 URL 后,脚本逐个浏览它们并将每个图像下载到你的计算机。它从 URL 构建文件名,发出另一个 HTTP 请求来获取图像数据,并将其存储在本地文件夹中。如果网站使用相对路径,脚本会将它们与主网站地址结合起来,以确保每个图像链接都有效。最终结果是一个充满直接从静态页面获取的图像的文件夹。
4.4. 处理常见问题
即使是静态页面也可能带来麻烦。某些服务器会拒绝自动化抓取,除非发送 User-Agent 标头,因此添加简短的类似浏览器的标识符可以帮助避免 4xx 错误。对于此类错误,更好的解决方案是使用动态住宅代理。需要注意的其他事项包括损坏的图像标签、重复的图像名称以及需要优雅跳过的缺失 URL。只要网站没有主动阻止机器人,这些检查通常就足以成功抓取。
五、静态网站的完整图像抓取器代码
将以下代码保存为 .py 文件并在终端或首选 IDE 中运行。添加你的代理详细信息并粘贴你想要抓取的目标 URL,然后启动脚本。它会扫描网站,提取它找到的每个图像源,并直接在终端中打印这些 URL。从那里,它会自动下载每个文件并将其保存到本地文件夹,为你提供一个可供使用的干净图像集合。
from bs4 import BeautifulSoup
import requests
html_page = "https://help.decodo.com/docs/how-do-i-use-proxies"
proxy = f'http://YOUR_PROXY_USERNAME:YOUR_PROXY_PASSWORD@gate.decodo.com:7000'
response = requests.get(html_page, proxies={'http': proxy, 'https': proxy})
soup = BeautifulSoup(response.text, 'html.parser')
for img in soup.findAll('img'):
if img.get('src') != None:
print(img.get('src'))
img_url = img.get('src')
name = img_url.split('/')[-1]
img_response = requests.get(img_url)
file = open(name, "wb")
file.write(img_response.content)
file.close()
六、如何从动态网站抓取图像
对于依赖 JavaScript 的网站,抓取需要更多力量。图像通常仅在页面完全渲染后才出现,因此标准的 HTTP 请求是不够的。在这里,我们将使用浏览器自动化库 Playwright 来加载内容,在需要时进行交互,然后像用户看到的那样提取图像源。
6.1. 检查目标网站
动态页面通常将其图像隐藏在 JavaScript 后面。打开 DevTools 可以让你看到 标签仅在页面完全加载后才出现,或者源字段不包含常规 URL。在 src 属性中看到 base64 编码的 blob 是很常见的,这意味着图像嵌入在页面内而不是单独托管。检查页面可以揭示脚本是否必须等待元素出现或手动解码图像。
6.2.提取图像 URL
与静态网站不同,你不能简单地下载 HTML 并解析它。相反,动态脚本在后台启动浏览器会话,访问页面,并等待网络活动稳定下来,以便所有 JavaScript 内容都已加载完成。一旦页面完全渲染,它会查询所有 元素,就像用户看到的那样。一些图像返回正常 URL,而另一些是嵌入到文档中的 base64 字符串。脚本对两种类型进行分类,以便可以分别处理它们。
6.3.下载图像
在此脚本中,HTTP 请求将图像保存到本地文件夹。嵌入的 base64 图像需要不同的方法:脚本直接解码 base64 数据并将其作为二进制文件写入磁盘,而不是发出网络请求。这两种方法最终都会进入同一个图像目录,但一个来自网络,而另一个来自页面的编码内容。
6.4. 处理常见问题
动态网站带来了自己的挑战。因为它们依赖 JavaScript,脚本可能需要更长的等待时间来加载图像、重试渲染或暂停以等待网络请求完成。一些页面使用反机器人逻辑,因此通过代理抓取或使用逼真的浏览器标头有助于融入正常流量。缺失或损坏的图像源和重复的文件名也很常见,因此脚本会检查重复项并跳过无法使用的条目。有了这些保障措施,即使是严重脚本化的页面也变得易于抓取。
七、动态网站的完整图像抓取器代码
将脚本保存为 .py 文件,添加你的代理详细信息和目标 URL,然后从终端或 IDE 运行它。此脚本在无头浏览器中打开页面,等待内容渲染,然后收集它找到的每个图像源。在执行过程中,脚本会报告其进度,首先显示它正在加载的页面,然后显示检测到多少图像,最后在保存时打印每个下载的文件名。当工作完成时,它会确认成功存储了多少文件以及可以在计算机上的何处找到它们。
from playwright.sync_api import sync_playwright
import requests
from urllib.parse import urljoin
import os
target_url = "https://www.bbc.co.uk/news/topics/c2vdnvdg6xxt"
output_dir = "images"
proxy = "https://YOUR_PROXY_USERNAME:YOUR_PROXY_PASSWORD@gate.decodo.com:7000"
os.makedirs(output_dir, exist_ok=True)
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy={"server": proxy.split("@")[1], "username": proxy.split("//")[1].split(":")[0], "password": proxy.split(":")[2].split("@")[0]}
)
page = browser.new_page()
print(f"Loading: {target_url}")
page.goto(target_url, wait_until="domcontentloaded", timeout=60000)
page.wait_for_timeout(5000)
for i in range(5):
page.evaluate("window.scrollBy(0, window.innerHeight)")
page.wait_for_timeout(1500)
image_urls = []
for img in page.query_selector_all("img"):
src = img.get_attribute("src") or img.get_attribute("data-src")
if src and not src.startswith("data:"):
full_url = urljoin(target_url, src)
if full_url.startswith("http"):
image_urls.append(full_url)
browser.close()
print(f"Found {len(image_urls)} images\n")
downloaded = 0
for img_url in image_urls:
try:
name = img_url.split("/")[-1].split("?")[0]
if not name:
name = f"image_{image_urls.index(img_url)}.jpg"
img_response = requests.get(img_url, proxies={'http': proxy, 'https': proxy}, timeout=15)
if len(img_response.content) > 1000:
file = open(os.path.join(output_dir, name), "wb")
file.write(img_response.content)
file.close()
downloaded += 1
print(f"Downloaded: {name}")
except:
pass
print(f"\nCompleted: {downloaded} images saved to file://{os.path.abspath(output_dir)}")
八、高级技巧和最佳实践
一旦你有了一个基本的抓取器在工作,你可以通过添加一些额外的功能和保障措施使其更强大且更易于维护。
将抓取的数据保存到 CSV 文件或数据库可以帮助你跟踪收集的内容并在以后重用数据。除了仅下载图像,你还可以存储每个图像 URL 以及来源页面、时间戳和捕获的任何元数据等字段。对于简单项目,CSV 文件通常就足够了。对于更大的工作流程或与其他工具的集成,将记录推送到数据库使过滤和查询变得更加容易。
抓取图像元数据可能与图像本身一样有价值。当你已经循环遍历 元素时,你还可以读取 alt、title、尺寸或自定义数据属性等属性。如果页面在图像附近包含标题、摄影师姓名、标签或类别标签,也可以通过检查 HTML 中的相邻元素来收集这些内容。当你为机器学习构建数据集或希望以后进行更好的搜索和过滤时,这特别有用。
许多现代网站依赖无限滚动或延迟加载,这意味着新图像仅在你滚动或与页面交互后才出现。浏览器自动化工具允许你通过分步滚动、单击加载更多按钮或等待新元素出现来模拟这些操作。在实践中,脚本执行用户会执行的相同操作,然后对新加载的内容重复提取逻辑。
要成为负责任的抓取者,添加速率限制并避免压倒网站是很重要的。在请求之间引入小延迟、限制单次运行中获取的页面数量以及重用现有连接可以减少服务器负载,并使你的抓取器不太可能被阻止。使用逼真的标头并且不用快速连续的请求轰炸端点会有很大帮助。
最后,稳固的错误处理和日志记录将脆弱的脚本变成可靠的工具。网络超时、缺失属性、重定向和意外的 HTML 更改都很常见。将你的请求和解析逻辑包装在 try-except 块中、记录失败的 URL 并在出现问题时打印清晰的消息将帮助你快速调试。随着时间的推移,这些日志成为你的抓取器行为以及网站哪些部分更容易出现问题的有用记录。
九、示例项目和用例
图像抓取的用处远不止简单的下载。一旦你开始大规模收集图像,相同的技术可以支持广泛的实际项目。
一个常见的应用是为机器学习构建数据集。许多计算机视觉模型依赖于大型、组织良好的图像集合,这些集合不仅包括文件,还包括标签、描述或类别等元数据。通过从精选网站抓取数千个视觉内容并将它们与标签或 alt 文本配对,你可以快速组装用于对象识别、风格检测或推荐系统等任务的训练数据。
在营销研究中,图像抓取帮助团队跟踪趋势、竞争对手品牌、视觉广告主题或产品设计发展。从着陆页、电子商务列表或社交活动中收集图像使分析品牌如何展示自己、跨行业重用哪些风格或视觉消息如何随时间变化变得更容易。这些数据可以转化为品牌战略、创意方向或产品定位的见解。
内容聚合是另一个实际用例。出版商和社区平台可以从多个来源提取视觉内容并将它们整理到画廊、信息流、新闻简报或灵感板中。当与标题、作者或类别等元数据结合使用时,就可以创建可搜索的档案或自动更新内容流。在这些情况下,抓取的图像不仅仅是原始文件,它们形成支持新产品、发现工具和编辑工作的结构化集合。
总结
使用 Python 抓取图像可以根据网站的要求变得简单或高级。静态页面允许你使用 Requests 和 Beautiful Soup 等工具快速获取视觉内容,而动态、JavaScript 驱动的平台则需要使用 Playwright 进行浏览器自动化。一旦你学会检查页面、提取源并保存文件,你就能够高效地收集视觉数据并使你的方法适应几乎任何网站。
从这里开始,真正的价值在于你如何使用收集的图像。你可能会为机器学习构建数据集、分析视觉内容用于营销或研究,或者将它们组织成可搜索的档案。随着你的需求增长,你可以将元数据存储在数据库中、自动化重复抓取或使用代理和云工具进行扩展,将简单的脚本转变为强大、可重用的工作流程。
1万+

被折叠的 条评论
为什么被折叠?



