前言在网络数据采集场景中图片资源是除文本信息外占比最高的资源类型电商商品图、资讯配图、壁纸素材、影视海报等各类业务场景均会涉及图片链接提取与批量下载操作。区别于普通文本数据爬取图片资源属于二进制流数据不仅需要精准从网页源码、接口返回内容中筛选出合法图片地址还要处理链接格式兼容、网络中断续传、文件命名、格式校验、防盗链拦截等一系列问题。图片链接往往混杂在海量 HTML 标签、JavaScript 代码、JSON 数据之中存在绝对地址、相对地址、残缺协议地址、加密地址、动态加载地址等多种形态若仅依靠简单字符匹配极易出现漏采、错采问题。同时部分站点会通过请求头校验、IP 访问限制、时效链接等方式拦截爬虫直接下载图片进一步提升了资源采集难度。本文从图片链接特征、解析提取方案、二进制流下载、异常处理、批量任务优化等维度展开讲解结合主流网页解析库、网络请求库搭配完整实战代码拆解每一段代码的底层运行原理同时汇总开发过程中的高频故障与解决方案。全文覆盖单张图片抓取、批量图片提取、动态链接处理、防盗链绕过等主流场景形成一套可直接落地使用的图片采集技术方案。本文所使用核心依赖库及官方文档链接如下读者可根据需求查阅接口说明、版本适配规则requestsHTTP 网络请求库负责图片资源拉取与会话维持 https://requests.readthedocs.io/bs4(BeautifulSoup)HTML/XML 文档解析库静态页面图片标签提取核心工具 https://www.crummy.com/software/BeautifulSoup/bs4/doc/urllibPython 内置工具库包含 URL 拼接、异常重试、基础网络请求能力 https://docs.python.org/3/library/urllib.htmlosPython 内置文件系统库用于本地目录创建、文件命名、路径管理 https://docs.python.org/3/library/os.html一、网页中图片资源的存储形态与链接特征1.1 主流图片标签与属性规范标准网页中图片资源主要依靠 HTMLimg标签进行展示这也是静态页面图片链接最主要的载体。同时随着网页技术迭代背景图、懒加载图、JSON 接口回传图等非标准形态大量出现不同形态的链接存储位置、命名规则、提取方式存在明显差异。下表对各类图片形态、对应属性、使用场景及提取难点进行汇总说明表格资源形态承载标签 / 字段链接存储属性典型场景提取难点常规静态图片imgsrc普通资讯图、文章配图、商品主图链接存在相对路径、残缺协议需二次拼接懒加载图片imgdata-src / data-original长页面、瀑布流网站提升加载速度标准 src 属性为占位图真实地址在自定义属性中背景图片div/span等块级标签style 样式属性网站 Banner、装饰图、模块背景图链接混杂在 CSS 样式字符串内需字符串截取或正则匹配动态接口图片JSON 数据自定义字段img_url/pic 等前后端分离网站、移动端 H5 页面无 HTML 标签需先解析接口 JSON 再提取链接加密 / 时效图片全形态标签带签名、时间戳的 URL大型商业站点、图库网站链接具备时效性过期后无法访问需实时提取立即下载img标签是整个体系的基础标签标准写法示例为img srchttps://example.com/1.jpg alt示例图片其中src属性为图片真实访问地址alt为图片描述文本不参与资源访问。懒加载是当前主流优化方案网页初次加载时仅加载占位图当页面滚动至可视区域后再加载真实图片因此真实地址会存放在data-*自定义属性中这也是新手提取图片时最容易遗漏的部分。1.2 图片 URL 通用格式与后缀特征网络图片存在固定的文件后缀标识可作为筛选有效链接的判断依据主流图片格式包含jpg、jpeg、png、gif、webp、bmp等。部分 URL 会在后缀后拼接查询参数例如https://example.com/1.jpg?x1y2此类链接依然属于合法图片地址筛选时不能直接截断参数部分。从协议与路径角度划分图片链接同样分为绝对地址、相对地址、残缺协议地址三类规则与前文 URL 拼接规范完全一致提取链接后必须先完成标准化拼接再发起下载请求否则会出现 404 访问失败。二、环境准备与基础依赖安装本文所有代码基于 Python3.x 版本开发内置库无需额外安装第三方库执行以下命令完成部署确保代码正常运行plaintextpip install requests beautifulsoup4其中beautifulsoup4为网页解析库主体安装完成后在代码中通过bs4模块进行导入。开发过程中建议搭配lxml解析器解析速度与容错性优于默认解析器安装命令plaintextpip install lxml三、静态页面图片链接提取BeautifulSoup 实现静态 HTML 页面是爬虫最基础的采集场景使用 BeautifulSoup 解析整个页面文档定位img标签及对应属性即可批量提取图片链接。本节分常规图片、懒加载图片、混合场景图片三大案例逐层讲解搭配代码与原理剖析。3.1 提取标准 img 标签内 src 属性图片该场景适用于无懒加载机制的传统网页直接定位所有img标签读取src属性值即可获取图片地址。3.1.1 代码案例python运行import requests from bs4 import BeautifulSoup from urllib.parse import urljoin # 目标网页地址 base_url https://www.example.com/news # 基础请求头模拟浏览器规避基础反爬 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } # 1. 请求网页源码 response requests.get(base_url, headersheaders) response.encoding utf-8 html_text response.text # 2. 初始化解析器使用lxml提升解析效率 soup BeautifulSoup(html_text, lxml) # 3. 查找页面中所有img标签 img_tag_list soup.find_all(img) # 4. 遍历标签提取并拼接完整图片链接 img_url_list [] for tag in img_tag_list: # 获取src属性值 src_path tag.get(src) if not src_path: continue # 拼接为标准绝对URL full_img_url urljoin(base_url, src_path) img_url_list.append(full_img_url) # 输出提取结果 print(本次提取到的图片链接总数, len(img_url_list)) for index, url in enumerate(img_url_list): print(f图片{index1}地址{url})3.1.2 代码原理详解网页请求逻辑通过requests.get获取完整 HTML 源码手动指定编码为utf-8防止页面中文乱码导致解析异常。网页编码可通过网页源码meta charset标签确认。解析器初始化BeautifulSoup接收两个核心参数第一个为待解析的 HTML 文本第二个为解析器名称。lxml解析器支持不规范 HTML 标签的容错解析处理复杂网页时稳定性更强。标签查找方法find_all(img)为批量查找方法会遍历整个文档返回所有img标签组成的列表与之对应的find(img)仅返回第一个匹配标签适用于单张图片提取场景。属性读取规则标签对象调用get(属性名)方法获取属性值该方法优势在于当标签不存在对应属性时会返回空值而非直接抛出异常程序容错性更高。不建议使用tag.属性名的取值方式。URL 拼接逻辑结合前文所学urljoin函数自动识别相对路径、残缺协议地址统一转换为标准绝对链接保证后续下载请求正常执行。空值过滤增加if not src_path判断过滤无图片地址的空标签避免无效链接进入后续流程。3.2 提取懒加载图片data 系列自定义属性现代网页普遍使用懒加载技术真实图片地址存储在data-src、data-original、data-lazy等自定义属性中src仅为占位图地址直接读取src会采集到无效图片。本节针对该场景编写提取代码。3.2.1 代码案例python运行import requests from bs4 import BeautifulSoup from urllib.parse import urljoin base_url https://www.example.com/lazy-page headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } response requests.get(base_url, headersheaders) response.encoding utf-8 soup BeautifulSoup(response.text, lxml) img_tags soup.find_all(img) real_img_urls [] for tag in img_tags: # 优先读取懒加载属性 lazy_src tag.get(data-src) or tag.get(data-original) or tag.get(data-lazy) if lazy_src: full_url urljoin(base_url, lazy_src) real_img_urls.append(full_url) continue # 若无懒加载属性再读取原生src属性 normal_src tag.get(src) if normal_src: full_url urljoin(base_url, normal_src) real_img_urls.append(full_url) print(懒加载图片提取结果) for url in real_img_urls: print(url)3.2.2 代码原理详解属性优先级设计代码采用「先懒加载属性、后原生 src 属性」的判断逻辑兼容常规图片与懒加载图片混合的页面场景一套代码适配两种形态。多属性兼容通过or逻辑依次匹配主流懒加载属性名称覆盖绝大多数网站的命名规则减少针对性修改成本。取值逻辑Python 逻辑运算中若前一个属性值为空会自动向后匹配直到获取有效值或全部匹配失败。业务适配该逻辑是当前网页图片提取的通用标准写法90% 以上的静态页面图片均可通过此方式完成提取。3.3 提取背景图style 样式属性解析背景图不使用img标签而是存放在标签的style样式字符串中格式通常为background-image: url(图片地址)。此类链接无法直接通过属性取值需要结合字符串处理或正则表达式完成提取。3.3.1 代码案例python运行import re import requests from bs4 import BeautifulSoup from urllib.parse import urljoin base_url https://www.example.com/banner-page headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36} res requests.get(base_url, headersheaders) res.encoding utf-8 soup BeautifulSoup(res.text, lxml) # 匹配所有包含背景图的标签可根据页面特征修改标签名 all_tags soup.find_all([div, span, section]) # 正则表达式匹配url()内部的图片链接 bg_pattern re.compile(rurl\([\]?(.*?)[\]?\)) bg_img_urls [] for tag in all_tags: style_text tag.get(style, ) if not style_text: continue # 正则匹配链接 match_result bg_pattern.search(style_text) if match_result: img_path match_result.group(1) full_url urljoin(base_url, img_path) bg_img_urls.append(full_url) print(背景图片链接) for url in bg_img_urls: print(url)3.3.2 代码原理详解标签范围选择背景图可作用于任意块级、行内标签代码中选取div、span、section三类高频标签开发者可根据实际页面结构增删标签范围。正则表达式规则url\([\]?(.*?)[\]?\)是匹配背景图的通用正则作用为匹配url()括号内的内容同时兼容单引号、双引号、无引号三种书写格式。.*?为非贪婪匹配保证精准截取链接。正则方法调用search()方法会在整个字符串中查找第一个匹配内容适用于单个背景图的场景若一个标签内存在多张背景图可使用findall()方法获取全部匹配结果。取值与拼接group(1)提取正则中第一个分组的内容即纯图片路径再通过urljoin完成地址标准化。四、接口型图片链接提取JSON 数据解析前后端分离架构的网站不再依赖传统 HTML 渲染内容图片链接直接由接口返回 JSON 格式数据页面通过 JavaScript 动态渲染。此类场景无可用 HTML 标签需要直接请求接口地址解析 JSON 字典提取图片链接。4.1 基础 JSON 接口图片提取案例4.1.1 代码案例python运行import requests # 图片数据接口地址 api_url https://www.example.com/api/image/list headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://www.example.com/ } # 请求接口获取JSON数据 response requests.get(api_url, headersheaders) # 直接转为Python字典 json_data response.json() img_url_list [] # 根据接口数据结构遍历提取链接 for item in json_data[data][list]: img_url item.get(img_url) if img_url: img_url_list.append(img_url) print(接口返回图片链接数量, len(img_url_list)) for url in img_url_list: print(url)4.1.2 代码原理详解接口请求规则接口通常存在Referer、Token等校验请求头需按照浏览器抓包结果完整复刻请求头否则接口会返回空数据或权限错误。JSON 解析response.json()是 requests 内置方法自动将 JSON 字符串转换为 Python 字典 / 列表无需手动调用json库序列化使用便捷。数据遍历逻辑JSON 数据存在固定层级结构通过抓包分析字段层级逐层取值即可提取图片链接。不同网站接口字段命名不同常见字段有img_url、pic、image、cover等。地址特性接口返回的图片链接大多为完整绝对地址一般无需二次拼接特殊相对路径链接仍需配合urljoin处理。五、图片资源下载实现二进制流写入本地图片、视频、文件等资源均为二进制数据流和文本数据的存储方式完全不同。文本数据直接将字符串写入文件即可图片必须以二进制模式读取网络流并以二进制模式写入本地文件。本节讲解单张图片下载、批量下载、文件命名、目录管理全流程。5.1 单张图片基础下载5.1.1 代码案例python运行import requests import os # 单张图片地址 img_url https://www.example.com/images/demo.jpg headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } # 定义本地保存路径与文件名 save_path ./images/ file_name demo_01.jpg full_save_path os.path.join(save_path, file_name) # 创建目录目录不存在则新建 if not os.path.exists(save_path): os.makedirs(save_path) # 请求图片资源streamTrue开启流模式避免一次性加载大文件至内存 res requests.get(img_url, headersheaders, streamTrue) # 判断请求状态码200表示请求成功 if res.status_code 200: # 二进制模式写入文件wb write binary with open(full_save_path, wb) as f: # 分块写入数据降低内存占用 for chunk in res.iter_content(chunk_size1024 * 8): f.write(chunk) print(f图片下载完成保存路径{full_save_path}) else: print(f图片下载失败状态码{res.status_code})5.1.2 代码原理详解目录管理os.path.exists()判断目录是否存在os.makedirs()递归创建多级目录保证文件可以正常保存避免因目录缺失报错。os.path.join()拼接路径适配 Windows、Linux、macOS 全平台路径分隔符。流模式请求streamTrue是下载大体积图片、文件的核心配置。默认情况下 requests 会将整个资源一次性加载到内存大图片会造成内存溢出开启流模式后数据分段加载。二进制读写模式文件打开模式wb代表以二进制写入模式打开文件禁止使用w文本模式文本模式会破坏图片二进制数据导致文件损坏无法打开。分块写入iter_content(chunk_size)按照指定字节大小分块读取数据流本例设置 8KB 分块逐块写入本地文件有效控制内存占用适配超大图片下载场景。状态码校验HTTP 200 为请求成功标识404 代表图片地址失效403 代表权限不足增加状态码判断可精准区分下载失败原因。5.2 批量图片下载循环遍历 自动命名实际爬虫项目中以批量下载为主结合前文链接提取逻辑循环遍历所有图片地址自动生成文件名实现全自动批量采集。5.2.1 代码案例python运行import requests import os from urllib.parse import urljoin from bs4 import BeautifulSoup def get_img_links(page_url, headers): 提取页面所有图片链接 res requests.get(page_url, headersheaders) res.encoding utf-8 soup BeautifulSoup(res.text, lxml) img_tags soup.find_all(img) url_list [] for tag in img_tags: src tag.get(src) if src: full_url urljoin(page_url, src) url_list.append(full_url) return url_list def download_images(url_list, save_dir, headers): 批量下载图片 if not os.path.exists(save_dir): os.makedirs(save_dir) # 遍历图片链接列表自动编号命名 for index, img_url in enumerate(url_list): try: # 截取文件后缀保证格式正确 suffix img_url.split(.)[-1].split(?)[0] # 限制合法图片后缀过滤无效链接 if suffix not in [jpg, jpeg, png, gif, webp]: continue file_name fimg_{index1}.{suffix} save_file os.path.join(save_dir, file_name) res requests.get(img_url, headersheaders, streamTrue, timeout10) if res.status_code 200: with open(save_file, wb) as f: for chunk in res.iter_content(8192): f.write(chunk) print(f成功下载{file_name}) else: print(f链接异常状态码{res.status_code}{img_url}) except Exception as e: print(f下载失败 {img_url}错误信息{str(e)}) # 主程序执行 if __name__ __main__: target_url https://www.example.com/gallery save_directory ./gallery_images/ base_headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } # 提取链接 img_links get_img_links(target_url, base_headers) print(f共提取 {len(img_links)} 条图片链接开始下载...) # 批量下载 download_images(img_links, save_directory, base_headers)5.2.2 代码原理详解函数模块化拆分将「链接提取」和「图片下载」拆分为两个独立函数代码结构清晰便于后期维护、复用与功能扩展符合工程化编码规范。自动命名规则使用索引序号的方式生成文件名避免重复文件名覆盖文件从 URL 中截取文件后缀保证本地文件格式与原资源一致。后缀过滤通过判断文件后缀筛选合法图片链接过滤网页脚本、样式文件、空链接等无效地址减少无效请求。超时限制timeout10设置请求超时时间为 10 秒防止部分失效链接长时间阻塞整个批量任务。异常捕获全局try-except捕获网络超时、连接失败、文件读写异常等各类错误单张图片下载失败不会中断整个批量任务提升程序稳定性。六、图片下载常见问题与解决方案图片采集过程中防盗链拦截、链接失效、文件损坏、超时中断是四大高频问题下表汇总故障现象、成因与标准化解决方案表格问题现象产生原因解决方案状态码 403拒绝访问网站开启防盗链校验Referer请求头在请求头中添加Referer值为目标网站主页或当前页面地址图片下载后无法打开、文件损坏使用文本模式w写入二进制数据严格使用wb二进制写入模式禁止文本模式请求长时间无响应程序卡死链接失效、服务器无响应配置timeout超时参数设置合理超时时间提取到大量重复图片页面多处引用同一张图片对链接列表做去重处理转为集合后再遍历下载后缀识别错误文件格式异常URL 后缀后拼接查询参数先截取?前的内容再提取文件后缀链接为相对地址请求 404未做 URL 拼接处理统一使用urljoin转换为绝对地址6.1 防盗链专项处理Referer 请求头配置防盗链是图片站点最基础的防护手段服务器会校验请求来源Referer非本站跳转的请求直接返回 403。解决方案为在请求头中添加对应Referer示例配置python运行headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://www.example.com/ }若网站校验规则严格可将Referer设置为图片所在页面的完整地址进一步提升模拟真实性。6.2 链接去重优化同一图片会在页面多次出现造成重复下载浪费带宽与时间利用 Python 集合自动去重特性优化链接列表python运行# 列表转集合去重再转回列表 img_url_list list(set(img_url_list))七、综合工具类封装链接提取 下载一体化整合前文所有功能封装一体化图片采集工具类集成链接提取、地址拼接、批量下载、异常处理、防盗链绕过等功能可直接在项目中复用。python运行import os import re import requests from bs4 import BeautifulSoup from urllib.parse import urljoin class ImageSpider: def __init__(self, headersNone, timeout10): # 初始化请求头、超时时间 self.base_headers headers or { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } self.timeout timeout # 正则匹配背景图 self.bg_pattern re.compile(rurl\([\]?(.*?)[\]?\)) # 合法图片后缀 self.suffix_list [jpg, jpeg, png, gif, webp, bmp] def extract_img_from_html(self, page_url): 从HTML页面提取所有类型图片链接 try: res requests.get(page_url, headersself.base_headers, timeoutself.timeout) res.encoding utf-8 soup BeautifulSoup(res.text, lxml) all_urls [] # 提取img标签图片 img_tags soup.find_all(img) for tag in img_tags: src tag.get(data-src) or tag.get(data-original) or tag.get(src) if src: all_urls.append(urljoin(page_url, src)) # 提取背景图 style_tags soup.find_all([div, span, section]) for tag in style_tags: style tag.get(style, ) match self.bg_pattern.search(style) if match: bg_url urljoin(page_url, match.group(1)) all_urls.append(bg_url) # 链接去重 unique_urls list(set(all_urls)) return unique_urls except Exception as e: print(f页面解析失败{str(e)}) return [] def download_single_image(self, img_url, save_path, file_name): 下载单张图片 try: res requests.get(img_url, headersself.base_headers, streamTrue, timeoutself.timeout) if res.status_code ! 200: return False full_path os.path.join(save_path, file_name) with open(full_path, wb) as f: for chunk in res.iter_content(8192): f.write(chunk) return True except Exception as e: print(f下载异常 {img_url}{str(e)}) return False def batch_download(self, url_list, save_dir): 批量下载图片 if not os.path.exists(save_dir): os.makedirs(save_dir) total len(url_list) success_count 0 for idx, url in enumerate(url_list): # 截取后缀 pure_url url.split(?)[0] suffix pure_url.split(.)[-1].lower() if suffix not in self.suffix_list: continue file_name fimage_{idx1}.{suffix} if self.download_single_image(url, save_dir, file_name): success_count 1 print(f批量下载完成总数{total}成功{success_count}) # 工具类测试 if __name__ __main__: spider ImageSpider() target_page https://www.example.com/pic-page save_folder ./pic_store/ # 提取链接 img_links spider.extract_img_from_html(target_page) # 批量下载 spider.batch_download(img_links, save_folder)
Python 爬虫项目:图片链接提取与下载
发布时间:2026/6/11 22:13:33
前言在网络数据采集场景中图片资源是除文本信息外占比最高的资源类型电商商品图、资讯配图、壁纸素材、影视海报等各类业务场景均会涉及图片链接提取与批量下载操作。区别于普通文本数据爬取图片资源属于二进制流数据不仅需要精准从网页源码、接口返回内容中筛选出合法图片地址还要处理链接格式兼容、网络中断续传、文件命名、格式校验、防盗链拦截等一系列问题。图片链接往往混杂在海量 HTML 标签、JavaScript 代码、JSON 数据之中存在绝对地址、相对地址、残缺协议地址、加密地址、动态加载地址等多种形态若仅依靠简单字符匹配极易出现漏采、错采问题。同时部分站点会通过请求头校验、IP 访问限制、时效链接等方式拦截爬虫直接下载图片进一步提升了资源采集难度。本文从图片链接特征、解析提取方案、二进制流下载、异常处理、批量任务优化等维度展开讲解结合主流网页解析库、网络请求库搭配完整实战代码拆解每一段代码的底层运行原理同时汇总开发过程中的高频故障与解决方案。全文覆盖单张图片抓取、批量图片提取、动态链接处理、防盗链绕过等主流场景形成一套可直接落地使用的图片采集技术方案。本文所使用核心依赖库及官方文档链接如下读者可根据需求查阅接口说明、版本适配规则requestsHTTP 网络请求库负责图片资源拉取与会话维持 https://requests.readthedocs.io/bs4(BeautifulSoup)HTML/XML 文档解析库静态页面图片标签提取核心工具 https://www.crummy.com/software/BeautifulSoup/bs4/doc/urllibPython 内置工具库包含 URL 拼接、异常重试、基础网络请求能力 https://docs.python.org/3/library/urllib.htmlosPython 内置文件系统库用于本地目录创建、文件命名、路径管理 https://docs.python.org/3/library/os.html一、网页中图片资源的存储形态与链接特征1.1 主流图片标签与属性规范标准网页中图片资源主要依靠 HTMLimg标签进行展示这也是静态页面图片链接最主要的载体。同时随着网页技术迭代背景图、懒加载图、JSON 接口回传图等非标准形态大量出现不同形态的链接存储位置、命名规则、提取方式存在明显差异。下表对各类图片形态、对应属性、使用场景及提取难点进行汇总说明表格资源形态承载标签 / 字段链接存储属性典型场景提取难点常规静态图片imgsrc普通资讯图、文章配图、商品主图链接存在相对路径、残缺协议需二次拼接懒加载图片imgdata-src / data-original长页面、瀑布流网站提升加载速度标准 src 属性为占位图真实地址在自定义属性中背景图片div/span等块级标签style 样式属性网站 Banner、装饰图、模块背景图链接混杂在 CSS 样式字符串内需字符串截取或正则匹配动态接口图片JSON 数据自定义字段img_url/pic 等前后端分离网站、移动端 H5 页面无 HTML 标签需先解析接口 JSON 再提取链接加密 / 时效图片全形态标签带签名、时间戳的 URL大型商业站点、图库网站链接具备时效性过期后无法访问需实时提取立即下载img标签是整个体系的基础标签标准写法示例为img srchttps://example.com/1.jpg alt示例图片其中src属性为图片真实访问地址alt为图片描述文本不参与资源访问。懒加载是当前主流优化方案网页初次加载时仅加载占位图当页面滚动至可视区域后再加载真实图片因此真实地址会存放在data-*自定义属性中这也是新手提取图片时最容易遗漏的部分。1.2 图片 URL 通用格式与后缀特征网络图片存在固定的文件后缀标识可作为筛选有效链接的判断依据主流图片格式包含jpg、jpeg、png、gif、webp、bmp等。部分 URL 会在后缀后拼接查询参数例如https://example.com/1.jpg?x1y2此类链接依然属于合法图片地址筛选时不能直接截断参数部分。从协议与路径角度划分图片链接同样分为绝对地址、相对地址、残缺协议地址三类规则与前文 URL 拼接规范完全一致提取链接后必须先完成标准化拼接再发起下载请求否则会出现 404 访问失败。二、环境准备与基础依赖安装本文所有代码基于 Python3.x 版本开发内置库无需额外安装第三方库执行以下命令完成部署确保代码正常运行plaintextpip install requests beautifulsoup4其中beautifulsoup4为网页解析库主体安装完成后在代码中通过bs4模块进行导入。开发过程中建议搭配lxml解析器解析速度与容错性优于默认解析器安装命令plaintextpip install lxml三、静态页面图片链接提取BeautifulSoup 实现静态 HTML 页面是爬虫最基础的采集场景使用 BeautifulSoup 解析整个页面文档定位img标签及对应属性即可批量提取图片链接。本节分常规图片、懒加载图片、混合场景图片三大案例逐层讲解搭配代码与原理剖析。3.1 提取标准 img 标签内 src 属性图片该场景适用于无懒加载机制的传统网页直接定位所有img标签读取src属性值即可获取图片地址。3.1.1 代码案例python运行import requests from bs4 import BeautifulSoup from urllib.parse import urljoin # 目标网页地址 base_url https://www.example.com/news # 基础请求头模拟浏览器规避基础反爬 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } # 1. 请求网页源码 response requests.get(base_url, headersheaders) response.encoding utf-8 html_text response.text # 2. 初始化解析器使用lxml提升解析效率 soup BeautifulSoup(html_text, lxml) # 3. 查找页面中所有img标签 img_tag_list soup.find_all(img) # 4. 遍历标签提取并拼接完整图片链接 img_url_list [] for tag in img_tag_list: # 获取src属性值 src_path tag.get(src) if not src_path: continue # 拼接为标准绝对URL full_img_url urljoin(base_url, src_path) img_url_list.append(full_img_url) # 输出提取结果 print(本次提取到的图片链接总数, len(img_url_list)) for index, url in enumerate(img_url_list): print(f图片{index1}地址{url})3.1.2 代码原理详解网页请求逻辑通过requests.get获取完整 HTML 源码手动指定编码为utf-8防止页面中文乱码导致解析异常。网页编码可通过网页源码meta charset标签确认。解析器初始化BeautifulSoup接收两个核心参数第一个为待解析的 HTML 文本第二个为解析器名称。lxml解析器支持不规范 HTML 标签的容错解析处理复杂网页时稳定性更强。标签查找方法find_all(img)为批量查找方法会遍历整个文档返回所有img标签组成的列表与之对应的find(img)仅返回第一个匹配标签适用于单张图片提取场景。属性读取规则标签对象调用get(属性名)方法获取属性值该方法优势在于当标签不存在对应属性时会返回空值而非直接抛出异常程序容错性更高。不建议使用tag.属性名的取值方式。URL 拼接逻辑结合前文所学urljoin函数自动识别相对路径、残缺协议地址统一转换为标准绝对链接保证后续下载请求正常执行。空值过滤增加if not src_path判断过滤无图片地址的空标签避免无效链接进入后续流程。3.2 提取懒加载图片data 系列自定义属性现代网页普遍使用懒加载技术真实图片地址存储在data-src、data-original、data-lazy等自定义属性中src仅为占位图地址直接读取src会采集到无效图片。本节针对该场景编写提取代码。3.2.1 代码案例python运行import requests from bs4 import BeautifulSoup from urllib.parse import urljoin base_url https://www.example.com/lazy-page headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } response requests.get(base_url, headersheaders) response.encoding utf-8 soup BeautifulSoup(response.text, lxml) img_tags soup.find_all(img) real_img_urls [] for tag in img_tags: # 优先读取懒加载属性 lazy_src tag.get(data-src) or tag.get(data-original) or tag.get(data-lazy) if lazy_src: full_url urljoin(base_url, lazy_src) real_img_urls.append(full_url) continue # 若无懒加载属性再读取原生src属性 normal_src tag.get(src) if normal_src: full_url urljoin(base_url, normal_src) real_img_urls.append(full_url) print(懒加载图片提取结果) for url in real_img_urls: print(url)3.2.2 代码原理详解属性优先级设计代码采用「先懒加载属性、后原生 src 属性」的判断逻辑兼容常规图片与懒加载图片混合的页面场景一套代码适配两种形态。多属性兼容通过or逻辑依次匹配主流懒加载属性名称覆盖绝大多数网站的命名规则减少针对性修改成本。取值逻辑Python 逻辑运算中若前一个属性值为空会自动向后匹配直到获取有效值或全部匹配失败。业务适配该逻辑是当前网页图片提取的通用标准写法90% 以上的静态页面图片均可通过此方式完成提取。3.3 提取背景图style 样式属性解析背景图不使用img标签而是存放在标签的style样式字符串中格式通常为background-image: url(图片地址)。此类链接无法直接通过属性取值需要结合字符串处理或正则表达式完成提取。3.3.1 代码案例python运行import re import requests from bs4 import BeautifulSoup from urllib.parse import urljoin base_url https://www.example.com/banner-page headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36} res requests.get(base_url, headersheaders) res.encoding utf-8 soup BeautifulSoup(res.text, lxml) # 匹配所有包含背景图的标签可根据页面特征修改标签名 all_tags soup.find_all([div, span, section]) # 正则表达式匹配url()内部的图片链接 bg_pattern re.compile(rurl\([\]?(.*?)[\]?\)) bg_img_urls [] for tag in all_tags: style_text tag.get(style, ) if not style_text: continue # 正则匹配链接 match_result bg_pattern.search(style_text) if match_result: img_path match_result.group(1) full_url urljoin(base_url, img_path) bg_img_urls.append(full_url) print(背景图片链接) for url in bg_img_urls: print(url)3.3.2 代码原理详解标签范围选择背景图可作用于任意块级、行内标签代码中选取div、span、section三类高频标签开发者可根据实际页面结构增删标签范围。正则表达式规则url\([\]?(.*?)[\]?\)是匹配背景图的通用正则作用为匹配url()括号内的内容同时兼容单引号、双引号、无引号三种书写格式。.*?为非贪婪匹配保证精准截取链接。正则方法调用search()方法会在整个字符串中查找第一个匹配内容适用于单个背景图的场景若一个标签内存在多张背景图可使用findall()方法获取全部匹配结果。取值与拼接group(1)提取正则中第一个分组的内容即纯图片路径再通过urljoin完成地址标准化。四、接口型图片链接提取JSON 数据解析前后端分离架构的网站不再依赖传统 HTML 渲染内容图片链接直接由接口返回 JSON 格式数据页面通过 JavaScript 动态渲染。此类场景无可用 HTML 标签需要直接请求接口地址解析 JSON 字典提取图片链接。4.1 基础 JSON 接口图片提取案例4.1.1 代码案例python运行import requests # 图片数据接口地址 api_url https://www.example.com/api/image/list headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://www.example.com/ } # 请求接口获取JSON数据 response requests.get(api_url, headersheaders) # 直接转为Python字典 json_data response.json() img_url_list [] # 根据接口数据结构遍历提取链接 for item in json_data[data][list]: img_url item.get(img_url) if img_url: img_url_list.append(img_url) print(接口返回图片链接数量, len(img_url_list)) for url in img_url_list: print(url)4.1.2 代码原理详解接口请求规则接口通常存在Referer、Token等校验请求头需按照浏览器抓包结果完整复刻请求头否则接口会返回空数据或权限错误。JSON 解析response.json()是 requests 内置方法自动将 JSON 字符串转换为 Python 字典 / 列表无需手动调用json库序列化使用便捷。数据遍历逻辑JSON 数据存在固定层级结构通过抓包分析字段层级逐层取值即可提取图片链接。不同网站接口字段命名不同常见字段有img_url、pic、image、cover等。地址特性接口返回的图片链接大多为完整绝对地址一般无需二次拼接特殊相对路径链接仍需配合urljoin处理。五、图片资源下载实现二进制流写入本地图片、视频、文件等资源均为二进制数据流和文本数据的存储方式完全不同。文本数据直接将字符串写入文件即可图片必须以二进制模式读取网络流并以二进制模式写入本地文件。本节讲解单张图片下载、批量下载、文件命名、目录管理全流程。5.1 单张图片基础下载5.1.1 代码案例python运行import requests import os # 单张图片地址 img_url https://www.example.com/images/demo.jpg headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } # 定义本地保存路径与文件名 save_path ./images/ file_name demo_01.jpg full_save_path os.path.join(save_path, file_name) # 创建目录目录不存在则新建 if not os.path.exists(save_path): os.makedirs(save_path) # 请求图片资源streamTrue开启流模式避免一次性加载大文件至内存 res requests.get(img_url, headersheaders, streamTrue) # 判断请求状态码200表示请求成功 if res.status_code 200: # 二进制模式写入文件wb write binary with open(full_save_path, wb) as f: # 分块写入数据降低内存占用 for chunk in res.iter_content(chunk_size1024 * 8): f.write(chunk) print(f图片下载完成保存路径{full_save_path}) else: print(f图片下载失败状态码{res.status_code})5.1.2 代码原理详解目录管理os.path.exists()判断目录是否存在os.makedirs()递归创建多级目录保证文件可以正常保存避免因目录缺失报错。os.path.join()拼接路径适配 Windows、Linux、macOS 全平台路径分隔符。流模式请求streamTrue是下载大体积图片、文件的核心配置。默认情况下 requests 会将整个资源一次性加载到内存大图片会造成内存溢出开启流模式后数据分段加载。二进制读写模式文件打开模式wb代表以二进制写入模式打开文件禁止使用w文本模式文本模式会破坏图片二进制数据导致文件损坏无法打开。分块写入iter_content(chunk_size)按照指定字节大小分块读取数据流本例设置 8KB 分块逐块写入本地文件有效控制内存占用适配超大图片下载场景。状态码校验HTTP 200 为请求成功标识404 代表图片地址失效403 代表权限不足增加状态码判断可精准区分下载失败原因。5.2 批量图片下载循环遍历 自动命名实际爬虫项目中以批量下载为主结合前文链接提取逻辑循环遍历所有图片地址自动生成文件名实现全自动批量采集。5.2.1 代码案例python运行import requests import os from urllib.parse import urljoin from bs4 import BeautifulSoup def get_img_links(page_url, headers): 提取页面所有图片链接 res requests.get(page_url, headersheaders) res.encoding utf-8 soup BeautifulSoup(res.text, lxml) img_tags soup.find_all(img) url_list [] for tag in img_tags: src tag.get(src) if src: full_url urljoin(page_url, src) url_list.append(full_url) return url_list def download_images(url_list, save_dir, headers): 批量下载图片 if not os.path.exists(save_dir): os.makedirs(save_dir) # 遍历图片链接列表自动编号命名 for index, img_url in enumerate(url_list): try: # 截取文件后缀保证格式正确 suffix img_url.split(.)[-1].split(?)[0] # 限制合法图片后缀过滤无效链接 if suffix not in [jpg, jpeg, png, gif, webp]: continue file_name fimg_{index1}.{suffix} save_file os.path.join(save_dir, file_name) res requests.get(img_url, headersheaders, streamTrue, timeout10) if res.status_code 200: with open(save_file, wb) as f: for chunk in res.iter_content(8192): f.write(chunk) print(f成功下载{file_name}) else: print(f链接异常状态码{res.status_code}{img_url}) except Exception as e: print(f下载失败 {img_url}错误信息{str(e)}) # 主程序执行 if __name__ __main__: target_url https://www.example.com/gallery save_directory ./gallery_images/ base_headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } # 提取链接 img_links get_img_links(target_url, base_headers) print(f共提取 {len(img_links)} 条图片链接开始下载...) # 批量下载 download_images(img_links, save_directory, base_headers)5.2.2 代码原理详解函数模块化拆分将「链接提取」和「图片下载」拆分为两个独立函数代码结构清晰便于后期维护、复用与功能扩展符合工程化编码规范。自动命名规则使用索引序号的方式生成文件名避免重复文件名覆盖文件从 URL 中截取文件后缀保证本地文件格式与原资源一致。后缀过滤通过判断文件后缀筛选合法图片链接过滤网页脚本、样式文件、空链接等无效地址减少无效请求。超时限制timeout10设置请求超时时间为 10 秒防止部分失效链接长时间阻塞整个批量任务。异常捕获全局try-except捕获网络超时、连接失败、文件读写异常等各类错误单张图片下载失败不会中断整个批量任务提升程序稳定性。六、图片下载常见问题与解决方案图片采集过程中防盗链拦截、链接失效、文件损坏、超时中断是四大高频问题下表汇总故障现象、成因与标准化解决方案表格问题现象产生原因解决方案状态码 403拒绝访问网站开启防盗链校验Referer请求头在请求头中添加Referer值为目标网站主页或当前页面地址图片下载后无法打开、文件损坏使用文本模式w写入二进制数据严格使用wb二进制写入模式禁止文本模式请求长时间无响应程序卡死链接失效、服务器无响应配置timeout超时参数设置合理超时时间提取到大量重复图片页面多处引用同一张图片对链接列表做去重处理转为集合后再遍历下载后缀识别错误文件格式异常URL 后缀后拼接查询参数先截取?前的内容再提取文件后缀链接为相对地址请求 404未做 URL 拼接处理统一使用urljoin转换为绝对地址6.1 防盗链专项处理Referer 请求头配置防盗链是图片站点最基础的防护手段服务器会校验请求来源Referer非本站跳转的请求直接返回 403。解决方案为在请求头中添加对应Referer示例配置python运行headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://www.example.com/ }若网站校验规则严格可将Referer设置为图片所在页面的完整地址进一步提升模拟真实性。6.2 链接去重优化同一图片会在页面多次出现造成重复下载浪费带宽与时间利用 Python 集合自动去重特性优化链接列表python运行# 列表转集合去重再转回列表 img_url_list list(set(img_url_list))七、综合工具类封装链接提取 下载一体化整合前文所有功能封装一体化图片采集工具类集成链接提取、地址拼接、批量下载、异常处理、防盗链绕过等功能可直接在项目中复用。python运行import os import re import requests from bs4 import BeautifulSoup from urllib.parse import urljoin class ImageSpider: def __init__(self, headersNone, timeout10): # 初始化请求头、超时时间 self.base_headers headers or { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } self.timeout timeout # 正则匹配背景图 self.bg_pattern re.compile(rurl\([\]?(.*?)[\]?\)) # 合法图片后缀 self.suffix_list [jpg, jpeg, png, gif, webp, bmp] def extract_img_from_html(self, page_url): 从HTML页面提取所有类型图片链接 try: res requests.get(page_url, headersself.base_headers, timeoutself.timeout) res.encoding utf-8 soup BeautifulSoup(res.text, lxml) all_urls [] # 提取img标签图片 img_tags soup.find_all(img) for tag in img_tags: src tag.get(data-src) or tag.get(data-original) or tag.get(src) if src: all_urls.append(urljoin(page_url, src)) # 提取背景图 style_tags soup.find_all([div, span, section]) for tag in style_tags: style tag.get(style, ) match self.bg_pattern.search(style) if match: bg_url urljoin(page_url, match.group(1)) all_urls.append(bg_url) # 链接去重 unique_urls list(set(all_urls)) return unique_urls except Exception as e: print(f页面解析失败{str(e)}) return [] def download_single_image(self, img_url, save_path, file_name): 下载单张图片 try: res requests.get(img_url, headersself.base_headers, streamTrue, timeoutself.timeout) if res.status_code ! 200: return False full_path os.path.join(save_path, file_name) with open(full_path, wb) as f: for chunk in res.iter_content(8192): f.write(chunk) return True except Exception as e: print(f下载异常 {img_url}{str(e)}) return False def batch_download(self, url_list, save_dir): 批量下载图片 if not os.path.exists(save_dir): os.makedirs(save_dir) total len(url_list) success_count 0 for idx, url in enumerate(url_list): # 截取后缀 pure_url url.split(?)[0] suffix pure_url.split(.)[-1].lower() if suffix not in self.suffix_list: continue file_name fimage_{idx1}.{suffix} if self.download_single_image(url, save_dir, file_name): success_count 1 print(f批量下载完成总数{total}成功{success_count}) # 工具类测试 if __name__ __main__: spider ImageSpider() target_page https://www.example.com/pic-page save_folder ./pic_store/ # 提取链接 img_links spider.extract_img_from_html(target_page) # 批量下载 spider.batch_download(img_links, save_folder)