30分钟上手Python爬虫:Selenium+Requests实战图片抓取

发布时间:2026/7/12 4:20:57
30分钟上手Python爬虫:Selenium+Requests实战图片抓取 1. 项目概述一个30分钟就能上手的图片爬虫看到这个标题很多刚接触Python的朋友可能会觉得“爬虫”是个很高深的技术需要掌握一大堆复杂的库和网络协议。其实不然就像标题里那个循环for image_element in image_elements所暗示的核心逻辑往往就是找到规律然后重复执行。今天我就用一个实际案例带你从零开始在30分钟内构建一个能自动从Unsplash这类高质量图片网站下载图片的Python爬虫。这个项目非常适合想通过一个有趣、有视觉成果的小项目来入门Python自动化和网络数据抓取的初学者。你不需要是编程高手只要会安装Python能照着步骤敲代码就能亲手实现一个能“干活”的小工具感受代码自动获取数据的魅力。整个教程我会围绕如何定位网页上的图片元素、如何提取链接、如何保存到本地这几个核心步骤展开。过程中我会穿插解释每一步背后的原理和为什么这么选比如为什么用Selenium而不是单纯的Requests库以及如何应对网站结构变化等实际问题。你会发现爬虫的本质就是模拟人的浏览行为并用程序将其自动化。我们开始吧。2. 环境准备与工具选型为什么是它们在动手写代码之前准备好趁手的工具是关键。这里的选择不是随意的每个工具都有其不可替代的作用。2.1 核心三件套Python、Pip与IDE首先你需要一个Python环境。我强烈建议使用Python 3.6或更高版本因为很多现代库对旧版本的支持已经减弱。安装Python时务必勾选“Add Python to PATH”选项这能让你在命令行中直接使用python和pip命令省去后续配置环境变量的麻烦。pip是Python的包管理工具安装Python时通常会一并安装。我们将用它来安装项目所需的所有第三方库。你可以打开命令行Windows上是CMD或PowerShellMac/Linux上是Terminal输入pip --version来检查是否安装成功。对于集成开发环境IDEPyCharm社区版是完全免费且功能强大的选择。它提供了代码高亮、智能提示、调试器和虚拟环境管理能极大提升开发效率和减少错误。当然如果你习惯用VS Code配合Python插件也是极好的。关键在于选择一个让你写代码时感觉舒服的工具。2.2 爬虫库的选择Selenium Requests Pillow这是本项目的核心技术栈我们来拆解一下每个库的职责和选型理由Selenium为什么不用更轻量的requestsBeautifulSoup因为Unsplash这类现代网站大量使用JavaScript动态加载内容。你直接请求网页源码很可能找不到图片标签因为图片是滚动后由JS渲染出来的。Selenium的强大在于它能驱动一个真实的浏览器如Firefox或Chrome完整地执行页面中的JavaScript让页面完全渲染出来我们再从中提取元素。这就模拟了真实用户滚动浏览的行为。Requests这是一个简单优雅的HTTP库。当Selenium帮我们拿到图片的真实URL后下载图片这个纯粹的“发送HTTP GET请求并获取响应内容”的任务就交给更高效、更专注的Requests来完成。用Selenium去下载大量文件是大材小用而且效率低下。Pillow (PIL)这是Python事实上的图像处理标准库。我们下载的图片数据在内存中是二进制字节流Pillow的Image模块可以轻松地打开这种流并按照正确的格式如JPEG, PNG保存到本地文件系统。这个组合拳——Selenium负责“浏览”和“定位”Requests负责“下载”Pillow负责“保存”——是处理动态加载图片网站的经典模式。2.3 浏览器驱动Geckodriver 的角色这是Selenium能控制Firefox的关键。你可以把它理解为Selenium和Firefox浏览器之间的一个翻译官或桥梁。Selenium发出的指令如“打开某个网页”、“点击某个元素”通过WebDriver协议传递给geckodrivergeckodriver再将其转换成Firefox能理解的操作。注意你必须下载与你的Firefox浏览器版本相匹配的geckodriver。版本不匹配是导致Selenium启动失败的常见原因。下载后通常有两种使用方式一是将其放在项目根目录下并在代码中指定路径如教程所示二是将其所在目录添加到系统的PATH环境变量中这样Selenium就能自动找到它。对于新手我推荐第一种方式更直观避免环境配置的坑。3. 核心流程拆解从浏览器自动化到图片落地理解了工具我们来看整个爬虫是如何一步步运行的。这个过程清晰地分为四个阶段。3.1 第一阶段启动与导航——让浏览器听你指挥首先我们需要让程序打开一个浏览器窗口并导航到目标网站。代码如下from selenium import webdriver # 目标网址 url https://unsplash.com # 创建驱动实例指定geckodriver的路径 driver webdriver.Firefox(executable_pathr./geckodriver) # 让浏览器访问该网址 driver.get(url)这几行代码执行后你会看到一个Firefox窗口自动弹出并打开了Unsplash首页。这里的executable_path参数就是指向你下载的geckodriver文件。如果它不在项目根目录你需要提供完整路径或相对路径。3.2 第二阶段模拟交互——解决动态加载问题Unsplash的图片是滚动到页面底部时自动加载的无限滚动。为了获取更多图片我们需要模拟用户向下滚动的操作。这里用到两个技巧执行JavaScriptSelenium的execute_script方法允许我们在浏览器中直接运行JS代码。window.scrollTo(0, document.body.scrollHeight)是经典的滚动到页面底部的JS语句。等待网络请求和图片渲染需要时间。滚动后立即抓取可能很多图片还没加载出来。time.sleep(5)让程序暂停5秒给页面充分的加载时间。这是一种“强制等待”简单但不够智能。更优的做法是使用Selenium提供的“显式等待”WebDriverWait让它等待某个特定元素出现后再继续这样更高效。但为了教程简洁我们先使用sleep。import time # 滚动到页面底部 driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) # 等待5秒让新内容加载 time.sleep(5)3.3 第三阶段元素定位与数据提取——找到你要的东西页面加载完毕图片也都在DOM文档对象模型里了接下来就是找到它们。我们使用CSS选择器来定位元素。通过浏览器的开发者工具F12检查图片元素你会发现它们可能有共同的类名或处于某个具有特定ID的容器内。比如教程中使用的#gridMulti img表示选择ID为gridMulti的元素内部的所有img标签。# 使用CSS选择器找到所有图片元素 image_elements driver.find_elements_by_css_selector(#gridMulti img) print(f找到了 {len(image_elements)} 张图片。) # 遍历这些元素提取src属性图片链接 for image_element in image_elements: image_url image_element.get_attribute(src) print(image_url)find_elements_by_css_selector返回一个列表包含了所有匹配的元素对象。然后我们遍历这个列表对每个元素调用get_attribute(src)来获取图片的URL地址。这一步非常关键因为src属性里存放的才是图片的真实网络地址。3.4 第四阶段下载与保存——将网络资源变为本地文件拿到URL后就是下载和保存了。我们使用Requests库发起GET请求将返回的二进制内容image_object.content用Pillow的Image.open()打开最后保存到本地。import requests from PIL import Image from io import BytesIO i 0 for image_element in image_elements: image_url image_element.get_attribute(src) try: # 发送请求获取图片数据 response requests.get(image_url) # 确保请求成功 response.raise_for_status() # 将二进制数据转换为图像对象 image Image.open(BytesIO(response.content)) # 生成文件名并保存使用图片自带的格式如JPEG, PNG filename f./images/image_{i}.{image.format.lower()} image.save(filename) print(f已保存: {filename}) i 1 except Exception as e: print(f下载 {image_url} 时出错: {e})这里有几个细节BytesIO它在内存中创建一个类文件对象让Pillow能够像读取文件一样读取二进制数据。response.raise_for_status()如果HTTP请求返回错误状态码如404 500这一行会抛出异常便于我们处理错误。image.formatPillow能识别图片的原始格式我们用它作为文件扩展名。错误处理try-except网络请求可能失败图片数据可能损坏加入异常处理能让程序更健壮不会因为一张图片出错而整个崩溃。4. 代码整合与功能增强打造一个实用的爬虫脚本把上面的代码片段组合起来就是一个基础可用的爬虫了。但我们可以让它更实用、更灵活。4.1 基础版本完整代码这是一个整合了所有步骤的基础脚本你可以直接保存为simple_image_scraper.py并运行。import time import os from selenium import webdriver import requests from PIL import Image from io import BytesIO # 1. 创建图片保存目录 os.makedirs(./images, exist_okTrue) # 2. 启动浏览器并导航 url https://unsplash.com driver webdriver.Firefox(executable_pathr./geckodriver) # 请确保路径正确 driver.get(url) # 3. 模拟滚动加载 print(正在滚动页面以加载更多图片...) driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) time.sleep(5) # 等待加载 # 4. 定位并提取图片元素 print(正在定位图片元素...) image_elements driver.find_elements_by_css_selector(#gridMulti img) print(f共找到 {len(image_elements)} 个图片元素。) # 5. 遍历下载 success_count 0 for idx, img_element in enumerate(image_elements): img_url img_element.get_attribute(src) if not img_url: print(f第 {idx} 个元素未找到src属性跳过。) continue try: print(f正在下载 ({idx1}/{len(image_elements)}): {img_url[:50]}...) resp requests.get(img_url, timeout10) resp.raise_for_status() img Image.open(BytesIO(resp.content)) # 使用索引和格式作为文件名 file_extension img.format.lower() if img.format else jpg filename f./images/image_{idx:04d}.{file_extension} img.save(filename) success_count 1 print(f 已保存为: {filename}) except requests.exceptions.RequestException as e: print(f 网络请求失败: {e}) except Exception as e: print(f 处理图片时出错: {e}) # 6. 收尾工作 print(f\n下载完成成功下载 {success_count} 张图片。) driver.quit() # 关闭浏览器4.2 功能增强让脚本更强大基础版能工作但不够好用。我们可以添加一些功能让它变成一个更通用的工具。支持搜索Unsplash的搜索页面URL是有规律的例如https://unsplash.com/s/photos/风景。我们可以让用户输入关键词构造对应的URL。控制滚动次数一次滚动加载的图片有限我们可以通过循环控制滚动的次数从而控制下载图片的数量。获取高清大图很多网站包括Unsplash的列表页使用缩略图小图图片真正的原图藏在另一个属性如srcset或>import argparse import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ... 其他导入 ... def main(search_querynature, scroll_times2): # 根据搜索词构造URL base_url https://unsplash.com/s/photos/ url base_url search_query driver webdriver.Firefox(executable_pathr./geckodriver) driver.get(url) # 多次滚动加载 for i in range(scroll_times): print(f第 {i1} 次滚动...) driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) # 使用显式等待等待某个特定元素如图片容器出现 try: wait WebDriverWait(driver, 10) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, #gridMulti img))) except: print(等待超时可能已无新内容加载。) break # 也可以简单等待几秒 # time.sleep(3) # ... 后续的定位、下载、保存逻辑与基础版类似 ... # 注意可能需要调整CSS选择器因为搜索页面的结构可能与首页不同 driver.quit() if __name__ __main__: parser argparse.ArgumentParser(descriptionUnsplash图片爬虫) parser.add_argument(-s, --search, typestr, defaultnature, help搜索关键词) parser.add_argument(-n, --num, typeint, default2, help滚动加载次数) args parser.parse_args() main(search_queryargs.search, scroll_timesargs.num)这样你就可以在命令行运行python scraper.py -s mountain -n 5来下载5屏关于“mountain”的图片了。5. 常见问题、避坑指南与优化建议在实际操作中你肯定会遇到各种各样的问题。这里我总结了一些常见的坑和解决方案。5.1 环境与驱动问题问题1selenium.common.exceptions.WebDriverException: Message: ‘geckodriver’ executable needs to be in PATH.原因Selenium找不到geckodriver。解决确认geckodriver文件是否放在项目目录下并且代码中的路径executable_path是否正确。在Windows上如果文件叫geckodriver.exe路径应为r‘./geckodriver.exe‘。或者将geckodriver所在目录添加到系统的PATH环境变量中然后代码中可以省略executable_path参数直接使用driver webdriver.Firefox()。问题2浏览器闪退或无法启动。原因浏览器与驱动版本不兼容是最常见的原因。解决检查你的Firefox浏览器版本然后去geckodriver的GitHub发布页面下载对应版本的驱动。通常选择最新版即可但务必注意版本匹配说明。5.2 爬取过程中的问题问题3find_elements_by_css_selector返回空列表。原因CSS选择器写错了网站改版了原来的#gridMulti img选择器可能失效。你需要用浏览器的开发者工具重新检查元素结构。页面还没加载完在执行查找元素操作前页面上的JavaScript可能还没渲染出目标内容。你需要增加等待时间或者使用更可靠的“显式等待”。解决打开开发者工具F12使用元素选择器箭头图标点击图片查看它在HTML结构中的位置重新确定选择器。可能是.some-class img或img[src*photo]等。使用显式等待确保元素出现from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC wait WebDriverWait(driver, 10) # 最多等10秒 image_elements wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, “你的选择器”)))问题4下载的图片很小是缩略图不是原图。原因网页为了加载速度列表页显示的通常是压缩后的小图thumbnail。原图的链接可能藏在其他HTML属性里比如>