使用Selenium自动化展开所有动态下拉菜单并抓取子类别链接

使用Selenium自动化展开所有动态下拉菜单并抓取子类别链接

本教程详细介绍了如何使用selenium自动化处理动态网页上的下拉菜单,以展开所有隐藏的子类别并提取其链接。通过识别并迭代点击“展开”图标,结合有效的元素定位和链接过滤策略,我们能够高效地从复杂网页结构中抓取所需数据,特别适用于需要深入导航多层级内容的场景。

在进行网页数据抓取时,经常会遇到动态加载或折叠的菜单和列表。为了访问这些隐藏的内容,特别是其中的链接,我们需要模拟用户交互,例如点击“展开”按钮或图标。本教程将以一个具体的案例为例,演示如何使用Python和Selenium库,自动化地展开网页上所有的下拉菜单,并从中提取所需的子类别链接。

1. 环境准备与初始化

首先,确保您已安装Python、Selenium库以及相应的WebDriver(如ChromeDriver)。

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECimport time # 仅用于演示,实际项目中推荐使用显式等待# 目标网页URLURL = "https://albiononline2d.com/en/item"# 初始化Chrome WebDriverdriver = webdriver.Chrome()# 设置隐式等待,在查找元素时,如果元素未立即出现,WebDriver会等待指定时间driver.implicitly_wait(5)# 访问目标URLdriver.get(URL)# 初始化ActionChains,用于执行更复杂的交互,如鼠标悬停action = webdriver.ActionChains(driver)

2. 自动化展开所有下拉菜单

对于动态网页,展开菜单通常涉及到点击一个“加号”或“展开”图标。关键在于,当一个菜单被展开后,页面结构可能会发生变化,导致之前找到的元素变得“陈旧”(StaleElementReferenceException)或列表顺序改变。因此,一种稳健的方法是在每次点击后重新查找所有可展开的图标。

在本例中,我们观察到展开图标具有 icon expand-icon ion-plus-round 类。我们将通过CSS选择器 span[class=”icon expand-icon ion-plus-round”] 来定位它们。

# 循环点击所有“展开”图标# 注意:这里使用了一个循环,每次都重新查找所有可展开的图标,# 并点击第一个找到的图标。这是因为点击一个图标可能会改变页面DOM,# 使得之前的元素列表失效,或者新的可展开图标会出现在列表的起始位置。# 这种策略确保我们总是点击当前可用的、尚未展开的第一个图标。try:    # 使用显式等待,直到至少有一个展开图标出现    WebDriverWait(driver, 10).until(        EC.presence_of_element_located((By.CSS_SELECTOR, 'span[class="icon expand-icon ion-plus-round"]'))    )    # 持续查找并点击,直到没有可点击的展开图标为止    while True:        # 重新查找所有可展开的图标        pluses = driver.find_elements(By.CSS_SELECTOR, 'span[class="icon expand-icon ion-plus-round"]')        if not pluses:            # 如果没有找到任何展开图标,说明所有菜单已展开            print("所有下拉菜单已展开。")            break        # 点击第一个找到的展开图标        # 使用try-except来处理可能出现的元素不可交互的情况        try:            pluses[0].click()            # 短暂等待,确保页面有时间响应点击并更新DOM            time.sleep(0.5)         except Exception as e:            print(f"点击展开图标时发生错误: {e}")            # 如果无法点击第一个,尝试移除它并继续,或者跳出循环            break except Exception as e:    print(f"初始化查找展开图标时发生错误: {e}")

3. 提取所有子类别链接

在所有下拉菜单都展开后,我们可以开始提取目标链接。在本例中,所有类别和子类别链接都位于一个 list-group 类的元素内,并且子类别链接的 href 属性中包含 subcat 字符串。

完整代码示例

将以上所有代码片段整合,形成一个完整的自动化脚本:

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECimport timeURL = "https://albiononline2d.com/en/item"driver = webdriver.Chrome()driver.implicitly_wait(5) # 设置隐式等待driver.get(URL)print("正在尝试展开所有下拉菜单...")try:    # 使用显式等待,直到至少有一个展开图标出现    WebDriverWait(driver, 10).until(        EC.presence_of_element_located((By.CSS_SELECTOR, 'span[class="icon expand-icon ion-plus-round"]'))    )    while True:        pluses = driver.find_elements(By.CSS_SELECTOR, 'span[class="icon expand-icon ion-plus-round"]')        if not pluses:            print("所有下拉菜单已展开。")            break        try:            # 点击第一个可展开的图标            pluses[0].click()            time.sleep(0.5) # 短暂等待页面更新        except Exception as e:            print(f"点击展开图标时发生错误或无更多可点击图标: {e}")            break # 出现错误或无法点击时退出循环except Exception as e:    print(f"初始化查找展开图标时发生错误: {e}")print("开始提取子类别链接...")subcat_links = []try:    # 再次使用显式等待,确保主类别列表加载完成    item_categories_container = WebDriverWait(driver, 10).until(        EC.presence_of_element_located((By.CLASS_NAME, 'list-group'))    )    all_links = item_categories_container.find_elements(By.TAG_NAME, 'a')    for link_element in all_links:        href = link_element.get_attribute('href')        if href and 'subcat' in href:            subcat_links.append(href)    print("n提取到的子类别链接:")    for link in subcat_links:        print(link)except Exception as e:    print(f"提取链接时发生错误: {e}")finally:    driver.quit() # 确保最后关闭浏览器

注意事项与最佳实践

元素定位器的选择: 优先使用稳定且唯一的定位器,如ID、CSS选择器或XPath。对于本例,span[class=”icon expand-icon ion-plus-round”] 是一个有效的CSS选择器。动态元素处理: 对于会改变DOM结构的交互,务必在每次交互后重新查找相关元素。本教程中 while True 循环内重新调用 driver.find_elements() 是处理动态内容的有效策略。等待机制:隐式等待 (implicitly_wait):设置一个全局的等待时间,WebDriver会在查找元素时等待这段时间。适用于大多数元素加载场景。显式等待 (WebDriverWait + expected_conditions):更精确和健壮的等待方式,可以等待特定条件(如元素可见、可点击)达成。例如,EC.presence_of_element_located 用于等待元素出现在DOM中。在处理动态内容时,推荐结合使用显式等待以提高脚本的稳定性。time.sleep():应尽量避免使用,因为它会无条件暂停脚本,浪费时间且可能导致不稳定。仅在调试或确定需要固定延迟时少量使用。错误处理: 使用 try-except 块来捕获可能发生的异常(如 StaleElementReferenceException、NoSuchElementException),使脚本更健壮。目标网站结构: 在编写自动化脚本前,务必通过浏览器开发者工具仔细分析目标网页的DOM结构和元素属性,这有助于选择正确的定位器和交互策略。资源管理: 始终在脚本结束时调用 driver.quit() 来关闭浏览器并释放资源。

总结

通过本教程,我们学习了如何使用Selenium自动化处理动态网页上的下拉菜单。核心策略是:利用CSS选择器定位“展开”图标,并通过循环和在每次点击后重新查找元素的方式,确保所有菜单被成功展开。随后,我们通过过滤链接的 href 属性来准确提取目标子类别链接。掌握这些技术,将使您能够更有效地从复杂的、交互式的网页中抓取所需数据。

以上就是使用Selenium自动化展开所有动态下拉菜单并抓取子类别链接的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1380184.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 21:34:16
下一篇 2025年12月14日 21:34:29

相关推荐

  • Pandas数据清洗教程:高效处理混合类型、多分隔符列并转换英文数字词

    本教程旨在解决pandas数据处理中常见的挑战:如何将包含混合数据类型(如英文数字词和数字字符串)以及多种分隔符的单列拆分为多个标准数值列。我们将利用正则表达式进行健壮的列拆分,结合`word2number`库智能地将英文数字词转换为数值,并最终统一数据类型,有效避免`valueerror: no …

    2025年12月14日
    000
  • Openpyxl教程:正确判断Excel单元格为空或None

    在使用openpyxl处理excel数据时,直接通过 `is none` 判断单元格是否为空可能导致误判,因为空单元格可能被解析为 `none` 或空字符串 `””`。本教程将详细解释这一现象,并提供一个健壮的解决方案,确保能够准确地识别出所有类型的空单元格,尤其在进行数据校…

    2025年12月14日
    000
  • Python电话号码字母组合:深入解析常见编码陷阱与回溯法实践

    本文深入探讨了leetcode 17题“电话号码的字母组合”问题,揭示了在使用字典处理重复数字时可能遇到的常见陷阱,该陷阱会导致组合结果丢失。文章通过分析错误代码,详细阐述了字典键唯一性对逻辑的影响,并提供了基于回溯算法的正确解决方案,旨在帮助读者掌握处理此类组合问题的通用方法,避免类似错误。 电话…

    2025年12月14日
    000
  • Pygame多进程像素渲染优化:基于Surface分片的高效方法

    本文探讨了在pygame中利用多进程优化像素渲染的策略。针对直接在子进程中修改主屏幕像素的限制和性能瓶颈,文章提出了一种高效解决方案:将屏幕划分为多个区域,每个工作进程负责在其局部surface上渲染指定区域的像素,然后将渲染结果转换为字节流传回主进程,主进程再将这些字节流转换回surface并拼接…

    2025年12月14日
    000
  • Openpyxl与Pytest:正确检查Excel单元格空值与空字符串的策略

    在使用openpyxl和pytest进行excel单元格空值检查时,常见误区是仅断言`none`。本文揭示了openpyxl可能返回空字符串而非`none`的情况,并提供了通过同时检查`none`和空字符串来确保断言准确性的解决方案,以避免测试失败,提升测试代码的健壮性。 在自动化测试或数据处理场景…

    2025年12月14日
    000
  • 解密Python datetime.strftime() 中的 %C 格式符

    本文深入探讨了python `datetime.strftime()` 方法中 `%c` 格式符的行为。尽管 `%c` 并非python官方文档中标准支持的格式符,但它在某些系统环境下可能有效,表示年份除以100的整数部分,即世纪数。文章通过示例代码解释了其输出逻辑,并强调了在日期格式化时使用标准格…

    2025年12月14日
    000
  • 在WSL Conda环境中安装CUDA加速的LightGBM

    本教程详细指导如何在WSL2环境下的Conda虚拟环境中安装并配置支持NVIDIA GPU (CUDA) 加速的LightGBM。文章将阐明OpenCL与CUDA构建的区别,提供两种主流的安装方法:通过源代码编译和使用pip安装,并演示如何在Python代码中正确启用CUDA加速。 引言 Light…

    2025年12月14日
    000
  • 优化HDFS数据访问:深入理解并启用短路本地读

    本文旨在解决HDFS数据访问中网络传输效率低下的问题,即使客户端位于数据节点上,也可能观察到高额网络流量。核心内容将详细介绍HDFS的“短路本地读”(Short-Circuit Local Reads)机制,阐述其工作原理、配置要求、优势及潜在限制,并指导用户如何在Python环境中利用此功能,从而…

    2025年12月14日
    000
  • 使用OpenPyXL在Excel单元格中精确插入和调整图片

    本教程详细介绍了如何利用Python的OpenPyXL库,将图片精确地插入到Excel工作表的特定单元格中,而非仅仅作为浮动对象。文章将通过示例代码演示图片插入的核心方法,并进一步指导如何根据图片尺寸自动调整目标单元格的行高和列宽,以确保图片在Excel中完美呈现,实现图片与单元格的紧密结合。 Op…

    2025年12月14日
    000
  • 深入解析Python字节码中的END_FINALLY指令及其演变

    end_finally是python虚拟机中一个重要的字节码指令,主要用于在finally块结束或没有匹配的except块时,恢复异常传播、return或continue操作。在早期python版本中,即使没有finally块或存在通配except,编译器也可能生成end_finally,但通过ju…

    2025年12月14日
    000
  • Python实现:将列表分割为长度递增的子列表序列

    本教程详细介绍了如何使用python将一个一维列表高效地分割成一系列子列表,其中每个子列表的长度依次递增(例如1, 2, 3…)。我们将通过一个简洁的编程方法,利用列表切片和循环逻辑,逐步构建出所需的多维列表结构,实现数据的自动化重组,无需引入复杂的额外数据结构。 问题描述 在数据处理和…

    2025年12月14日
    000
  • Python实现Excel数据追加:智能去重与更新策略

    本文详细介绍了如何使用Python的Pandas和openpyxl库,将DataFrame中的新数据高效地追加到Excel工作表,并自动跳过已存在的重复记录。通过识别并过滤现有数据,确保Excel文件内容保持唯一性和整洁性,特别适用于需要定期更新而不覆盖历史数据的场景。 在数据处理工作中,我们经常需…

    2025年12月14日
    000
  • 通过qpython安全加载KDB+加密Q脚本的最佳实践

    本文旨在解决通过python向kdb+实例加载二进制加密q文件时遇到的常见问题。核心内容是阐明加密q文件无法通过ipc直接传输其二进制内容,而必须由kdb+实例从其文件系统加载。我们将详细介绍如何利用qpython库,通过执行kdb+的`system”l”`命令来安全有效地加…

    2025年12月14日
    000
  • Keras模型输出形状异常导致DQNAgent报错的排查与解决

    本文旨在解决keras模型在与`keras-rl`库中的`dqnagent`结合使用时,因输出形状异常而引发的`valueerror`。核心问题在于`inputlayer`的`input_shape`定义不当,导致模型输出多余的维度。通过修正输入层形状,确保模型输出与`dqnagent`期望的扁平化…

    2025年12月14日
    000
  • NiceGUI设置错误:FastAPI兼容性问题及解决方案

    本文旨在解决nicegui初次设置时可能遇到的“’int’ object has no attribute ‘items’”错误。该问题通常源于nicegui与新版本fastapi(如0.108.0)之间的兼容性冲突。教程将提供详细的错误分析、临时的版…

    2025年12月14日
    000
  • Python教程:生成数字字符串中每位数字加减一的所有组合

    本教程详细介绍了如何使用python生成一个给定数字字符串的所有可能组合,其中每个数字都必须增加一或减少一。文章解释了为何存在2^n种组合(n为数字位数),并提供了一个高效的递归解决方案。特别地,教程还探讨了如何处理数字0和9的边界情况,确保生成所有预期的2^n种组合,包括环绕(wrap-aroun…

    2025年12月14日
    000
  • 使用Boto3高效检索S3存储桶中的对象:深度解析与实践

    本文详细介绍了如何利用Python的Boto3库高效地从AWS S3存储桶中检索特定路径下的对象。我们将探讨S3事件触发与手动对象列表的区别,并重点讲解如何使用自定义的`s3list`生成器函数来遍历、过滤S3对象,尤其适用于处理大量按层级结构(如日期时间)存储的数据,如日志文件。通过示例代码,您将…

    2025年12月14日
    000
  • Redisearch 全文索引与 Python 客户端:理解查询机制与常见陷阱

    本文深入探讨了在使用 Redisearch Python 客户端进行全文索引查询时遇到的常见问题,特别是关于前缀匹配和单字符查询的限制。我们将分析 Query(“s”) 返回空结果的原因,并提供正确的 Query(“sa*”) 前缀查询方法,同时介绍如…

    2025年12月14日
    000
  • Python中高效合并嵌套字典的实用指南

    本文将详细介绍如何在python中高效地合并两个字典,特别是当字典中包含嵌套结构时,如何确保所有数据不丢失,并以pythonic的方式实现。我们将通过`setdefault`和`update`方法的巧妙结合,提供一种既简洁又高效的解决方案,并解析其工作原理及适用场景。 在Python编程中,合并字典…

    2025年12月14日
    000
  • 解决SQLAlchemy关系映射错误:单一Base对象的重要性

    本文旨在解决sqlalchemy中常见的`invalidrequesterror`,该错误通常发生在定义模型间的`relationship()`时,因目标模型无法被定位而引发。核心解决方案是确保所有参与关系映射的sqlalchemy模型都使用同一个`declarative_base()`实例,从而在…

    2025年12月14日
    000

发表回复

登录后才能评论
关注微信