Python爬虫之保存图片到本地

Python爬虫之BeautifulSoup保存图片到本地

在网络爬虫的世界里,文字是丰富的养分,而图片则是色彩缤纷的果实。无论你是在收集艺术作品、建立产品目录,还是只是想保存那些令人惊叹的旅行照片,从网页上抓取并保存图片都是一项常见而重要的任务。今天,我们将深入探讨如何使用Python优雅且高效地将这些数字图像从浩瀚的互联网转移到你的本地磁盘上。

为什么要保存网页图片?

在开始技术细节之前,让我们先思考一下为什么我们要这么做:

  1. 数据集构建:机器学习研究者经常需要大量的图像来训练模型,比如物体识别或风格转换算法。
  2. 内容聚合:想象一个展示全球街头艺术的网站,你需要从各种博客和社交媒体平台收集图片。
  3. 备份与存档:也许你是一个摄影师,想备份所有发布在你网站上的照片。
  4. 离线访问:保存旅游目的地的图片,以便在没有网络时进行参考。
  5. 比较研究:收集多年来同一产品的图片,研究其设计演变。

无论理由是什么,技术挑战都是相似的:识别、下载并适当地组织这些图片。

步骤1:定位图片

在开始下载之前,我们需要在网页的HTML中找到图片链接。这就是我们上一篇博客中讨论的BeautifulSoup大显身手的地方。

import requests
from bs4 import BeautifulSoup# 假设我们在爬一个旅游博客
url = "http://travelblog.com/japan-2024/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')# 查找所有<img>标签
images = soup.find_all('img')# 提取src属性
image_urls = [img['src'] for img in images if 'src' in img.attrs]print(f"找到 {len(image_urls)} 张图片")
for url in image_urls[:3]:  # 只显示前3个print(f"  - {url}")

这段代码使用BeautifulSoup找到所有的<img>标签,并提取它们的src属性,这通常是图片文件的URL。但要小心,有时图片可能在其他属性中,如data-src(用于延迟加载)或srcset(用于响应式图片)。

# 更全面的方法
for img in images:src = img.get('src') or img.get('data-src') or img.get('srcset', '').split()[0]if src:image_urls.append(src)

步骤2:构建完整的URL

<img>标签中提取的URL并不总是完整的。它们可能是:

  • 绝对路径:https://example.com/images/photo.jpg
  • 根相对路径:/images/photo.jpg
  • 协议相对路径://example.com/images/photo.jpg
  • 相对路径:../images/photo.jpg

我们需要确保所有的URL都是完整的绝对路径:

from urllib.parse import urljoinbase_url = "http://travelblog.com/japan-2024/"full_urls = [urljoin(base_url, img_url) for img_url in image_urls]print("完整的图片URL:")
for url in full_urls[:3]:print(f"  - {url}")

urljoin函数非常智能,它知道如何正确地组合基础URL和相对路径。

步骤3:下载图片

现在我们有了完整的图片URL列表,是时候将它们下载到本地了。我们将使用requests库来完成这个任务:

import os# 创建一个目录来存储图片
if not os.path.exists("japan_photos"):os.makedirs("japan_photos")# 下载每张图片
for i, url in enumerate(full_urls):response = requests.get(url)# 检查请求是否成功if response.status_code == 200:# 从URL中提取文件名,如果没有则使用索引filename = os.path.basename(url) or f"{i+1}.jpg"# 拼接完整的文件路径filepath = os.path.join("japan_photos", filename)# 以二进制模式写入文件with open(filepath, 'wb') as f:f.write(response.content)print(f"保存 {filename}")else:print(f"无法下载 {url}")

这个脚本做了以下几件事:

  1. 创建一个名为japan_photos的目录来存储图片。
  2. 遍历每个图片URL并发送GET请求。
  3. 检查响应是否成功(状态码200)。
  4. 尝试从URL中提取文件名,如果不能则使用索引。
  5. 构建完整的文件路径。
  6. 以二进制模式写入图片数据。

注意,我们使用os.path模块来处理文件路径,这使得代码在Windows、macOS和Linux上都能正常工作。

高级技巧

1. 异步下载

当处理大量图片时,同步下载可能会很慢。使用aiohttp库进行异步下载可以显著提升速度:

import asyncio
import aiohttpasync def download_image(session, url, path):async with session.get(url) as response:if response.status == 200:with open(path, 'wb') as f:f.write(await response.read())print(f"保存 {path}")async def main():async with aiohttp.ClientSession() as session:tasks = [download_image(session, url, f"japan_photos/{i+1}.jpg") for i, url in enumerate(full_urls)]await asyncio.gather(*tasks)asyncio.run(main())

2. 避免重复下载

如果你的爬虫会多次访问同一网站,你可能会重复下载相同的图片。使用图片的SHA-256哈希作为唯一标识符可以避免这种情况:

import hashlibdef get_image_hash(data):return hashlib.sha256(data).hexdigest()# 在保存图片时
image_data = response.content
image_hash = get_image_hash(image_data)
filename = f"{image_hash}.jpg"if not os.path.exists(f"japan_photos/{filename}"):with open(f"japan_photos/{filename}", 'wb') as f:f.write(image_data)

3. 尊重robots.txt

爬虫应该遵守网站的robots.txt文件,它指定了哪些区域是允许爬取的。使用robotparser模块:

import robotparserrp = robotparser.RobotFileParser()
rp.set_url("http://travelblog.com/robots.txt")
rp.read()if rp.can_fetch("*", "http://travelblog.com/japan-2024/"):# 继续爬取
else:print("此页面不允许爬取")

4. 添加请求头和延迟

一些网站可能会阻止未带请求头的请求,或者如果请求太频繁。设置User-Agent和添加延迟可以帮助规避这些问题:

import time
import randomheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}for url in full_urls:response = requests.get(url, headers=headers)# ... 保存图片 ...# 随机延迟1到3秒time.sleep(random.uniform(1, 3))

错误处理和恢复

网络爬虫总是会遇到问题:网站可能会暂时离线,图片可能已被移动或删除,或者你的IP可能被暂时封禁。健壮的错误处理是关键:

import requests.exceptionstry:response = requests.get(url, timeout=10)# ... 处理响应 ...
except requests.exceptions.Timeout:print(f"{url} 请求超时")
except requests.exceptions.ConnectionError:print(f"无法连接到服务器")
except requests.exceptions.HTTPError as e:print(f"HTTP错误: {e}")
except Exception as e:print(f"发生未知错误: {e}")# 可以将错误的URL保存到一个文件中以后重试with open("failed_urls.txt", "a") as f:f.write(f"{url}\n")

道德和法律注意事项

在我们结束之前,必须强调网络爬虫的道德和法律方面:

  1. 版权:不是所有在网上找到的图片都是免费使用的。确保你有权下载和使用这些图片。
  2. 带宽成本:大规模下载图片会增加网站的带宽成本。对小型网站要特别小心。
  3. 服务条款:许多网站在其服务条款中禁止抓取。总是要检查这些条款。
  4. 个人隐私:如果你在下载可能包含个人信息的图片(如个人照片),要特别注意隐私问题。
  5. 商业用途:如果你打算将这些图片用于商业目的,几乎总是需要明确的许可。

我的建议?首先尝试通过官方API或与网站所有者联系来获取你需要的图片。只有在这些选项不可行且你确定你的行为是道德和合法的情况下,才应该采取网络爬虫的方式。

总结

从网页上抓取并保存图片是一项技术性和道德性并重的任务。技术上,它涉及定位图片链接、构建完整URL、高效下载以及处理各种边缘情况和错误。我们已经看到如何使用强大的Python库如BeautifulSoup、requests和aiohttp来完成这些任务,甚至学习了一些高级技巧来优化性能和可靠性。

但技术只是故事的一半。作为开发者和数据科学家,我们有责任以尊重、合法且道德的方式使用这些工具。网络不仅仅是数据的海洋;它也是创意、知识产权和个人隐私的家园。优雅地下载图片不仅意味着编写智能高效的代码,还意味着明智且合乎道德地选择我们的目标和方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/22849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高通开发系列 - 借助libhybris库实现Linux系统中使用Andorid库

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 返回:专栏总目录 目录 概述Android代码下载和编译aarch64开发环境libhybris下载和编译libhybris测试验证调用库中的函数概述 我主要是基于…

从函数开始学习ABAP01

从函数开始学习ABAP01 函数接口创建步骤实例1&#xff1a;供应商信息同步相关知识函数的属性DATA定义时TYPE 和LIKE的区别IN CORRESPONDING FIELDS OF TABLE表连接判断内表是否不为空FOR ALL ENTRIES INREAD TABLESY-SUBRCSELECT 关键字运算符CONVERSION_EXIT_ALPHA_OUTPUTCALL…

攻防世界---web---Web_php_unserialize

1、题目描述 2、 3、分析代码 class Demo { private $file fl4g.php; }&#xff1a;定义了一个名为Demo的类&#xff0c;该类有一个私有属性$file&#xff0c;默认值为fl4g.php。 $a serialize(new Demo);&#xff1a;创建了一个Demo类的实例&#xff0c;并对其进行序列化&a…

智能监测,无忧续航!Battery Indicator for Mac,让电池状态尽在掌握

Battery Indicator for Mac 是一款设计精良的电池状态监测软件&#xff0c;它极大地增强了Mac用户对电池使用情况的感知和管理能力。 首先&#xff0c;Battery Indicator for Mac 能够实时显示电池电量百分比。这意味着&#xff0c;无论你是在处理文件、浏览网页还是观看视频&…

【栈】736. Lisp 语法解析

本文涉及知识点 栈 LeetCode736. Lisp 语法解析 给你一个类似 Lisp 语句的字符串表达式 expression&#xff0c;求出其计算结果。 表达式语法如下所示: 表达式可以为整数&#xff0c;let 表达式&#xff0c;add 表达式&#xff0c;mult 表达式&#xff0c;或赋值的变量。表达…

电影推荐系统配置运行

电影推荐系统配置运行 代码地址项目介绍&#xff08;引自原文&#xff09; 环境创建新环境激活环境安装包创建管理员用户(可选)启动 代码地址 movie 项目介绍&#xff08;引自原文&#xff09; 本推荐系统采用的是分层模型设计思想&#xff0c;第一层为前端页面模型设计&…

C++ primer例子1实现

问题 代码 Sales_item.h #include<iostream> #include<string> class Sales_item {public:Sales_item(){};Sales_item(std::string insid, int num, double price);friend std::istream& operator>>(std::istream& is, Sales_item& item);frie…

springboot 图形验证码 前后端分离解决方案 easy-captcha

easy-captcha介绍 easy-captcha&#xff0c;提供了Java图形验证码&#xff0c;支持gif、中文、算术等类型&#xff0c;可用于Java Web、JavaSE等项目&#xff0c;是个很好用的工具库&#xff0c;文档比较完备。 用法 添加maven依赖 <!--图形验证码--><dependency&g…

支付系统-业务账单

target&#xff1a;离开柬埔寨倒计时-210day 前言 最近不知道该写什么了&#xff0c;很多东西要写起来非常耗时间&#xff0c;写作是真的不容易呀 我们的支付系统账单有两大类&#xff0c;一个是业务账单还有一个就是资金记录&#xff0c;都是引发资金流后的资金变动表现&…

高效数据处理的前沿:【C++】、【Redis】、【人工智能】与【大数据】的深度整合

目录 1.为什么选择 C 和 Redis&#xff1f; 2.人工智能与大数据的背景 1.大数据的挑战 2.人工智能的需求 3.C 与 Redis 的完美结合 1.安装 Redis 和 Redis C 客户端 2.连接 Redis 并进行数据操作 高级数据操作 列表操作 哈希操作 4.与大数据和人工智能结合 5.实际应…

机器学习18个核心算法模型

1. 线性回归&#xff08;Linear Regression&#xff09; 用于建立自变量&#xff08;特征&#xff09;和因变量&#xff08;目标&#xff09;之间的线性关系。 核心公式&#xff1a; 简单线性回归的公式为&#xff1a; , 其中 是预测值&#xff0c; 是截距&#xff0c; 是斜…

【C语言】结构体(及位段)

你好&#xff01;感谢支持孔乙己的新作&#xff0c;本文就结构体与大家分析我的思路。 希望能大佬们多多纠正及支持 &#xff01;&#xff01;&#xff01; 个人主页&#xff1a;爱摸鱼的孔乙己-CSDN博客 欢迎 互粉哦&#x1f648;&#x1f648;&#xff01; 目录 1. 声明结构…

解锁财富新篇章:消费增值模式引领未来消费趋势

你是否曾对日常消费感到一丝单调&#xff0c;认为它仅仅是一种物质上的交换&#xff0c;而非财富增长的途径&#xff1f;那么&#xff0c;让我们为你打开一扇全新的消费之门——消费增值模式。这不仅是一种全新的消费体验&#xff0c;更是一种让你的资金在消费过程中不断积累与…

Oracle 19c linux安装

下载Oracle Database Preinstallation RPM&#xff0c;该包会自动下载依赖&#xff0c;创建oracle用户&#xff0c; 手动下载地址&#xff1a;https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/index.html wget http://yum.oracle.com/repo/OracleLinux/OL7/latest…

百度地图API 教程使用 嵌套到vue3项目中使用,能够定位并且搜索地点名称位置,反向解析获取经度和维度

文章目录 目录 文章目录 流程 小结 概要安装流程技术细节小结 概要 注册百度地图成为开发者&#xff1a; 登录百度账号 注册成功开始下一步 百度地图API是百度提供的一组开发接口&#xff0c;用于在自己的应用程序中集成地图功能。通过百度地图API&#xff0c;您可以实现地图…

PS的抠图算法原理剖析 1

以这个抠tree为例子 在PS里&#xff0c;操作过程是让你开启R G B三个通道 分别看一下 哪一个的对比最明显 上面的图片 树叶肯定B最少 天空B富裕&#xff0c;所以对比最明显的就用B通道 然后使用一些奇怪的函数&#xff0c;把texture.bbb这张图片变成黑白&#xff0c;纯黑纯白 那…

mysql连接不上可能的原因:防火墙放行mysql的3306端口 全库复制:data目录替换即可 mysql查看版本

1.看本地localhost能否连接 2.在本地看IP能否连接 能说明本地正常 权限也够 都能的话&#xff0c;ip能否ping通 能就说明可能是防火墙原因了。关闭防火墙及杀毒试试。 我这里关防火墙就能访问了。 windows如何开启防火墙&#xff0c;又放行mysql的3306端口&#xff1f; 在 …

微信小程序动画

微信小程序动画属性&#xff1a;提升用户体验的利器 引言 随着移动互联网技术的快速发展&#xff0c;微信小程序已经成为开发者和用户的热门选择。其轻便、快捷、即用即走的特点使得它在各种场景中都有广泛的应用。而动画作为一种重要的视觉元素&#xff0c;在增强用户体验方…

银行从业者心声:银行工作,是围城还是试炼场?

我的一个朋友&#xff0c;曾经对银行工作抱有美好的幻想&#xff0c;觉得那是一个光鲜亮丽、稳定无忧的职业。然而&#xff0c;当他真正踏入银行的大门&#xff0c;成为一名柜员后&#xff0c;才深刻体会到了其中的艰辛与不易。 他告诉我&#xff0c;银行的工作远非他想象中的…

十二、配置注解执行SQL

简化一下流程&#xff0c;主要可以分为下面几步&#xff1a; 1.解析配置&#xff0c;写入配置项 2.执行SQL 3.封装结果 通过注解配置SQL主要体现在解析部分&#xff0c;这部分要分别做解析XML还是配置注解的接口&#xff0c;拿到sql以后&#xff0c;select的处理和insert/upda…