想把喜欢的网站上的图片都下载下来?想让这些图片井井有条地躺在你的硬盘里,而不是乱糟糟地堆在一起?没问题!今天就来手把手教你用Python写一个爬虫,它可以自动抓取网站上的所有图片,并且按照文件夹分类保存,让你的收藏整洁又高效。
准备工作
首先,确保你已经安装了Python环境。然后,我们需要安装几个强大的库来帮助我们完成任务:
- requests: 用于发送HTTP请求,获取网页内容。
- Beautiful Soup 4 (bs4): 用于解析HTML和XML文档,方便我们提取图片链接。
- os: 用于创建文件夹,保存图片。
- urllib.parse: 用于处理URL,拼接完整的图片链接。
你可以使用pip命令来安装这些库:
pip install requests beautifulsoup4
核心代码
下面是完整的Python代码,我会一步一步地解释它的功能:
import requests
from bs4 import BeautifulSoup
import os
from urllib.parse import urljoin, urlparse
def is_valid(url):
'''
判断URL是否有效
'''
parsed = urlparse(url)
return bool(parsed.netloc) and bool(parsed.scheme)
def get_all_images(url):
'''
返回页面中所有图片的URL
'''
try:
response = requests.get(url)
response.raise_for_status() # 检查请求是否成功
except requests.exceptions.RequestException as e:
print(f"请求 {url} 失败: {e}")
return []
soup = BeautifulSoup(response.content, 'html.parser')
urls = []
for img in soup.find_all('img'):
img_url = img.attrs.get('src')
if not img_url:
# 如果<img>标签没有src属性,则跳过
continue
img_url = urljoin(url, img_url) # 将相对URL转换为绝对URL
try:
pos = img_url.index('?')
img_url = img_url[:pos]
except ValueError:
pass
if is_valid(img_url):
urls.append(img_url)
return urls
def download_image(url, pathname):
'''
下载一张图片
'''
if not os.path.isdir(pathname):
os.makedirs(pathname)
try:
response = requests.get(url, stream=True)
response.raise_for_status() # 检查请求是否成功
except requests.exceptions.RequestException as e:
print(f"下载 {url} 失败: {e}")
return
filename = os.path.join(pathname, os.path.basename(url))
# 检查文件是否已经存在,如果存在则跳过下载
if os.path.exists(filename):
print(f"文件 {filename} 已经存在,跳过下载")
return
with open(filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
print(f"下载 {url} 完成")
def main(url, path):
'''
主函数
'''
images = get_all_images(url)
# 根据URL的域名创建文件夹
parsed_url = urlparse(url)
domain = parsed_url.netloc
folder_path = os.path.join(path, domain)
if not os.path.exists(folder_path):
os.makedirs(folder_path)
print(f"创建文件夹: {folder_path}")
for img_url in images:
try:
download_image(img_url, folder_path)
except Exception as e:
print(f"下载图片 {img_url} 时发生错误: {e}")
if __name__ == "__main__":
# 替换成你要爬取的网站URL和保存图片的根目录
website_url = "https://www.example.com" # 例如:"https://www.nationalgeographic.com/photography/"
save_path = "./images" # 例如:"/Users/yourname/pictures/"
main(website_url, save_path)
代码详解
- 导入库: 导入我们需要的库,包括
requests
、BeautifulSoup
、os
和urllib.parse
。 is_valid(url)
函数: 检查给定的URL是否有效。这可以防止程序尝试下载无效的链接。get_all_images(url)
函数: 这个函数负责从给定的URL中提取所有图片的URL。它首先发送一个HTTP请求,然后使用Beautiful Soup解析返回的HTML内容。接着,它找到所有的<img>
标签,提取src
属性,并使用urljoin
函数将相对URL转换为绝对URL。最后,它返回一个包含所有图片URL的列表。download_image(url, pathname)
函数: 这个函数负责下载单个图片。它首先检查保存图片的文件夹是否存在,如果不存在则创建它。然后,它发送一个HTTP请求下载图片,并将图片保存到指定的文件夹中。为了防止程序崩溃,我们使用了try...except
块来捕获可能发生的异常。main(url, path)
函数: 这是主函数,它协调整个爬虫的工作。它首先调用get_all_images
函数获取所有图片的URL。然后,它遍历这些URL,并调用download_image
函数下载每个图片。为了更好地组织图片,它会根据URL的域名创建文件夹,并将图片保存到对应的文件夹中。if __name__ == "__main__":
: 这是Python的入口点,它确保我们的代码只在直接运行脚本时执行,而不是在被作为模块导入时执行。在这里,我们指定要爬取的网站URL和保存图片的根目录,并调用main
函数开始爬取。
如何使用
- 替换URL: 将代码中的
website_url
替换成你想要爬取的网站URL。 - 替换保存路径: 将代码中的
save_path
替换成你想要保存图片的根目录。 - 运行代码: 在命令行中运行Python脚本:
python your_script_name.py
进阶技巧
- 自定义文件夹分类: 你可以根据自己的需求修改
main
函数,实现更复杂的文件夹分类逻辑。例如,你可以根据图片的标签、大小、类型等信息进行分类。 - 处理动态加载的内容: 如果网站使用JavaScript动态加载图片,你需要使用Selenium等工具来模拟浏览器行为,获取完整的HTML内容。
- 设置请求头: 有些网站会检查请求头,你可以设置User-Agent等请求头来模拟浏览器,避免被网站屏蔽。
- 添加延时: 为了避免给网站服务器带来过大的压力,你可以在每次请求之间添加延时。
- 使用代理: 如果你的IP地址被网站屏蔽,你可以使用代理IP地址来继续爬取。
注意事项
- 遵守robots.txt协议: 在爬取网站之前,请务必查看网站的
robots.txt
文件,了解网站允许哪些内容被爬取,哪些内容禁止爬取。 - 尊重网站的版权: 爬取到的图片可能受到版权保护,请勿用于商业用途。
- 不要过度爬取: 过度爬取可能会给网站服务器带来过大的压力,甚至导致网站崩溃。请合理控制爬取速度和频率。
总结
通过这个教程,你已经学会了如何使用Python编写一个简单的爬虫,从网站上抓取图片并按照文件夹分类保存。希望你能将这些知识应用到实际项目中,创造出更多有趣的应用!记住,爬虫技术是一把双刃剑,请务必遵守法律法规和网站的规则,做一个负责任的爬虫工程师!