Python Selenium 超详细新手教程:从零开始掌握浏览器自动化

目录

一、写给新手的话

二、准备工作:环境搭建

2.1 安装Python(如果你还没有)

2.2 安装Selenium库

2.3 安装浏览器驱动管理工具

三、第一个Selenium程序:打开百度

四、Selenium基础操作详解

4.1 常用操作汇总表

4.2 详细操作示例

五、元素定位:找到网页上的内容

5.1 8种定位方式(从易到难)

方式1:通过ID定位(最简单)

方式2:通过NAME定位

方式3:通过CLASS_NAME定位

方式4:通过TAG_NAME定位

方式5:通过LINK_TEXT定位

方式6:通过PARTIAL_LINK_TEXT定位

方式7:通过CSS_SELECTOR定位(推荐)

方式8:通过XPATH定位(最强大)

5.2 元素定位完整示例

5.3 元素定位选择建议

六、元素操作:与网页交互

6.1 输入文本

6.2 点击操作

6.3 获取元素信息

6.4 处理下拉框

6.5 处理复选框和单选框

七、等待机制:让程序"等一等"

7.1 强制等待(不推荐)

7.2 隐式等待(全局等待)

7.3 显式等待(推荐)

7.4 常用等待条件

7.5 等待机制完整示例

八、综合实战:自动化登录并爬取数据

8.1 项目目标

8.2 完整代码(带详细注释)

8.3 代码分步解析

第一步:导入库

第二步:创建爬虫类

第三步:搜索图片

第四步:滚动加载

第五步:解析数据

第六步:保存数据

8.4 如何运行程序

8.5 修改配置尝试

九、常见问题与解决方法

问题1:找不到元素(NoSuchElementException)

问题2:元素不可点击(ElementNotInteractableException)

问题3:超时错误(TimeoutException)

问题4:浏览器驱动问题

十、学习建议与下一步

10.1 给新手的建议

10.2 练习题目

10.3 下一步学习方向

十一、总结


一、写给新手的话

        如果你是第一次接触Selenium,可能会觉得有些复杂。别担心!这篇教程将从最基础的安装开始,一步步带你掌握Selenium的每个细节。我会用最简单的语言和大量示例代码,让你快速上手。

二、准备工作:环境搭建

2.1 安装Python(如果你还没有)

首先确认你安装了Python。打开命令行(Windows按Win+R,输入cmd;Mac打开终端),输入:

python --version

如果看到类似 Python 3.12.7 这样的版本号,说明已安装。如果没有,去Python官网下载安装。

2.2 安装Selenium库

在命令行中输入:

pip install selenium

如果下载慢,可以使用国内镜像:

pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple

2.3 安装浏览器驱动管理工具

传统方式需要手动下载浏览器驱动,但现在有更简单的方法:

pip install webdriver-manager

这个工具会自动帮你下载和配置浏览器驱动。

三、第一个Selenium程序:打开百度

让我们从一个最简单的例子开始:

# 1. 导入必要的库 from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager # 2. 自动下载并设置Chrome驱动 service = Service(ChromeDriverManager().install()) # 3. 创建浏览器对象(会弹出一个Chrome窗口) driver = webdriver.Chrome(service=service) # 4. 打开百度首页 driver.get("https://www.baidu.com") # 5. 等待5秒,让你看到效果 import time time.sleep(5) # 6. 关闭浏览器 driver.quit()

运行这个程序,你会看到:

  1. 自动打开Chrome浏览器
  2. 自动访问百度首页
  3. 5秒后自动关闭

四、Selenium基础操作详解

4.1 常用操作汇总表

操作方法示例
打开网页driver.get(url)driver.get("https://www.baidu.com")
获取页面标题driver.titletitle = driver.title
获取当前URLdriver.current_urlurl = 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)

4.2 详细操作示例

# 基础操作示例代码 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"我要找什么"。

5.1 8种定位方式(从易到难)

方式1:通过ID定位(最简单)
<input name="wd" maxlength="255" autocomplete="off">
# HTML元素有id属性时使用(id通常是唯一的) search_input = driver.find_element("id", "kw") # 或者 search_input = driver.find_element_by_id("kw")
方式2:通过NAME定位
<input name="wd" maxlength="255" autocomplete="off">

python

# name属性可能不唯一,但经常使用 search_input = driver.find_element("name", "wd") # 或者 search_input = driver.find_element_by_name("wd")
方式3:通过CLASS_NAME定位
<input name="wd" maxlength="255" autocomplete="off">
# class可能不唯一,一个元素可能有多个class search_input = driver.find_element("class name", "s_ipt") # 或者 search_input = driver.find_element_by_class_name("s_ipt")
方式4:通过TAG_NAME定位
<div>内容</div> <input type="text"> <a href="...">链接</a>
# 通过标签名查找(最不精确,通常用来查找多个元素) divs = driver.find_elements("tag name", "div") # 所有div元素 inputs = driver.find_elements("tag name", "input") # 所有input元素 links = driver.find_elements("tag name", "a") # 所有链接
方式5:通过LINK_TEXT定位
<a href="https://news.baidu.com">新闻</a> <a href="https://www.hao123.com">hao123</a>
# 精确匹配链接文本 news_link = driver.find_element("link text", "新闻") hao123_link = driver.find_element("link text", "hao123")
方式6:通过PARTIAL_LINK_TEXT定位
<a href="https://news.baidu.com">百度新闻</a> <a href="https://www.hao123.com">hao123网址导航</a>
# 部分匹配链接文本(包含即可) baidu_link = driver.find_element("partial link text", "百度") # 匹配"百度新闻" hao123_link = driver.find_element("partial link text", "hao123") # 匹配"hao123网址导航"
方式7:通过CSS_SELECTOR定位(推荐)

CSS选择器功能强大,类似于CSS样式选择元素:

# 通过id element = driver.find_element("css selector", "#kw") # #表示id # 通过class element = driver.find_element("css selector", ".s_ipt") # .表示class # 通过标签名+class element = driver.find_element("css selector", "input.s_ipt") # input标签且class为s_ipt # 通过属性 element = driver.find_element("css selector", "[name='wd']") # name属性为wd # 组合选择 element = driver.find_element("css selector", "input#kw.s_ipt[name='wd']")
方式8:通过XPATH定位(最强大)

XPath就像文件路径,可以定位到任何元素:

# 绝对路径(从html开始) element = driver.find_element("xpath", "/html/body/div/div[2]/div/div/div/form/span/input") # 相对路径(推荐) element = driver.find_element("xpath", "//input") # 所有input标签 # 带属性的相对路径 element = driver.find_element("xpath", "//input[@id='kw']") # id为kw的input element = driver.find_element("xpath", "//input[@name='wd']") # name为wd的input # 使用and/or element = driver.find_element("xpath", "//input[@id='kw' and @name='wd']") # 使用文本内容 element = driver.find_element("xpath", "//a[text()='新闻']") # 文本为"新闻"的链接 element = driver.find_element("xpath", "//a[contains(text(),'新闻')]") # 包含"新闻"的链接

5.2 元素定位完整示例

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") # id选择器 search_box = driver.find_element(By.CSS_SELECTOR, ".s_ipt") # class选择器 search_box = driver.find_element(By.CSS_SELECTOR, "input#kw") # 标签+id # 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()

5.3 元素定位选择建议

场景推荐方式原因
元素有idBy.ID最简单、最快、唯一
元素有nameBy.NAME简单常用
元素有classBy.CLASS_NAME简单,但class可能重复
查找多个同类元素By.TAG_NAME查找所有同类元素
精确文本链接By.LINK_TEXT链接文本不变时使用
模糊文本链接By.PARTIAL_LINK_TEXT链接文本部分匹配
复杂选择By.CSS_SELECTOR功能强大,语法简洁
最复杂情况By.XPATH功能最强大,但稍慢

六、元素操作:与网页交互

找到元素后,我们需要与之交互。下面是常用的操作:

6.1 输入文本

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") # 方法1:直接输入 search_box.send_keys("Python教程") time.sleep(2) # 方法2:先清空再输入 search_box.clear() # 清空内容 search_box.send_keys("Selenium教程") time.sleep(2) # 方法3:输入特殊键(如回车) from selenium.webdriver.common.keys import Keys search_box.clear() search_box.send_keys("自动化测试") search_box.send_keys(Keys.ENTER) # 按回车键 time.sleep(2) finally: driver.quit()

6.2 点击操作

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()

6.3 获取元素信息

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()

6.4 处理下拉框

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()

6.5 处理复选框和单选框

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()

七、等待机制:让程序"等一等"

网页加载需要时间,我们需要等待元素出现后再操作。

7.1 强制等待(不推荐)

import time time.sleep(5) # 强制等待5秒,不管元素是否加载完成

缺点:如果元素提前加载完成,也要等;如果超时未加载,会报错。

7.2 隐式等待(全局等待)

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("id", "kw") # 最多等10秒

优点:设置一次,全局生效。

7.3 显式等待(推荐)

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()

7.4 常用等待条件

条件说明
presence_of_element_located元素出现在DOM中(不一定可见)
visibility_of_element_located元素可见(有宽高,非隐藏)
element_to_be_clickable元素可点击
text_to_be_present_in_element元素包含特定文本
title_contains页面标题包含特定文本
alert_is_present出现警告框

7.5 等待机制完整示例

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图片的描述信息。

8.1 项目目标

  1. 访问Bing图片搜索
  2. 搜索"小黑子"图片
  3. 滚动加载更多图片
  4. 获取每张图片的标题和描述
  5. 保存数据到文件

8.2 完整代码(带详细注释)

""" 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['标题']}") print(f" 描述: {img['描述'][:80]}..." if len(img['描述']) > 80 else f" 描述: {img['描述']}") 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()

8.3 代码分步解析

第一步:导入库
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可打开) # 保存为文本格式

8.4 如何运行程序

  1. 保存代码:将上面的完整代码保存为 bing_crawler.py
  2. 运行程序
python bing_crawler.py
  1. 你会看到
    1. 自动打开Chrome浏览器
    2. 访问Bing图片搜索
    3. 搜索"小黑子"图片
    4. 自动滚动加载更多图片
    5. 获取图片信息
    6. 保存到文件
    7. 在控制台显示结果
  2. 查看结果
    • 在程序所在目录会创建 bing_images_data 文件夹
    • 里面包含3个文件:
      • 小黑子_时间戳.json:完整JSON数据
      • 小黑子_时间戳.csv:Excel可打开的表格
      • 小黑子_时间戳.txt:易读的文本格式

8.5 修改配置尝试

你可以修改代码中的配置:

# 修改搜索关键词 keyword = "动物" # 改为"汽车"、"美食"、"星空"等 # 修改图片数量 max_images = 20 # 想要获取的图片数量 # 修改是否显示浏览器 headless = True # True不显示浏览器(后台运行),False显示浏览器

九、常见问题与解决方法

问题1:找不到元素(NoSuchElementException)

错误信息

selenium.common.exceptions.NoSuchElementException: Message: no such element

可能原因

  1. 元素还没加载出来
  2. 元素ID/名称已改变
  3. 页面有iframe框架

解决方法

# 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() # 切换回主页面

问题2:元素不可点击(ElementNotInteractableException)

错误信息

ElementNotInteractableException: element not interactable

可能原因

  1. 元素被其他元素遮挡
  2. 元素不可见(display: none)
  3. 元素还没加载完成

解决方法

# 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()

问题3:超时错误(TimeoutException)

错误信息

TimeoutException: Message: timeout waiting for element

解决方法

# 1. 增加等待时间 wait = WebDriverWait(driver, 20) # 从10秒增加到20秒 # 2. 设置更频繁的检查 wait = WebDriverWait(driver, 10, 0.1) # 每0.1秒检查一次 # 3. 检查网络或网站状态

问题4:浏览器驱动问题

错误信息

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)

十、学习建议与下一步

10.1 给新手的建议

  1. 从简单开始:先运行示例代码,理解每行代码的作用
  2. 多练习:修改代码中的参数,观察变化
  3. 善用打印:使用print()输出中间结果,方便调试
  4. 分步调试:不要一次性写太多代码,写完一小段就测试

10.2 练习题目

  1. 基础练习:修改代码,爬取"动物"或"汽车"图片
  2. 进阶练习:添加功能,自动下载前5张图片到本地
  3. 挑战练习:爬取其他网站,如豆瓣电影、知乎热点等

10.3 下一步学习方向

  1. 处理复杂网站:学习处理登录、验证码、Ajax加载
  2. 提高效率:学习多线程、分布式爬虫
  3. 避免被封:学习使用代理、随机延迟、伪装浏览器
  4. 数据存储:学习使用数据库(MySQL、MongoDB)

十一、总结

通过本教程,你已经学会了:

✅ Selenium基础:安装、启动浏览器、基本操作
✅ 元素定位:8种定位方式,找到网页上的任何元素
✅ 元素操作:点击、输入、获取信息、处理表单
✅ 等待机制:显式等待、隐式等待,处理动态加载
✅ 实战项目:完整的Bing图片爬虫,包含数据保存

        Selenium是一个强大的工具,不仅可以用于爬虫,还可以用于自动化测试、自动化办公等。现在你已经有了坚实的基础,可以继续探索更多高级功能了!

        记住:学习编程最好的方式就是动手实践。复制代码运行一次,然后尝试修改它,最后尝试自己从头写一个类似的项目。

        祝你学习顺利!如果有问题,可以随时查阅Selenium官方文档或在线搜索解决方案。

Read more

5步掌握OpenLLaMA:从零构建智能文案生成系统

5步掌握OpenLLaMA:从零构建智能文案生成系统 【免费下载链接】open_llamaOpenLLaMA, a permissively licensed open source reproduction of Meta AI’s LLaMA 7B trained on the RedPajama dataset 项目地址: https://gitcode.com/gh_mirrors/op/open_llama 还在为创意枯竭而烦恼?OpenLLaMA作为开源大语言模型的杰出代表,正在彻底改变传统内容创作的方式。这个基于Meta AI LLaMA 7B架构的开源复现版本,使用RedPajama数据集进行训练,为内容创作者提供了强大的AI助手工具。 🎯 OpenLLaMA的核心优势解析 OpenLLaMA不仅仅是一个普通的语言模型,它具备多项独特优势: 开源免费特性:完全免费使用,无需支付高昂的API费用,让每个创作者都能享受到AI带来的便利。 多版本选择:提供3B、7B和13B三种规模的模型,

By Ne0inhk
6.llamafactory项目介绍与安装部署

6.llamafactory项目介绍与安装部署

一、学术资源加速 * 服务说明:AutoDL提供学术资源加速服务,主要解决GitHub和HuggingFace访问速度慢的问题,但仅限学术用途且不承诺稳定性 * 加速地址:包含github.com、githubusercontent.com、githubassets.com、huggingface.co等域名 * 终端配置: * 注意事项: * 建议不需要时关闭加速,可能影响正常网络 * 关闭命令: 二、主流微调框架介绍 1. Transformer * 生态地位:Hugging Face核心库,NLP领域最广泛使用的基础框架 * 技术特点: * 支持全参数微调 * 兼容PEFT库扩展 * 优势: * 生态系统最完善,社区活跃 * 与PyTorch/TensorFlow无缝集成 * 模型和教程资源丰富 * 适用场景:中小规模模型实验、研究和开发,微调入门首选 2. PEFT * 技术定位:参数高效微调标准库 * 核心方法: * LoRA * Prefix-tuning * AdaLoRA

By Ne0inhk
微软 Copilot Cowork 深度解析:用 Kotlin + 147API 手搓一个 AI Agent

微软 Copilot Cowork 深度解析:用 Kotlin + 147API 手搓一个 AI Agent

微软最近发布的 Copilot Cowork 在技术圈炸开了锅。它变了。它不再是那个只会补全代码的插件,而是变成了你的 “Coworker”(同事)。基于 Anthropic 的 Claude 构建,它现在能像真人一样处理复杂任务。 作为开发者,我们不仅要会用,更要懂得背后的原理。今天我们就来拆解一下 Copilot Cowork 的核心逻辑,并教你如何利用 Kotlin 和 147API 构建一个属于自己的简易 AI Agent。 从 Chatbot 到 Agent 传统的 Copilot 就像一个实习生,你给它一个指令,它执行一个动作。而 Copilot Cowork 更像是一个成熟的合作伙伴。它具备了 感知(Perception)、规划(Planning) 和 执行(Execution)

By Ne0inhk
Kimi vs 豆包学术助手:AI写作降AI谁更适合中国学生?

Kimi vs 豆包学术助手:AI写作降AI谁更适合中国学生?

Kimi vs 豆包学术助手:AI写作降AI谁更适合中国学生? TL;DR Kimi和豆包都是国产AI的代表,用来辅助论文写作或降AI各有优势:Kimi擅长长文本处理和学术场景,豆包日常对话更自然。但用它们降AI效果有限,本质上还是AI生成AI。真正靠谱的降AI方案是用专业工具,推荐嘎嘎降AI(达标率99.26%)或比话降AI(不达标全额退款)。 国产AI双雄:学生党的新选择 这两年国产AI发展特别快,Kimi和豆包是最被学生群体熟知的两个名字。Kimi是月之暗面开发的,主打长文本处理能力,据说一次能处理20万字;豆包是字节跳动出品的,更像一个全能型AI助手,什么都能聊。作为即将毕业的学生,我一直在思考:这两个工具用来写论文和降AI,到底哪个更靠谱? 于是我做了一次实测对比。测试用的是一篇10000字的课程论文,知网AIGC检测原始AI率是65%。我分别用Kimi和豆包尝试降AI,同时也用嘎嘎降AI和比话降AI作为对照,看看国产通用AI和专业降AI工具之间的差距到底有多大。 Kimi降AI实测 Kimi最大的优势是长文本处理能力。一般的AI处理几千字就要分段,Kim

By Ne0inhk