news 2026/8/24 9:46:40

零基础玩转Selenium——从安装到实战的爬虫指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零基础玩转Selenium——从安装到实战的爬虫指南

1. 为什么你需要Selenium?一个爬虫新手的真实困惑

如果你刚开始学爬虫,大概率已经听过或者用过requestsBeautifulSoup这对黄金搭档。它们确实好用,抓取静态网页数据又快又准。但很快你就会遇到一个头疼的问题:当你兴冲冲地打开一个购物网站或者社交媒体,准备大展身手时,却发现用requests拿到的response.text里空空如也,只有几行基础的HTML骨架,你想要的那些商品列表、用户评论、动态加载的内容,通通不见踪影。

这就是我们常说的“动态网页”。现在的网站为了用户体验和性能,大量使用 JavaScript 在用户浏览器里实时渲染内容。传统的爬虫工具只能拿到服务器最初返回的“空壳”,而真正有价值的数据,是后来由 JavaScript 代码“画”上去的。这时候,requests就有点力不从心了。

我第一次遇到这情况时也懵了,对着浏览器里明明显示得清清楚楚的页面,代码却抓不到任何东西,那种感觉就像隔着一层单向玻璃,看得见摸不着。后来我发现了Selenium,它简直是为这类场景而生的“神器”。

简单来说,Selenium 是一个浏览器自动化工具。它最初是用来做网页自动化测试的,但爬虫开发者们很快发现,它能完美解决动态加载的问题。因为它不是直接发送HTTP请求,而是真正地启动一个浏览器(比如Chrome、Edge、Firefox),像真人一样去打开网页、等待页面完全加载、执行JavaScript,然后再去获取渲染后的完整HTML。你在浏览器里能看到什么,Selenium 就能抓到什么。

所以,Selenium 特别适合以下这些让你抓狂的场景:

  • 页面内容由 JavaScript 异步加载:比如无限滚动的社交媒体、点击“加载更多”才出现的数据。
  • 需要登录才能访问:Selenium 可以模拟输入用户名密码、点击登录按钮的全过程。
  • 操作复杂:比如需要先点击某个选项卡,再选择日期,再提交表单才能看到结果。
  • 对付简单的反爬:有些网站通过检测请求头或行为模式来反爬,而Selenium驱动的浏览器行为与真人高度相似。

当然,它也不是万能的。相比requests,它速度慢、占用资源多(毕竟开着一个浏览器)。但对于我们新手来说,先从 Selenium 入手,能让你绕过最复杂的动态内容难题,快速获得成就感,建立起信心。等基础打牢了,再去研究更高效的方案(比如分析背后的API接口)也不迟。接下来,我们就从零开始,一步步把它用起来。

2. 手把手搭建你的第一个Selenium环境

万事开头难,但Selenium的环境搭建其实比想象中简单。你只需要准备好两样东西:Python的Selenium库对应浏览器的驱动程序。我强烈建议新手使用ChromeEdge浏览器,因为它们的驱动最稳定,社区资源也最丰富。这里我以 Edge 浏览器为例,Chrome 的步骤几乎一模一样。

2.1 第一步:安装Selenium库

打开你的命令行终端(Windows上是CMD或PowerShell,Mac/Linux上是Terminal),输入下面这行命令。这是最标准的方式。

pip install selenium

如果你安装了多个Python版本,或者遇到了权限问题,可以尝试用pip3或者加上--user参数:

pip3 install selenium # 或者 pip install selenium --user

安装过程通常很快。完成后,你可以在Python里导入试试,不报错就说明成功了。

from selenium import webdriver print("Selenium 库导入成功!")

2.2 第二步:搞定最关键的浏览器驱动

这是新手最容易卡住的一步,但其实只要理清逻辑就很简单。Selenium 库本身只是个“指挥中心”,它需要靠一个叫做WebDriver的“驱动程序”来实际控制浏览器。这个驱动必须和你的浏览器版本严格匹配

具体操作步骤:

  1. 查看你的浏览器版本: 打开 Edge 浏览器,点击右上角的三个点...->帮助和反馈->关于 Microsoft Edge。你会看到一个版本号,比如版本 128.0.2739.42 (正式版本) (64 位)。记下主版本号128

  2. 下载对应版本的驱动: 访问微软官方的 Edge WebDriver 下载页面。你需要根据刚才记下的主版本号,找到对应的驱动版本进行下载。下载时选择与你操作系统匹配的文件(通常是 Windows 的msedgedriver.exe)。

  3. 放置驱动并配置路径: 下载下来的是一个msedgedriver.exe文件。你有两种方法来让Python找到它:

    • 方法A(推荐给新手):把这个exe文件直接放在你的 Python 安装目录下(或者 Scripts 目录下),因为这些目录通常已经在系统的环境变量PATH里。放进去之后,你在代码里就可以直接初始化,不用指定路径。
    • 方法B(更灵活):把驱动文件放在任何你喜欢的位置,比如D:\WebDriver\。然后在代码里初始化时,通过Service对象明确告诉 Selenium 驱动在哪。

这里我用方法B写个例子,这样你以后管理多个驱动会更清晰:

from selenium import webdriver from selenium.webdriver.edge.service import Service # 指定你的 msedgedriver.exe 文件所在路径 driver_path = r'D:\WebDriver\msedgedriver.exe' # 注意这里的 'r' 是为了防止路径中的反斜杠被转义 # 创建 Service 对象 service = Service(executable_path=driver_path) # 使用这个 service 来启动浏览器 driver = webdriver.Edge(service=service) # 如果一切正常,你会看到一个新的Edge浏览器窗口被打开 driver.get("https://www.baidu.com")

如果浏览器成功启动并打开了百度,恭喜你!环境搭建已经成功了99%。剩下的1%是可能会遇到的小坑,比如驱动版本不匹配(会报错),按照错误提示重新下载对应版本即可。

3. Selenium 核心操作:像真人一样浏览网页

环境搞定,我们就可以开始“驾驶”浏览器了。Selenium 的 API 设计得非常直观,很多方法名一看就懂。

3.1 页面级操作:导航、窗口与源码

让我们从一个最简单的脚本开始,它包含了最基础的几个操作:

import time from selenium import webdriver from selenium.webdriver.edge.service import Service service = Service(r'D:\WebDriver\msedgedriver.exe') driver = webdriver.Edge(service=service) # 打开第一个网页 driver.get("https://www.baidu.com") print("当前页面标题是:", driver.title) # 获取标题 time.sleep(2) # 等待2秒,方便我们观察 # 调整浏览器窗口 driver.maximize_window() # 最大化窗口 # driver.set_window_size(1200, 800) # 或者自定义窗口大小 # driver.set_window_position(100, 100) # 设置窗口在屏幕上的位置 # 在同一个浏览器标签页里打开新页面,会覆盖当前页面 driver.get("https://news.baidu.com") time.sleep(2) # 模拟点击浏览器的“后退”按钮 driver.back() print("后退到了:", driver.title) time.sleep(1) # 模拟点击“前进”按钮 driver.forward() print("又前进到了:", driver.title) time.sleep(1) # 刷新当前页面 driver.refresh() # 获取渲染后的完整页面HTML源码,这是爬虫最关心的! full_html = driver.page_source # 你可以把 full_html 保存下来,或者用 BeautifulSoup 等工具解析 # print(full_html[:500]) # 打印前500个字符看看 # 关闭当前标签页(如果只有一个标签页,则关闭浏览器) driver.close() # 彻底关闭浏览器并结束WebDriver进程(更干净) driver.quit()

几个关键点解释:

  • driver.get(url):这是导航到某个网址的核心命令。
  • driver.page_source:这是获取动态渲染后完整HTML的魔法属性。之前requests抓不到的数据,现在都在这里面了。
  • driver.close()driver.quit()close()关闭当前标签页,quit()退出整个浏览器并释放资源。写脚本时,最后用driver.quit()是个好习惯。
  • time.sleep(seconds):这是一个“强制等待”。让程序暂停几秒,确保页面有足够时间加载。但在真实项目中,我们会有更智能的等待方式,后面会讲。

3.2 元素级操作:与页面内容交互

能打开页面拿到源码只是第一步,我们更需要的是与页面上的具体元素互动:点击按钮、输入文字、下拉选择等等。要做到这些,首先必须找到那个元素。

如何定位元素?在浏览器页面按F12打开开发者工具,使用左上角的箭头工具,点击页面上你感兴趣的部分(比如搜索框),代码区就会高亮显示出对应的HTML代码。Selenium 提供了8种主要的定位方式,对应着HTML元素的不同属性:

定位方式代码示例 (By.XXX)适用于
IDBy.ID元素有唯一的id属性时,最快最准
NAMEBy.NAME元素有name属性时
CLASS_NAMEBy.CLASS_NAME通过元素的CSS类名定位
TAG_NAMEBy.TAG_NAME通过标签名定位,如input,div
LINK_TEXTBy.LINK_TEXT精确匹配超链接的完整文本
PARTIAL_LINK_TEXTBy.PARTIAL_LINK_TEXT匹配超链接文本的部分内容
CSS_SELECTORBy.CSS_SELECTOR使用CSS选择器,功能强大灵活
XPATHBy.XPATH使用XML路径语言,功能最强大,路径可复制

实战:模拟百度搜索我们以在百度输入框输入关键词并搜索为例,演示最常用的IDXPATH定位。

import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys # 引入键盘按键 driver = webdriver.Edge() driver.get("https://www.baidu.com") driver.maximize_window() # 方法1:通过ID定位。查看百度输入框,发现它有 id="kw" search_box = driver.find_element(By.ID, "kw") # 方法2:通过XPATH定位。在开发者工具中,右键点击元素->复制->复制XPath # search_box = driver.find_element(By.XPATH, '//*[@id="kw"]') # 在搜索框里输入文字 search_box.send_keys("Python爬虫") time.sleep(1) # 模拟按下键盘的“回车键”进行搜索 search_box.send_keys(Keys.ENTER) # 除了回车,还可以模拟点击搜索按钮,其id是‘su’ # search_button = driver.find_element(By.ID, 'su') # search_button.click() time.sleep(3) # 等待搜索结果加载 print("搜索完成,当前页面标题包含:", driver.title) driver.quit()

find_elementfind_elements的区别:

  • find_element(By.XX, "值"):返回第一个匹配到的元素。如果没找到,会抛出NoSuchElementException异常。
  • find_elements(By.XX, "值"):返回一个包含所有匹配元素的列表。如果没找到,返回空列表[]。 当你需要操作一个特定元素(如唯一的搜索框)时用前者;当需要处理一组元素(如商品列表)时用后者。

4. 等待的艺术:让爬虫更稳定可靠

上面例子中我用了很多time.sleep(3),这是为了演示方便。但在真实爬虫里,这是非常糟糕的做法。因为网络速度和电脑性能不同,固定等待时间要么太长(效率低下),要么太短(页面没加载完就操作,导致报错)。

Selenium 提供了两种更优雅的等待策略:隐式等待显式等待

4.1 隐式等待:设置全局耐心

隐式等待告诉WebDriver:在查找任何一个元素时,如果没能立即找到,就等待一段设定的时间,期间持续尝试查找,直到找到或超时。

from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Edge() # 设置隐式等待时间为10秒 driver.implicitly_wait(10) driver.get("https://一个加载很慢的网站.com") # 下面这行代码会等待,最多等10秒,直到id为‘myButton’的元素出现 # 如果10秒内出现了,就继续执行;如果10秒后还没出现,就抛出异常 button = driver.find_element(By.ID, "myButton") button.click()

隐式等待是全局性的,设置一次,对后续所有的find_elementfind_elements都生效。它简单,但不够灵活,因为它只检查元素是否存在,不关心元素是否可点击可见或有特定文本

4.2 显式等待:条件触发,精准控制

显式等待则强大和精准得多。你可以为某个特定的操作设定一个等待条件,比如“等待这个元素变成可点击状态”或者“等待这个元素里的文字包含某个关键词”。这更符合真实场景。

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 driver = webdriver.Edge() driver.get("https://www.example.com") # 创建一个WebDriverWait对象,设置最大等待时间10秒 wait = WebDriverWait(driver, 10) try: # 等待,直到ID为‘dynamicContent’的元素出现在DOM中 element = wait.until( EC.presence_of_element_located((By.ID, "dynamicContent")) ) print("元素已加载!") # 再等待,直到这个元素变得可见(不仅存在,而且宽高大于0) visible_element = wait.until( EC.visibility_of_element_located((By.ID, "dynamicContent")) ) print("元素现在可见了!") # 再等待,直到这个元素可以被点击 clickable_element = wait.until( EC.element_to_be_clickable((By.ID, "submitBtn")) ) clickable_element.click() print("按钮已点击!") except TimeoutException: print("等待超时,元素没有出现或满足条件") driver.quit()

常用的等待条件(EC)有:

  • presence_of_element_located:元素出现在DOM中(不一定可见)。
  • visibility_of_element_located:元素可见。
  • element_to_be_clickable:元素可见且可点击。
  • text_to_be_present_in_element:元素文本包含特定文字。

我的经验是:在项目里混合使用。先设置一个较短的隐式等待(如5秒)作为兜底,然后在关键操作(如点击一个异步加载的按钮)前,使用显式等待来确保状态正确。这能让你的爬虫既健壮又高效。

5. 处理复杂交互:多窗口、iframe与动作链

当爬虫需要应对更复杂的网站交互时,以下几个技巧必不可少。

5.1 多窗口/标签页切换

点击一个链接,有时会在新标签页打开。此时Selenium的焦点还在老页面,你需要手动切换。

# 获取当前所有窗口的句柄(类似于ID) original_window = driver.current_window_handle print("当前窗口句柄:", original_window) # 点击一个会在新标签页打开的链接 link = driver.find_element(By.LINK_TEXT, "打开新窗口") link.click() # 获取所有窗口句柄 all_windows = driver.window_handles # 这是一个列表 # 切换到新窗口(假设是新打开的最后一个) for window in all_windows: if window != original_window: driver.switch_to.window(window) break print("已切换到新窗口,标题是:", driver.title) # 在新窗口操作完毕后,可以切回原窗口 driver.switch_to.window(original_window) # 也可以直接新建一个标签页 driver.switch_to.new_window('tab') # 新建标签页 driver.get("https://www.newpage.com") driver.switch_to.new_window('window') # 新建浏览器窗口

5.2 处理 iframe/表单嵌套

很多登录框、广告、地图插件是嵌套在iframeframe标签里的。你必须先“进入”这个框,才能操作里面的元素。

driver.get("https://一个带iframe登录框的网站.com") # 方法1:通过iframe的id或name切换 driver.switch_to.frame("login_frame") # "login_frame"是iframe的id # 方法2:通过定位到的iframe元素切换 iframe_element = driver.find_element(By.XPATH, "//iframe[@class='modal-iframe']") driver.switch_to.frame(iframe_element) # 现在可以操作iframe里面的元素了 driver.find_element(By.NAME, "username").send_keys("your_username") driver.find_element(By.NAME, "password").send_keys("your_password") # 操作完成后,必须切回主页面 driver.switch_to.default_content() # 或者切回上一级iframe(如果有多层嵌套) # driver.switch_to.parent_frame()

5.3 动作链:模拟复杂的鼠标和键盘操作

对于拖拽、右键菜单、悬停等复杂操作,需要使用ActionChains

from selenium.webdriver.common.action_chains import ActionChains driver.get("https://一个可拖拽元素的网站.com") source = driver.find_element(By.ID, "draggable") target = driver.find_element(By.ID, "droppable") # 创建动作链对象 actions = ActionChains(driver) # 将一系列动作放入链中:点击并按住源元素 -> 移动到目标元素 -> 释放鼠标 actions.click_and_hold(source).move_to_element(target).release().perform() # 另一个例子:鼠标悬停 menu = driver.find_element(By.ID, "dropdownMenu") actions.move_to_element(menu).perform() # perform() 是执行所有链中动作的关键 # 悬停后,下拉菜单应该显示出来了,再点击其中的选项 driver.find_element(By.LINK_TEXT, "选项一").click()

6. 实战项目:爬取一个动态商品列表

让我们把所有知识串联起来,完成一个模拟小项目:爬取一个模拟电商网站(例如一个练习用的测试网站)上的商品名称和价格。假设这个网站的商品列表是滚动加载的。

import time import csv 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 from selenium.webdriver.common.keys import Keys # 初始化浏览器,并设置一些选项避免被轻易检测 options = webdriver.EdgeOptions() # 添加参数,移除“自动化控制”特征(一种基础的反反爬措施) options.add_argument("--disable-blink-features=AutomationControlled") # 不自动关闭浏览器,方便调试 options.add_experimental_option("detach", True) driver = webdriver.Edge(options=options) driver.implicitly_wait(5) # 设置全局隐式等待 wait = WebDriverWait(driver, 10) # 显式等待对象 driver.get("https://scrapingclub.com/exercise/list_infinite_scroll/") driver.maximize_window() product_data = [] # 用来存储商品信息 # 模拟滚动加载。这里假设滚动3次来加载更多商品 for scroll in range(3): # 将页面滚动到底部 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") print(f"已执行第 {scroll + 1} 次滚动") # 等待新的商品卡片加载出来。这里假设新加载的商品会有特定的类 # 使用显式等待,等待至少4个带有‘card’类的元素出现(比上一次多) time.sleep(2) # 简单等待一下网络请求,也可以换成更智能的显式等待 # 滚动完成后,开始解析页面上的所有商品 # 使用 find_elements 获取所有商品卡片 product_cards = driver.find_elements(By.CLASS_NAME, "card") # 根据目标网站的HTML结构调整选择器 print(f"共找到 {len(product_cards)} 个商品") for card in product_cards: try: # 在单个卡片元素内查找商品名和价格元素 name = card.find_element(By.CLASS_NAME, "card-title").text price = card.find_element(By.CLASS_NAME, "card-price").text product_data.append([name, price]) print(f"商品: {name}, 价格: {price}") except Exception as e: # 如果某个卡片解析失败,打印错误并继续 print(f"解析一个商品时出错: {e}") continue # 将数据保存到CSV文件 with open('products.csv', 'w', newline='', encoding='utf-8-sig') as file: writer = csv.writer(file) writer.writerow(['商品名称', '价格']) # 写入表头 writer.writerows(product_data) print(f"数据已保存到 products.csv,共 {len(product_data)} 条记录。") driver.quit()

这个例子涵盖了:基础设置、页面滚动、智能等待、元素查找(包括在父元素内查找)、异常处理和数据存储。你可以根据实际要爬取的网站,调整选择器、滚动逻辑和等待条件。

7. 进阶话题:绕开常见的检测机制

随着你频繁使用Selenium,可能会遇到一些网站提示“检测到自动化工具”或直接拒绝访问。这是因为Selenium驱动的浏览器有一些特征可以被网站检测到(例如navigator.webdriver属性为true)。这里分享几个我常用的、相对简单有效的应对方法。

1. 添加启动参数(最常用)在初始化浏览器选项时,添加一些参数可以隐藏部分特征。

from selenium import webdriver from selenium.webdriver.edge.options import Options options = Options() # 移除“自动化控制”特征 options.add_argument("--disable-blink-features=AutomationControlled") # 排除“启用自动化”的开关 options.add_experimental_option("excludeSwitches", ["enable-automation"]) # 禁用密码保存提示等弹窗 options.add_experimental_option('prefs', { 'credentials_enable_service': False, 'profile.password_manager_enabled': False }) # 使用无头模式(不显示浏览器界面,节省资源) # options.add_argument("--headless") driver = webdriver.Edge(options=options)

2. 使用undetected-chromedriver(对于Chrome/Edge)这是一个第三方库,专门用于修改ChromeDriver,使其更难被检测。它使用起来和原生Selenium几乎一样。

pip install undetected-chromedriver
import undetected_chromedriver as uc driver = uc.Chrome() driver.get("https://nowsecure.nl") # 这是一个著名的检测自动化工具的测试网站 # 正常操作... driver.quit()

3. 关于验证码这是一个更棘手的问题。对于简单的图片验证码,可以尝试接入打码平台(如超级鹰、图鉴等),用它们的API识别。但核心思路是:Selenium本身不解决验证码识别,它只负责“搬运”和“输入”。你需要用Selenium截图验证码区域,发送给打码平台,获取返回的文本,再用Selenium输入到文本框。

更复杂的滑动、点选验证码,破解成本很高。对于个人学习和中小型项目,更务实的建议是:

  • 尝试寻找网站的手机版或WAP版,其反爬可能较弱。
  • 分析网站API,如果能找到数据接口,直接请求API效率远高于模拟浏览器。
  • 降低请求频率,添加合理的随机延迟,模拟真人操作。
  • 使用代理IP池,防止因请求过于频繁而被封IP。

记住,爬虫的道德和法律边界很重要。始终遵守网站的robots.txt协议,不要对目标网站造成压力,仅用于学习和获取公开数据。从Selenium入门,理解网页交互的逻辑,然后逐步探索更高效、更专业的方法,这才是成长的正确路径。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 9:46:04

C语言文件操作实战:读写SmallThinker-3B-Preview模型生成的文本日志

C语言文件操作实战:读写SmallThinker-3B-Preview模型生成的文本日志 你是不是也遇到过这种情况?自己部署的AI模型服务跑得好好的,突然出了点小毛病,想看看它到底“想”了什么,却对着满屏滚动的日志信息无从下手。或者…

作者头像 李华
网站建设 2026/7/14 16:48:15

基于Abaqus的换档控制支架轻量化设计:从建模到优化的完整流程

1. 为什么我们要对换档控制支架“瘦身”? 大家好,我是老张,在汽车零部件结构设计这行摸爬滚打了十几年,跟各种CAE软件打了无数交道。今天想跟大家聊聊一个非常实际的话题:怎么给汽车里的换档控制支架做“轻量化设计”。…

作者头像 李华
网站建设 2026/7/14 16:48:33

解决403 Forbidden:MiniCPM-V-2_6模型API访问权限配置详解

解决403 Forbidden:MiniCPM-V-2_6模型API访问权限配置详解 最近在星图GPU平台上部署了MiniCPM-V-2_6模型,准备大展拳脚调用API时,迎面而来的却是一个冷冰冰的“403 Forbidden”。这感觉就像你兴冲冲跑到朋友家敲门,结果对方隔着门…

作者头像 李华
网站建设 2026/7/14 16:48:19

从零到一:基于ISE原理图开发与FPGA的译码器实战指南

1. 环境准备:从零搭建你的FPGA开发舞台 大家好,我是老张,一个在FPGA和嵌入式领域摸爬滚打了十多年的工程师。今天,我想带大家从一个最经典的案例——3-8译码器实现逻辑函数入手,手把手教你如何在ISE这个“老牌”开发环…

作者头像 李华
网站建设 2026/7/14 16:48:20

零门槛声音克隆教程:用CosyVoice2快速生成专属语音内容

零门槛声音克隆教程:用CosyVoice2快速生成专属语音内容 你有没有想过,用自己的声音给视频配音,但不想一遍遍录音?或者想用朋友的声音录一段生日祝福,但又不好意思开口?上周我试了一个叫CosyVoice2的工具&a…

作者头像 李华
网站建设 2026/7/14 16:48:19

从开发到上线:在快马平台实战构建基于openclaw的新闻聚合Web服务

最近在做一个新闻聚合的小项目,想把几个常看的网站信息整合到一个页面里,方便浏览。一开始想自己从头写爬虫、搭后端、做前端,想想就觉得麻烦,光是环境配置和服务器部署就能劝退不少人。后来发现,用 InsCode(快马)平台…

作者头像 李华