准备工作:环境搭建
2.1 安装 Python(如果你还没有)
首先确认你安装了 Python。打开命令行(Windows 按 Win+R,输入 cmd;Mac 打开终端),输入:
python --version
如果看到类似 Python 3.12.7 这样的版本号,说明已安装。如果没有,去 Python 官网 下载安装。
Python Selenium 浏览器自动化教程涵盖环境搭建、元素定位、页面交互及等待机制。内容包含基础操作、8 种定位方式、显式隐式等待处理、下拉框复选框操作,并提供完整代码示例与常见问题解决方案,适合初学者快速上手自动化测试与数据采集任务。
首先确认你安装了 Python。打开命令行(Windows 按 Win+R,输入 cmd;Mac 打开终端),输入:
python --version
如果看到类似 Python 3.12.7 这样的版本号,说明已安装。如果没有,去 Python 官网 下载安装。
在命令行中输入:
pip install selenium
如果下载慢,可以使用国内镜像:
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
传统方式需要手动下载浏览器驱动,但现在有更简单的方法:
pip install webdriver-manager
这个工具会自动帮你下载和配置浏览器驱动。
让我们从一个最简单的例子开始:
# 1. 导入必要的库
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
# 2. 自动下载并设置 Chrome 驱动
service = Service(ChromeDriverManager().install())
# 3. 创建浏览器对象(会弹出一个 Chrome 窗口)
driver = webdriver.Chrome(service=service)
# 4. 打开百度首页
driver.get("https://www.baidu.com")
# 5. 等待 5 秒,让你看到效果
time.sleep(5)
# 6. 关闭浏览器
driver.quit()
运行这个程序,你会看到:
| 操作 | 方法 | 示例 |
|---|---|---|
| 打开网页 | driver.get(url) | driver.get("https://www.baidu.com") |
| 获取页面标题 | driver.title | title = driver.title |
| 获取当前 URL | driver.current_url | url = driver.current_url |
| 前进 | driver.forward() | driver.forward() |
| 后退 | driver.back() | driver.back() |
| 刷新 | driver.refresh() | driver.refresh() |
| 关闭当前窗口 | driver.close() | driver.close() |
| 关闭所有窗口 | driver.quit() | driver.quit() |
| 最大化窗口 | driver.maximize_window() | driver.maximize_window() |
| 设置窗口大小 | driver.set_window_size(width, height) | driver.set_window_size(800, 600) |
# 基础操作示例代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
# 初始化浏览器
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
# 访问第一个网站
driver.get("https://www.baidu.com")
print(f"当前页面标题:{driver.title}")
print(f"当前页面 URL:{driver.current_url}")
# 等待 2 秒
time.sleep(2)
# 访问第二个网站
driver.get("https://www.taobao.com")
print(f"新页面标题:{driver.title}")
# 等待 2 秒
time.sleep(2)
# 后退到百度
driver.back()
print(f"后退后页面:{driver.title}")
# 等待 2 秒
time.sleep(2)
# 前进到淘宝
driver.forward()
print(f"前进后页面:{driver.title}")
# 刷新页面
driver.refresh()
# 最大化窗口
driver.maximize_window()
# 设置窗口大小
driver.set_window_size(800, 600)
finally:
# 关闭浏览器
time.sleep(3)
driver.quit()
print("浏览器已关闭")
这是 Selenium 最重要的部分!就像在网页上找东西一样,我们需要告诉 Selenium "我要找什么"。
HTML 元素有 id 属性时使用(id 通常是唯一的):
search_input = driver.find_element(By.ID, "kw")
name 属性可能不唯一,但经常使用:
search_input = driver.find_element(By.NAME, "wd")
class 可能不唯一,一个元素可能有多个 class:
search_input = driver.find_element(By.CLASS_NAME, "s_ipt")
通过标签名查找(最不精确,通常用来查找多个元素):
divs = driver.find_elements(By.TAG_NAME, "div")
inputs = driver.find_elements(By.TAG_NAME, "input")
links = driver.find_elements(By.TAG_NAME, "a")
精确匹配链接文本:
news_link = driver.find_element(By.LINK_TEXT, "新闻")
hao123_link = driver.find_element(By.LINK_TEXT, "hao123")
部分匹配链接文本(包含即可):
baidu_link = driver.find_element(By.PARTIAL_LINK_TEXT, "百度")
hao123_link = driver.find_element(By.PARTIAL_LINK_TEXT, "hao123")
CSS 选择器功能强大,类似于 CSS 样式选择元素:
# 通过 id
element = driver.find_element(By.CSS_SELECTOR, "#kw")
# 通过 class
element = driver.find_element(By.CSS_SELECTOR, ".s_ipt")
# 通过标签名 +class
element = driver.find_element(By.CSS_SELECTOR, "input.s_ipt")
# 通过属性
element = driver.find_element(By.CSS_SELECTOR, "[name='wd']")
# 组合选择
element = driver.find_element(By.CSS_SELECTOR, "input#kw.s_ipt[name='wd']")
XPath 就像文件路径,可以定位到任何元素:
# 绝对路径(从 html 开始)
element = driver.find_element(By.XPATH, "/html/body/div/div[2]/div/div/div/form/span/input")
# 相对路径(推荐)
element = driver.find_element(By.XPATH, "//input")
# 带属性的相对路径
element = driver.find_element(By.XPATH, "//input[@id='kw']")
# 使用 and/or
element = driver.find_element(By.XPATH, "//input[@id='kw' and @name='wd']")
# 使用文本内容
element = driver.find_element(By.XPATH, "//a[text()='新闻']")
# 包含文本
element = driver.find_element(By.XPATH, "//a[contains(text(),'新闻')]")
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
# 初始化浏览器
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
# 打开百度
driver.get("https://www.baidu.com")
# 各种定位方式的示例
# 1. 通过 ID 定位搜索框
search_box = driver.find_element(By.ID, "kw")
# 2. 通过 NAME 定位搜索框
search_box = driver.find_element(By.NAME, "wd")
# 3. 通过 CLASS_NAME 定位搜索框
search_box = driver.find_element(By.CLASS_NAME, "s_ipt")
# 4. 通过 TAG_NAME 定位所有输入框
inputs = driver.find_elements(By.TAG_NAME, "input")
print(f"找到 {len(inputs)} 个 input 元素")
# 5. 通过 LINK_TEXT 定位'新闻'链接
news_link = driver.find_element(By.LINK_TEXT, "新闻")
# 6. 通过 PARTIAL_LINK_TEXT 定位包含'新'的链接
news_links = driver.find_elements(By.PARTIAL_LINK_TEXT, "新")
print(f"找到 {len(news_links)} 个包含'新'的链接")
# 7. 通过 CSS_SELECTOR 定位
search_box = driver.find_element(By.CSS_SELECTOR, "#kw")
search_box = driver.find_element(By.CSS_SELECTOR, ".s_ipt")
search_box = driver.find_element(By.CSS_SELECTOR, "input#kw")
# 8. 通过 XPATH 定位
search_box = driver.find_element(By.XPATH, "//input[@id='kw']")
search_box = driver.find_element(By.XPATH, "//*[@id='kw']")
print("所有定位方式测试成功!")
finally:
driver.quit()
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 元素有 id | By.ID | 最简单、最快、唯一 |
| 元素有 name | By.NAME | 简单常用 |
| 元素有 class | By.CLASS_NAME | 简单,但 class 可能重复 |
| 查找多个同类元素 | By.TAG_NAME | 查找所有同类元素 |
| 精确文本链接 | By.LINK_TEXT | 链接文本不变时使用 |
| 模糊文本链接 | By.PARTIAL_LINK_TEXT | 链接文本部分匹配 |
| 复杂选择 | By.CSS_SELECTOR | 功能强大,语法简洁 |
| 最复杂情况 | By.XPATH | 功能最强大,但稍慢 |
找到元素后,我们需要与之交互。下面是常用的操作:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.keys import Keys
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
driver.get("https://www.baidu.com")
# 找到搜索框
search_box = driver.find_element(By.ID, "kw")
# 方法 1:直接输入
search_box.send_keys("Python 教程")
time.sleep(2)
# 方法 2:先清空再输入
search_box.clear() # 清空内容
search_box.send_keys("Selenium 教程")
time.sleep(2)
# 方法 3:输入特殊键(如回车)
search_box.clear()
search_box.send_keys("自动化测试")
search_box.send_keys(Keys.ENTER) # 按回车键
time.sleep(2)
finally:
driver.quit()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
driver.get("https://www.baidu.com")
# 找到搜索框并输入内容
search_box = driver.find_element(By.ID, "kw")
search_box.send_keys("Python")
# 方法 1:直接点击百度一下按钮
search_button = driver.find_element(By.ID, "su")
search_button.click()
time.sleep(2)
# 方法 2:模拟键盘回车(不需要点击按钮)
driver.back() # 返回百度首页
time.sleep(1)
search_box = driver.find_element(By.ID, "kw")
search_box.clear()
search_box.send_keys("Selenium")
search_box.submit() # 提交表单(相当于在输入框按回车)
time.sleep(2)
finally:
driver.quit()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
driver.get("https://www.baidu.com")
# 获取搜索框元素
search_box = driver.find_element(By.ID, "kw")
# 获取元素的各种属性
print(f"元素标签名:{search_box.tag_name}")
print(f"元素 ID: {search_box.get_attribute('id')}")
print(f"元素 name: {search_box.get_attribute('name')}")
print(f"元素 class: {search_box.get_attribute('class')}")
print(f"元素类型:{search_box.get_attribute('type')}")
print(f"元素值:{search_box.get_attribute('value')}")
print(f"元素是否可见:{search_box.is_displayed()}")
print(f"元素是否可用:{search_box.is_enabled()}")
print(f"元素是否被选中:{search_box.is_selected()}")
# 获取元素位置和大小
location = search_box.location
size = search_box.size
print(f"元素位置:x={location['x']}, y={location['y']}")
print(f"元素大小:宽={size['width']}, 高={size['height']}")
# 获取元素文本(对于有文本的元素)
baidu_link = driver.find_element(By.LINK_TEXT, "百度首页")
print(f"链接文本:{baidu_link.text}")
finally:
driver.quit()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
import time
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
# 访问一个测试页面(包含下拉框)
driver.get("https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select")
# 切换到 iframe(因为这个页面有 iframe 框架)
driver.switch_to.frame("iframeResult")
# 找到下拉框
cars_select = driver.find_element(By.ID, "cars")
# 创建 Select 对象
select = Select(cars_select)
# 方法 1:通过可见文本选择
select.select_by_visible_text("Audi")
time.sleep(1)
# 方法 2:通过 value 值选择
select.select_by_value("opel")
time.sleep(1)
# 方法 3:通过索引选择(从 0 开始)
select.select_by_index(0) # 选择第一个选项
time.sleep(1)
# 获取所有选项
all_options = select.options
print("所有选项:")
for option in all_options:
print(f" {option.text} (value: {option.get_attribute('value')})")
# 获取已选中的选项
selected_option = select.first_selected_option
print(f"当前选中:{selected_option.text}")
finally:
driver.quit()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
# 访问测试页面
driver.get("https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_type_checkbox")
# 切换到 iframe
driver.switch_to.frame("iframeResult")
# 找到复选框
vehicle1 = driver.find_element(By.ID, "vehicle1") # 自行车
vehicle2 = driver.find_element(By.ID, "vehicle2") # 汽车
vehicle3 = driver.find_element(By.ID, "vehicle3") # 船
# 检查复选框状态
print(f"自行车是否选中:{vehicle1.is_selected()}")
print(f"汽车是否选中:{vehicle2.is_selected()}")
print(f"船是否选中:{vehicle3.is_selected()}")
# 选中复选框(如果未选中)
if not vehicle1.is_selected():
vehicle1.click()
time.sleep(1)
if not vehicle2.is_selected():
vehicle2.click()
time.sleep(1)
# 取消选中(如果已选中)
if vehicle3.is_selected():
vehicle3.click()
time.sleep(1)
# 重新检查状态
print(f"自行车是否选中:{vehicle1.is_selected()}")
print(f"汽车是否选中:{vehicle2.is_selected()}")
print(f"船是否选中:{vehicle3.is_selected()}")
finally:
driver.quit()
网页加载需要时间,我们需要等待元素出现后再操作。
import time
time.sleep(5) # 强制等待 5 秒,不管元素是否加载完成
缺点:如果元素提前加载完成,也要等;如果超时未加载,会报错。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
# 设置隐式等待 10 秒
driver.implicitly_wait(10)
# 之后的所有 find_element 操作都会最多等待 10 秒
driver.get("https://www.baidu.com")
element = driver.find_element(By.ID, "kw")
优点:设置一次,全局生效。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
driver.get("https://www.baidu.com")
# 创建等待对象(最多等 10 秒,每 0.5 秒检查一次)
wait = WebDriverWait(driver, 10, 0.5)
# 等待元素出现
search_box = wait.until(EC.presence_of_element_located((By.ID, "kw")))
print("搜索框已出现")
# 等待元素可点击
search_button = wait.until(EC.element_to_be_clickable((By.ID, "su")))
print("搜索按钮可点击")
# 等待元素可见
logo = wait.until(EC.visibility_of_element_located((By.ID, "lg")))
print("百度 logo 可见")
# 等待文本出现在元素中
news_link = wait.until(EC.text_to_be_present_in_element((By.LINK_TEXT, "新闻"), "新闻"))
print("新闻链接文本正确")
finally:
driver.quit()
| 条件 | 说明 |
|---|---|
presence_of_element_located | 元素出现在 DOM 中(不一定可见) |
visibility_of_element_located | 元素可见(有宽高,非隐藏) |
element_to_be_clickable | 元素可点击 |
text_to_be_present_in_element | 元素包含特定文本 |
title_contains | 页面标题包含特定文本 |
alert_is_present | 出现警告框 |
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
try:
# 1. 设置隐式等待
driver.implicitly_wait(5)
# 2. 访问慢速网站测试等待
driver.get("https://the-internet.herokuapp.com/dynamic_loading/2")
# 3. 点击开始按钮
start_button = driver.find_element(By.XPATH, "//button[text()='Start']")
start_button.click()
# 4. 创建显式等待对象
wait = WebDriverWait(driver, 10)
# 5. 等待加载完成文字出现
finish_text = wait.until(EC.visibility_of_element_located((By.ID, "finish")))
print(f"加载完成,文字内容:{finish_text.text}")
# 6. 等待特定文本出现
wait.until(EC.text_to_be_present_in_element((By.ID, "finish"), "Hello World!"))
print("成功等到'Hello World!'文本")
finally:
time.sleep(2)
driver.quit()
现在我们来完成一个完整的实战案例:登录并爬取 Bing 图片的描述信息。
""" Bing 图片爬虫 - Selenium 新手实战教程
功能:自动搜索并获取 Bing 图片信息
"""
# 导入所需库
import os
import time
import json
import csv
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
class BingImageCrawler:
"""Bing 图片爬虫类"""
def __init__(self, headless=False):
"""
初始化爬虫
参数:
headless: 是否使用无头模式(不显示浏览器窗口)
默认 False 显示窗口,适合新手调试
"""
print("=" * 50)
print("Bing 图片爬虫 - 初始化中...")
print("=" * 50)
# 创建保存数据的文件夹
self.data_dir = "bing_images_data"
if not os.path.exists(self.data_dir):
os.makedirs(self.data_dir)
print(f"创建文件夹:{self.data_dir}")
# 设置浏览器选项
options = webdriver.ChromeOptions()
# 如果设置为无头模式,不显示浏览器窗口
if headless:
options.add_argument('--headless')
print("启用无头模式(不显示浏览器窗口)")
# 其他配置
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--disable-gpu')
options.add_argument('--window-size=1920,580') # 设置窗口大小
# 使用 DriverManager 自动管理浏览器驱动
print("正在下载/配置 Chrome 浏览器驱动...")
service = Service(ChromeDriverManager().install())
# 启动浏览器
self.driver = webdriver.Chrome(service=service, options=options)
# 设置等待时间
self.wait = WebDriverWait(self.driver, 5)
print("浏览器启动成功!")
def search_images(self, keyword, max_images=10):
"""
搜索图片
参数:
keyword: 搜索关键词,如"小黑子"
max_images: 最大图片数量
返回:
图片数据列表
"""
print(f"\n开始搜索:{keyword}")
try:
# 1. 访问 Bing 图片搜索
search_url = f"https://cn.bing.com/images/search?q={keyword}"
self.driver.get(search_url)
print(f"访问 URL: {search_url}")
# 等待页面加载
time.sleep(2)
# 2. 等待搜索框出现(确认页面加载完成)
try:
search_box = self.wait.until(
EC.presence_of_element_located((By.ID, "sb_form_q"))
)
print("页面加载完成")
except:
print("页面加载异常,但继续执行...")
# 3. 滚动加载更多图片
print("开始滚动加载图片...")
loaded_count = self._scroll_to_load_images(max_images)
# 4. 获取图片数据
print("开始解析图片信息...")
images_data = self._parse_images(loaded_count)
if images_data:
print(f"成功获取 {len(images_data)} 张图片信息")
else:
print("未找到图片数据")
return images_data
except Exception as e:
print(f"搜索过程中发生错误:{str(e)}")
return []
def _scroll_to_load_images(self, max_images):
"""
滚动页面加载更多图片
返回:
加载的图片数量
"""
images_count = 0
scroll_count = 0
max_scroll = 1 # 最大滚动次数
while images_count < max_images and scroll_count < max_scroll:
# 获取当前图片数量
current_images = self.driver.find_elements(By.CSS_SELECTOR, '.imgpt .iusc')
images_count = len(current_images)
print(f" 已加载 {images_count} 张图片")
# 如果已达到目标数量,停止滚动
if images_count >= max_images:
break
# 滚动到底部
self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 等待新图片加载
time.sleep(1.5)
scroll_count += 1
# 检查是否有'加载更多'按钮
try:
load_more = self.driver.find_element(By.CLASS_NAME, 'btn_seemore')
if load_more.is_displayed():
load_more.click()
print(" 点击'加载更多'按钮")
time.sleep(2)
except:
pass
print(f"滚动完成,共加载 {images_count} 张图片")
return images_count
def _parse_images(self, max_count):
"""
解析图片信息
返回:
图片数据列表
"""
images_data = []
seen_urls = set() # 用于跟踪已经处理过的图片 URL
# 查找所有图片元素
image_elements = self.driver.find_elements(By.CSS_SELECTOR, '.imgpt .iusc')[:max_count]
# 只取前 max_count 张
for idx, img_element in enumerate(image_elements):
try:
# 获取图片的 m 属性(包含图片信息的 JSON)
m_value = img_element.get_attribute('m')
if m_value:
# 解析 JSON 数据
img_info = json.loads(m_value)
# 获取图片 URL
image_url = img_info.get('murl', '')
# 检查是否已经处理过这张图片,避免重复
if image_url in seen_urls:
continue
seen_urls.add(image_url)
# 提取我们需要的信息
image_data = {
'序号': len(images_data) + 1, # 使用实际添加到列表中的顺序编号
'标题': img_info.get('t', '无标题'),
'描述': img_info.get('desc', '无描述'),
'图片 URL': image_url,
'缩略图 URL': img_info.get('turl', ''),
'宽度': img_info.get('w', '未知'),
'高度': img_info.get('h', '未知'),
'文件类型': img_info.get('ity', '未知'),
'来源网站': img_info.get('purl', ''),
'域名': img_info.get('p', ''),
'采集时间': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
images_data.append(image_data)
# 显示进度
if len(images_data) % 10 == 0:
print(f" 已解析 {len(images_data)} 张图片...")
except Exception as e:
print(f" 解析第 {idx + 1} 张图片时出错:{str(e)}")
continue
return images_data
def save_data(self, images_data, keyword):
"""
保存数据到文件
参数:
images_data: 图片数据列表
keyword: 搜索关键词(用于命名文件)
"""
if not images_data:
print("没有数据可保存")
return
# 生成文件名(包含时间戳)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
base_filename = f"{keyword}_{timestamp}"
# 1. 保存为 JSON 文件
json_file = os.path.join(self.data_dir, f"{base_filename}.json")
with open(json_file, 'w', encoding='utf-8') as f:
json.dump(images_data, f, ensure_ascii=False, indent=2)
# 2. 保存为 CSV 文件(用 Excel 可以打开)
csv_file = os.path.join(self.data_dir, f"{base_filename}.csv")
with open(csv_file, 'w', encoding='utf-8') as f:
# 写入表头
fieldnames = images_data[0].keys()
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
# 写入数据
for img in images_data:
writer.writerow(img)
# 3. 保存为简易文本文件(方便查看)
txt_file = os.path.join(self.data_dir, f"{base_filename}.txt")
with open(txt_file, 'w', encoding='utf-8') as f:
f.write(f"搜索关键词:{keyword}\n")
f.write(f"采集时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"图片数量:{len(images_data)}\n")
f.write("=" * 50 + "\n\n")
for img in images_data:
f.write(f"图片 {img['序号']}:\n")
f.write(f" 标题:{img['标题']}\n")
f.write(f" 描述:{img['描述']}\n")
f.write(f" 尺寸:{img['宽度']}x{img['高度']}\n")
f.write(f" 类型:{img['文件类型']}\n")
f.write(f" 图片 URL: {img['图片 URL'][:80]}...\n")
f.write("-" * 30 + "\n")
print(f"\n数据已保存到:")
print(f" JSON 文件:{json_file}")
print(f" CSV 文件:{csv_file}")
print(f" 文本文件:{txt_file}")
def display_sample_data(self, images_data, count=10):
"""
显示示例数据
参数:
images_data: 图片数据列表
count: 显示前几条数据
"""
if not images_data:
print("没有数据可显示")
return
print(f"\n前 {min(count, len(images_data))} 条数据示例:")
print("=" * 60)
for i, img in enumerate(images_data[:count]):
print(f"{img['序号']}. {img['标题']}")
desc = img['描述'][:80] + "..." if len(img['描述']) > 80 else img['描述']
print(f" 描述:{desc}")
print(f" 尺寸:{img['宽度']}x{img['高度']}")
print(f" 类型:{img['文件类型']}")
print()
def close(self):
"""关闭浏览器"""
self.driver.quit()
print("浏览器已关闭")
def main():
"""主程序"""
print("=" * 50)
print("Bing 图片爬虫 - 新手实战教程")
print("=" * 50)
# 用户配置
keyword = "小黑子" # 可以修改为其他关键词,如'动物'、'汽车'等
max_images = 10 # 想要获取的图片数量
headless = False # 新手建议设为 False,可以看到浏览器操作
# 创建爬虫实例
crawler = BingImageCrawler(headless=headless)
try:
# 搜索图片
images_data = crawler.search_images(keyword, max_images)
if images_data:
# 显示示例数据
crawler.display_sample_data(images_data, count=3)
# 保存数据
crawler.save_data(images_data, keyword)
# 用户交互
print("\n" + "=" * 50)
choice = input("是否查看所有图片标题?(y/n): ").lower()
if choice == 'y':
print("\n所有图片标题:")
for img in images_data:
print(f" {img['序号']:2d}. {img['标题']}")
else:
print("未能获取图片数据,请检查网络或重试")
except KeyboardInterrupt:
print("\n用户中断操作")
except Exception as e:
print(f"\n程序运行出错:{str(e)}")
print("可能的原因:")
print(" 1. 网络连接问题")
print(" 2. 浏览器驱动问题,请重新运行程序")
print(" 3. 网页结构已变化,需要更新代码")
finally:
# 确保浏览器被关闭
input("\n按回车键退出程序...")
crawler.close()
# 程序入口
if __name__ == "__main__":
main()
import os # 文件操作
import time # 时间等待
import json # JSON 数据处理
import csv # CSV 文件处理
from datetime import datetime # 时间处理
class BingImageCrawler:
def __init__(self, headless=False):
# 初始化代码
def search_images(self, keyword, max_images=10):
# 访问 Bing
# 等待加载
# 滚动加载
# 解析数据
def _scroll_to_load_images(self, max_images):
# 不断滚动直到加载足够图片
# 处理'加载更多'按钮
def _parse_images(self, max_count):
# 获取每个图片元素的 JSON 数据
# 提取标题、描述、URL 等信息
def save_data(self, images_data, keyword):
# 保存为 JSON 格式
# 保存为 CSV 格式(Excel 可打开)
# 保存为文本格式
bing_crawler.pypython bing_crawler.py
bing_images_data 文件夹时间戳.json:完整 JSON 数据时间戳.csv:Excel 可打开的表格时间戳.txt:易读的文本格式你可以修改代码中的配置:
# 修改搜索关键词
keyword = "动物" # 改为'汽车'、'美食'、'星空'等
# 修改图片数量
max_images = 20 # 想要获取的图片数量
# 修改是否显示浏览器
headless = True # True 不显示浏览器(后台运行),False 显示浏览器
错误信息:
selenium.common.exceptions.NoSuchElementException: Message: no such element
可能原因:
解决方法:
# 1. 增加等待时间
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "element_id"))
)
# 2. 使用其他定位方式
# 如果 id 找不到,试试 name、class、xpath 等
# 3. 检查是否有 iframe
driver.switch_to.frame("iframe_name_or_id") # 切换到 iframe
# 操作元素...
driver.switch_to.default_content() # 切换回主页面
错误信息:
ElementNotInteractableException: element not interactable
可能原因:
解决方法:
# 1. 等待元素可点击
element = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "element_id"))
)
# 2. 使用 JavaScript 点击
driver.execute_script("arguments[0].click();", element)
# 3. 滚动到元素位置
driver.execute_script("arguments[0].scrollIntoView();", element)
element.click()
错误信息:
TimeoutException: Message: timeout waiting for element
解决方法:
# 1. 增加等待时间
wait = WebDriverWait(driver, 20) # 从 10 秒增加到 20 秒
# 2. 设置更频繁的检查
wait = WebDriverWait(driver, 10, 0.1) # 每 0.1 秒检查一次
# 3. 检查网络或网站状态
错误信息:
WebDriverException: Message: 'chromedriver' executable needs to be in PATH
解决方法: 确保安装了 webdriver-manager 并正确使用:
# 正确的方式
from webdriver_manager.chrome import ChromeDriverManager
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
通过本教程,你已经学会了:
✅ Selenium 基础:安装、启动浏览器、基本操作 ✅ 元素定位:8 种定位方式,找到网页上的任何元素 ✅ 元素操作:点击、输入、获取信息、处理表单 ✅ 等待机制:显式等待、隐式等待,处理动态加载 ✅ 实战项目:完整的 Bing 图片爬虫,包含数据保存
Selenium 是一个强大的工具,不仅可以用于爬虫,还可以用于自动化测试、自动化办公等。现在你已经有了坚实的基础,可以继续探索更多高级功能了!
记住:学习编程最好的方式就是动手实践。复制代码运行一次,然后尝试修改它,最后尝试自己从头写一个类似的项目。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online