requests + BeautifulSoup 拿不到懒加载图片,因为其 src 为空或为占位图,真实 URL 存于 data-src、data-lazy-src 或 srcset 中;requests 不执行 JS,无法获取动态注入内容。

为什么 requests + BeautifulSoup 拿不到懒加载图片?
因为懒加载图片的 src 属性通常为空,或指向占位图(如 data:image/gif;base64,...),真实 URL 存在 data-src、data-lazy-src 或 srcset 里。requests 不执行 JS,自然读不到动态注入的内容。
常见错误现象:采集到的全是空白、小图标、404 图片链接,或者 img 标签根本没 src 值。
- 先检查目标页面源码(右键「查看网页源代码」,非「检查元素」),确认图片是否真在 HTML 初始结构中 —— 如果不在,说明必须触发 JS 加载
- 若存在
data-src,直接提取它即可;若只有srcset,需解析其中最高分辨率的 URL(注意逗号分隔和空格) - 部分站点用 WebP 格式 + 响应式路径拼接(如
/images/photo.jpg?width=600),单纯取data-src可能 404,得补全域名或去掉 query 参数
用 Selenium 模拟滚动触发动态加载
适用于图片靠滚动事件触发加载、且无 API 接口可绕过的场景。核心是让浏览器“看到”图片区域,触发 JS 执行。
关键点不是等全部加载完,而是滚动到底部 + 短暂等待 + 再次滚动(有些站点需多次触发):
立即学习“Python免费学习笔记(深入)”;
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 初始化时加
--headless=new和--disable-gpu提升稳定性,避免无头模式下懒加载失效 - 用
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")滚到底,而非driver.find_element(...).location_once_scrolled_into_view(后者可能不触发批量加载) - 每次滚动后
time.sleep(1.5),太短 JS 来不及响应,太长浪费时间;可用WebDriverWait等待某张图片的data-src出现,更可靠 - 滚动后重新用
driver.page_source解析,或直接用driver.find_elements(By.TAG_NAME, "img")获取当前 DOM 中已加载的img元素
从 Network 面板找真实图片接口(比 Selenium 更快)
很多懒加载实际是通过 AJAX 请求 JSON 数据再渲染,比如 /api/v1/feed?offset=20 返回带图片 URL 的列表。这种方式比跑浏览器快得多,也更稳定。
操作路径:Chrome 打开开发者工具 → Network → 切到 XHR/Fetch → 刷新页面 → 滚动 → 观察新增请求 → 点开看 Response 是否含图片 URL。
- 重点看请求 URL 中是否含分页参数(
offset、page、cursor),Response 是 JSON 还是 HTML 片段 - 注意请求头:
Referer、X-Requested-With、Cookie常被校验,漏掉会导致 403;可用session.cookies.set()复用登录态 - 若接口返回的是缩略图 URL(如
xxx_webp@120w_80h_1e_1c.jpg),需按规则替换为原图(删掉@...w_...h...部分) - 遇到 sign 参数(如
sign=abc123),大概率是前端 JS 生成的,此时必须逆向或改用 Selenium,别硬啃加密逻辑
requests + 正则提取 srcset 或 data-src 的边界情况
当页面静态 HTML 已含懒加载属性,但结构混乱(如多层嵌套、属性名不统一、URL 编码)时,BeautifulSoup 容易漏或错提。
推荐组合策略:先用 soup.find_all("img", attrs={"data-src": True}) 抓主流,再用正则兜底:
-
re.findall(r'data\-src\s*=\s*[\'"]([^\'"]+)[\'"]', html)能覆盖属性值带空格、换行、单/双引号的情况 -
srcset提取更麻烦:先匹配整条srcset="...",再用re.split(r',\s+', value.strip())拆分,取最后一个非空项(通常是最高清),再re.sub(r'\s+\d+[wx]', '', candidate)去掉尺寸后缀 - 所有提取出的 URL 都要
urllib.parse.urljoin(base_url, url)补全,否则相对路径会 404 - 遇到
src是 base64 的,直接跳过 —— 它本就不是外链图片,无需采集
懒加载的复杂性不在技术本身,而在每个网站实现方式不同:有的藏在 data-original,有的用 loading="lazy" 但 src 已真实,有的靠 IntersectionObserver API 动态 fetch。抓之前务必人工确认目标字段在哪,别默认所有站点都用 data-src。

















