抓取图片听起来很简单——找到URL,下载文件。但在实际操作中,现代网络让这个过程的几乎每个环节都比想象中要困难得多:图片库会在滚动时延迟加载,图片URL会被CDN签名,最高质量的版本需要悬停鼠标才能显示,而且任何值得抓取的网站都配备了反机器人防御机制,只需几百次请求,就会将一个简单的脚本标记为可疑。
本指南介绍了2026年切实可行的方法,涵盖从一次性浏览器扩展到生产级Python管道的各种方案,还包括大多数教程都会忽略的内容:处理JavaScript渲染的内容、绕过热链接保护,以及越来越难以忽视的法律与伦理层面。
根据您的实际需求选择相应的方法
图像抓取大致可分为四个层次,选择合适的工具取决于数据量、目标以及操作频率。
一级 — 一次性、小批量、单一站点。使用浏览器扩展程序,或右键点击并保存。除此之外的做法都有些小题大做。
第2级——来自单个网站的数十至数百张图片。可使用专用的图片提取工具,或编写一个能遍历单个页面的简单Python脚本。
第3级——跨越多个页面或网站的数千张图片。一个真正的爬虫脚本,具备合理的速率限制、重试逻辑和存储功能。
第4级——持续、大规模的数据采集(机器学习训练数据、持续的市场调研)。一个具备轮换代理、无头浏览器支持和真实数据存储的生产管道。
关于这个话题的大多数文章都将这两者混为一谈。第一层级的正确方法与第四层级确实不同,而不仅仅是后者的缩小版。
第一类:浏览器扩展程序
若要从单个页面抓取十几张图片,浏览器扩展程序依然是最快捷的方式。目前值得安装的扩展程序有:
- 图片下载器 (Chrome)——支持按尺寸和文件类型筛选,操作简便,可批量下载。堪称最接近“万能默认”的工具。
- Imageye (Chrome、Edge)——功能集相似,尺寸和格式筛选界面设计良好。
- DownThemAll!(Firefox)——一款经久不衰的经典工具,至今仍在维护中,支持的文件类型不仅限于图片。
请避免使用超过一年未更新的扩展程序(2020年推出的许多“双击下载”工具如今已被弃用或暗藏恶意——Chrome扩展商店早已沦为“坟场”)。安装任何扩展程序前,请先查看其最后更新日期。
任何扩展程序的局限之处在于:你仍然需要手动加载每一页。一旦图片数量超过几百张,你的手就会抽筋。
第2层:图像提取工具和无界面工具
比扩展程序更进一步:这类工具只需输入一个网址,就能从渲染出的页面中提取所有图片。虽然大多数工具每次只能处理一个网站,但能帮你省去逐一点击的麻烦。
对于一次性任务,最简单的做法通常就是 wget 在命令行中:
bash
wget -r -l 2 -A jpg,jpeg,png,webp,gif --no-parent https://example.com/gallery/
该命令可从一个 URL 递归下载两层深度的图片,并过滤为图片文件类型。25 年来,它一直存在于每个 Linux 发行版中,至今仍适用于静态网站。对于 Windows 系统,其对应命令是 curl 或 PowerShell 的 Invoke-WebRequest.
对于那些您不愿编写脚本的网站,以下这些经得起考验的无代码工具值得推荐:Octoparse(依然稳定,采用免费增值模式), Apify (更偏向开发者,提供包含图像专用爬虫在内的现成爬虫市场), Bardeen (较新,基于浏览器扩展,可与其他工作流工具集成)。ParseHub已不再像三年前那样是首选推荐——其免费套餐的限制已大幅收紧。
这些工具支持分页、基本的 JavaScript 渲染以及 CSV 格式的导出。但在安全措施严密的网站上,或者在需要登录才能访问且支持无限滚动的网站上,它们就会开始失效。
第3级:Python——在职开发者的首选语言
如果要真正实现大规模应用,就自己动手写吧。在2026年仍能稳定运行的Python技术栈其实很简单:
requests— 获取页面并下载图片文件BeautifulSoup— 解析 HTML 并查找<img>标签和srcset属性Playwright— 当网站需要使用 JavaScript 来渲染图片时,会调用一个真正的无头浏览器Pillow— 处理下载的图像(调整大小、去重、验证格式)
静态页面的基本流程:
python
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import os
url = "https://example.com/gallery"
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"}
resp = requests.get(url, headers=headers)
soup = BeautifulSoup(resp.text, "html.parser")
os.makedirs("images", exist_ok=True)
for img in soup.find_all("img"):
src = img.get("src") or img.get("data-src")
if not src:
continue
full_url = urljoin(url, src)
filename = os.path.join("images", os.path.basename(full_url.split("?")[0]))
with open(filename, "wb") as f:
f.write(requests.get(full_url, headers=headers).content)
以上就是30秒的简要说明。实际上,你需要应对以下几个现实情况:
- 延迟加载的图片 居住在
data-src,data-original,或类似的属性,而不是src— 在信任标记之前,请先检查该页面。 srcset属性 提供多种分辨率的响应式图片。最高质量的版本通常并不是src指向;解析srcset以抢到最大的。- 通过 JavaScript 渲染的图库 不会出现在
requests完全没有输出。切换到 Playwright,等待图库渲染完成,然后从 DOM 中提取内容。 - 签名过的 CDN URL会过期——如果你一次性收集所有 URL,然后稍后下载,可能会遇到 403 错误。请在发现时立即下载。
- 防热链接保护 拒绝未经授权的请求
Refererheader。将源页面的 URL 作为Referer而且其中大部分都会消失。
对于由 Playwright 生成的抓取:
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com/gallery")
page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
page.wait_for_timeout(2000)
image_urls = page.eval_on_selector_all(
"img",
"elements => elements.map(el => el.src)"
)
browser.close()
这解决了“滚动加载更多”模式的问题,该模式会导致在大多数现代图片库中,简单的爬虫程序无法正常工作。
第4级:生产级采集
一旦单次运行处理的图像数量超过几千张,或者持续运行批量处理任务(最常见的情况包括:构建用于机器学习训练的图像数据集、监控竞争对手的视觉素材,或大规模整理内容推送),瓶颈就会发生变化。
问题已经不再出在脚本上了。问题在于:
速率限制与IP封禁。任何有影响力的网站都会屏蔽每分钟访问次数超过几次的单一IP地址。解决方法是轮换使用住宅代理——这些分配给真实家庭的IP地址,其流量与普通用户流量毫无二致。数据中心代理对此无效;主要图片托管服务商和电商平台默认会将数据中心IP范围标记为可疑。
基于地理围栏的内容。部分图片仅向特定地区展示(如获得授权的体育图片、地区性产品照片)。这可通过国家层面的代理定位来实现;而对于真正本地化的内容,城市层面的定位则至关重要。
存储与去重。 一次下载10万张图片(每张200KB)的任务,总大小为20GB。在下载时对每张图片进行哈希计算(一个简单的 hashlib.md5(content).hexdigest()) 允许您跳过重复项,而无需维护一个并行的文件名数据库。
重试机制。网络会出故障,CDN 会限速,浏览器会崩溃。将每次下载都封装在“带退避机制的重试”中,并在出现故障时进行日志记录,而不是直接终止操作。
并发。 使用 aiohttp 与 asyncio 适用于下载量大的工作负载。一个简单的顺序脚本,以每次请求 200 毫秒的速度下载 1 万张图片,需要 33 分钟;而异步版本则不到一分钟(前提是源服务器能承受——别把别人的服务器搞垮了)。
对于这一级别的项目,代理基础设施比爬虫脚本更为重要。脚本只需100行代码,一个下午就能写完。而可靠的、轮换的、家庭IP地址,才是真正决定任务能否顺利完成,还是会在IP被封禁后卡在30%处停滞不前的关键因素。
IPBurger正适合这里——轮换的住宅代理、国家级定向、在需要时提供粘性会话——而且无论使用哪家服务商,这个更广泛的观点都成立:在这个级别上,代理层才是承担主要负荷的部分。
大多数指南都忽略的部分:合法性和伦理问题
图像抓取是网络抓取领域中法律界定较为模糊的领域之一,这主要源于以下几个具体原因,而这些原因在过去两年间已日趋明确:
图片默认受版权保护。与文本片段不同,后者在“合理使用”方面有更大的回旋余地,而图片的复制通常属于版权范畴。图片在互联网上公开可访问这一事实,并不意味着授予了复制和再分发的许可。对于商业用途而言,这确实存在风险;对于机器学习训练数据集而言,这是一个尚存争议且法律界定尚不明确的领域。
服务条款通常会明确禁止数据抓取。违反服务条款通常不构成刑事犯罪,但可能涉及民事责任,并可能导致您的账户和IP地址被封禁。在对任何网站进行大规模数据抓取前,请务必阅读该网站的服务条款。
《欧盟人工智能法案》及类似法规已开始要求披露人工智能模型的训练数据来源。如果您正在为机器学习进行数据抓取,请记录数据的来源及其收集方式。
无论从技术上是否可访问,某些内容均被禁止发布。展示可识别身份的个人(尤其是未成年人)的图片绝对禁止发布——即使该页面是公开的。隐私法规(GDPR、CCPA)同样适用。
一条实用的经验法则:如果你不好意思向法官或该网站的律师解释你的数据抓取操作,那就别做。如果你能清晰地解释清楚——“我们正在收集公开发布的产品图片用于价格比较,遵守robots.txt规则,对请求进行速率限制,并注明来源”——那么你大概就没问题。
一个合理的默认工作流
如果您今天要启动一个图片抓取项目,但不确定需要选择哪个套餐,以下方案可随业务规模灵活扩展:
- 在浏览器的开发者工具中检查该页面。 找出图片 URL 的实际存储位置。静态
src?srcset?data-src? CSS 中的背景图片?花10分钟研究一下,以后能省下好几个小时。 - 试一试
wget或者一个小requests + BeautifulSoup先写脚本。 如果图片下载下来没有问题,那就大功告成了。 - 如果 JavaScript 渲染导致问题,请改用 Playwright。无头浏览器虽然速度较慢,但能处理真实用户所能看到的任何内容。
- 如果你开始遇到403或429错误,请添加一层住宅代理。不要试图通过无休止地调整请求头来欺骗反机器人系统;一旦网站识别出你的IP地址,就再也无法隐藏了。
- 只有当业务量达到一定规模时,才添加去重、重试逻辑和并发处理功能。不要在项目启动的第一天就构建生产环境管道。
大多数图像抓取项目都在第4步中途夭折——不是因为编写脚本很难,而是因为操作员试图在需要住宅IP的地方使用数据中心IP,为此白白浪费了三天时间,最终只能放弃。只要从一开始就选择正确的基础设施,剩下的步骤就简单明了了。
