Python网络爬虫:应对动态CSS类名选择的策略

python网络爬虫:应对动态css类名选择的策略

在Python网络爬虫中,面对现代网站动态生成的随机CSS类名(如media-story-card__body__3tRWy)是常见挑战。本文将详细介绍如何利用CSS属性选择器,特别是“以…开头”的选择器([attribute^=”value”]),来有效定位这些元素。通过实例代码,您将学会如何编写更健壮的爬虫,成功提取数据,即使面对变化的网页结构。

动态CSS类名:爬虫的挑战

现代网站为了优化性能、实现组件化或防止简单爬虫,常常会采用前端框架(如React、Vue、Angular)来动态生成CSS类名。这些类名通常包含随机字符或哈希值,例如media-story-card__body__3tRWy,与传统的稳定类名(如search-result-content)形成鲜明对比。当类名频繁变化时,依赖固定类名进行元素选择的爬虫会很快失效,导致数据抓取失败。

对于网络爬虫开发者而言,这意味着不能简单地复制浏览器开发者工具中看到的完整类名来定位元素。我们需要一种更灵活、更具韧性的选择策略。

解决方案:CSS属性选择器

CSS属性选择器提供了一种强大的方式,允许我们根据元素的属性及其值来选择元素,而不仅仅是ID或完整的类名。当类名具有可预测的前缀但后缀随机时,属性选择器显得尤为有效。

1. 以特定前缀开头的属性选择器 ([attribute^=”value”])

这是解决动态类名问题的核心方法。它允许我们选择那些指定属性值以特定字符串开头的元素。

立即学习“Python免费学习笔记(深入)”;

语法: [attribute^=”prefix_value”]

示例:如果一个元素的类名是media-story-card__body__3tRWy,我们可以观察到media-story-card__body__这部分是相对稳定的前缀。因此,我们可以使用div[class^=”media-story-card__body__”]来选择所有类名以media-story-card__body__开头的div元素。

2. 其他常用属性选择器

除了“以…开头”的选择器,还有其他几种属性选择器在不同场景下也很有用:

*`[attribute=”value”]:包含特定子串** 选择属性值中包含指定子串的元素。例如,div[class*=”story-card”]可以选择类名中包含story-card的所有div`元素。[attribute$=”value”]:以特定后缀结尾选择属性值以指定字符串结尾的元素。这在某些特定场景下也可能有用,但对于随机后缀的类名则不适用。[attribute=”value”]:属性值完全匹配选择属性值完全等于指定字符串的元素。这适用于稳定的属性值。

实战演练:使用BeautifulSoup与属性选择器

下面我们将通过一个具体的Python爬虫示例来展示如何应用CSS属性选择器。

原始问题代码(可能失效):

from bs4 import BeautifulSoupimport requestsfrom rich.pretty import pprinttext = "hello"url = f"https://www.reuters.com/site-search/?query={text}"response = requests.get(url)soup = BeautifulSoup(response.text, "lxml")# 尝试直接选择完整的动态类名,这很容易失效results = soup.select("div.media-story-card__body__3tRWy") for result in results:    pprint(result)    pprint("###############")

在上述代码中,div.media-story-card__body__3tRWy这种选择器依赖于完整的动态类名,一旦3tRWy部分发生变化,代码就会失效,无法抓取到任何结果。

优化后的代码(使用属性选择器):

from bs4 import BeautifulSoupimport requestsfrom rich.pretty import pprinttext = "hello"url = f"https://www.reuters.com/site-search/?query={text}"response = requests.get(url)response.raise_for_status() # 检查请求是否成功soup = BeautifulSoup(response.text, "lxml")# 使用CSS属性选择器:选择所有类名以"media-story-card__body__"开头的div元素# 这样即使类名后缀随机变化,只要前缀稳定,也能准确选中results = soup.select('div[class^="media-story-card__body__"]') if not results:    print(f"未找到匹配 '{text}' 的结果,请检查选择器或网页结构。")for i, result in enumerate(results):    print(f"--- 结果 {i+1} ---")    # 这里可以进一步解析每个result,例如提取标题、链接等    # 假设标题在一个a标签内,且其类名也可能部分动态    title_tag = result.select_one('a[class^="media-story-card__heading__"]')    if title_tag:        pprint(f"标题: {title_tag.get_text(strip=True)}")        pprint(f"链接: {title_tag['href']}")    else:        pprint("未找到标题或链接。")    print("###############")

代码解析:

soup.select(‘div[class^=”media-story-card__body__”]’):这是关键的改进。它不再依赖完整的类名,而是寻找所有div元素,其class属性值以media-story-card__body__开头。这样,无论后面的随机字符如何变化,只要这个前缀保持不变,我们就能成功选中目标元素。response.raise_for_status():这是一个良好的实践,用于检查HTTP请求是否成功,如果状态码不是200,会抛出异常,避免后续解析错误。对结果进行迭代和进一步解析:在找到主要容器元素后,我们通常还需要从这些容器中提取更具体的数据,如标题、链接、摘要等。这里也示范了如何对子元素使用类似的属性选择器。

注意事项与最佳实践

选择稳定的前缀: 在使用^=选择器时,选择一个尽可能长且稳定的前缀至关重要。过短的前缀可能导致选中不相关的元素,而过长的前缀则可能因微小变化而失效。通过观察多个页面和刷新页面来确定最稳定的前缀。结合其他选择器: 如果仅靠属性前缀选择器仍然不够精确,可以将其与其他CSS选择器结合使用,例如:div[class^=”some-prefix”] > h2.title-class(子元素选择器)、div[class^=”some-prefix”] + p(相邻兄弟选择器)等。利用浏览器开发者工具: 熟练使用浏览器的开发者工具(F12)是发现稳定选择器的关键。检查元素: 右键点击目标元素,选择“检查”,观察其HTML结构和属性。观察类名变化: 刷新页面多次,看哪些部分是动态变化的,哪些是稳定的。尝试CSS选择器: 在开发者工具的控制台(Console)中,可以使用$$(‘css-selector’)来测试你的CSS选择器是否能准确选中目标元素。考虑API接口: 对于高度动态或反爬机制严格的网站,直接爬取HTML可能非常困难。有时,网站会提供公开或隐藏的API接口来获取数据。通过监控网络请求(Network tab in DevTools),你可能会发现这些API,直接调用API通常比解析HTML更高效和稳定。处理JavaScript渲染: 如果页面内容是通过JavaScript动态加载的,requests库可能无法获取到完整内容。在这种情况下,你需要使用Selenium或Playwright等工具来模拟浏览器行为,等待JavaScript执行完毕后再进行解析。

总结

面对现代网站中常见的动态CSS类名,直接使用完整的类名进行选择是不可靠的。通过掌握CSS属性选择器,特别是“以…开头”的选择器([attribute^=”value”]),我们可以编写出更具鲁棒性的网络爬虫。结合浏览器开发者工具进行细致的分析,选择最稳定的属性前缀,并灵活运用其他选择器,将大大提高爬虫的成功率和维护性。在遇到极端情况时,也应考虑探索API接口或使用无头浏览器等高级策略。

以上就是Python网络爬虫:应对动态CSS类名选择的策略的详细内容,更多请关注创想鸟其它相关文章!

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
如何用Golang实现指针安全访问_Golang 指针安全操作实践
上一篇 2026年5月10日 10:53:51
如何在Monaco编辑器中嵌入并编辑图片?
下一篇 2026年5月10日 10:53:58

相关推荐

  • Python Pandas:根据指定分隔符及大写字母规则拆分字符串列

    本文介绍了如何使用 Python Pandas 库,根据包含大写字母的特定分隔符拆分字符串列。我们将探讨使用 str.extract 函数结合正则表达式来实现这一目标,并提供详细的代码示例和解释,帮助你理解和应用这种方法。 在数据处理中,经常会遇到需要根据特定规则拆分字符串列的情况。例如,我们需要根…

    2026年5月10日
    000
  • python中canvas颜色有哪些

    python中canvas颜色有基本颜色、RGB颜色、十六进制颜色和随机颜色。详细介绍:1、基本颜色,如红色、绿色、蓝色、黄色、黑色、白色等,这些颜色可以通过直接使用它们的名称来使用;2、RGB颜色模式是通过红色、绿色和蓝色的组合来创建颜色的一种方式;3、十六进制颜色码是通过在#字符后面跟随6位16…

    2026年5月10日
    000
  • 使用JS动态生成HTML时如何管理状态_使用JS动态生成HTML时如何管理状态策略

    答案:管理JavaScript动态生成HTML的状态需以数据驱动UI。1. 使用单一数据源确保状态集中,如将用户信息存于对象中,更新时先改数据再重新渲染;2. 封装状态与逻辑,用类组织数据和方法,调用方法后自动刷新视图;3. 借鉴响应式模式,通过Proxy监听状态变化并自动更新界面;4. 避免频繁直…

    2026年5月10日
    000
  • 以太坊和比特币的区别_主要差异在哪里

    比特币是去中心化电子现金,专注价值存储与转移;以太坊是可编程平台,支持智能合约与去中心化应用,二者在定位、技术与生态上根本不同。 以太坊和比特币:不仅仅是数字资产的差异 当人们谈论加密世界时,比特币和以太坊是两个无法绕开的名字。虽然它们常常被并列提及,但实际上,两者在设计哲学、核心功能和未来愿景上存…

    2026年5月10日
    000
  • Web开发教程:如何在HTML容器中正确调整图片大小

    Web开发教程:如何在HTML容器中正确调整图片大小Web开发教程:如何在HTML容器中正确调整图片大小Web开发教程:如何在HTML容器中正确调整图片大小Web开发教程:如何在HTML容器中正确调整图片大小

    本教程旨在解决HTML中图片无法按预期在容器内缩放的问题。当图片尺寸超出其父容器时,通常需要通过CSS设置图片的width: 100%,使其自适应父容器的宽度,从而避免溢出并实现响应式布局。文章将详细阐述这一核心解决方案,并提供代码示例,帮助开发者掌握图片在Web页面中的正确缩放技巧。 理解图片在H…

    2026年5月10日 用户投稿
    000
  • php数据库如何实现增删改查 php数据库基本操作的综合教程

    使用PDO实现PHP数据库操作,需通过预处理语句执行增删改查。1. 连接数据库时设置DSN和异常模式;2. 插入数据使用prepare与execute防止SQL注入;3. 查询用fetchAll或fetch获取结果;4. 更新和删除同样采用预处理绑定参数,确保安全。核心是始终使用预处理机制避免拼接S…

    2026年5月10日
    000
  • c++中decltype关键字的用法 _c++ decltype关键字解析

    decltype 是 C++11 关键字,用于编译时推导表达式类型,包含引用和 const 限定符;其规则分三种情况:标识符或成员访问返回声明类型,加括号的表达式视为左值返回 T&,函数调用或右值返回确切类型但不带引用;常用于模板、泛型编程和尾置返回类型,如 decltype(t + u) …

    2026年5月10日
    000
  • HTML如何添加字体图标?iconfont怎么引入?

    字体图标不显示最常见的原因是路径错误,需检查iconfont.css中字体文件的url路径是否与实际存放位置一致,并通过浏览器开发者工具的network面板确认字体文件是否404;2. 确保html元素同时包含基础类名iconfont和具体图标类名如icon-home,类名缺失会导致图标无法渲染;3…

    2026年5月10日
    000
  • Golang指针与闭包变量捕获区别分析

    指针保存变量内存地址,可间接读写值;2. 闭包捕获外部变量本身而非值,循环中goroutine易误共享变量导致数据竞争。 在Go语言中,指针和闭包变量捕获是两个容易混淆的概念,尤其在循环中使用goroutine或匿名函数时。它们的行为差异直接影响程序的正确性,理解其机制对编写安全、可预测的代码至关重…

    2026年5月10日
    000
  • python进程的交流方式

    Python中进程间通信主要有四种方式:1. multiprocessing.Queue支持跨进程安全的数据传递,适用于多生产者消费者场景;2. multiprocessing.Pipe提供双向通信通道,适合两个进程间的点对点高效通信;3. Value和Array通过共享内存实现简单数据类型共享,性…

    2026年5月10日
    000
  • JSON文件转换为二进制格式后,体积一定会缩小吗?

    json 文件转换为二进制格式后,体积会缩小吗?这取决于具体情况。 JSON (JavaScript Object Notation) 是一种常用的数据交换格式,易于人类阅读和编写。但它也可能比较冗余,尤其是在处理大量数据时。 将 JSON 转换为二进制格式,通常可以减少文件大小,因为二进制格式更紧…

    2026年5月10日
    000
  • 非关联元素悬停交互:使用JavaScript动态调整DIV亮度

    本文详细介绍了如何通过javascript实现对非关联html元素进行悬停交互效果,具体演示了当鼠标悬停在一个`div`上时,如何动态改变另一个`div`的亮度。教程涵盖了html结构、javascript事件监听与css `filter`属性的应用,并提供了完整的代码示例、平滑过渡效果的实现以及最…

    2026年5月10日
    000
  • BRC-20和Ordinals协议是什么?比特币生态的新革命还是昙花一现

    BRC-20代币标准是技术创新也是短暂热潮:它基于Ordinals协议为“聪”编号并铭刻数据,实现比特币网络上的资产发行;其核心机制是通过JSON文本铭刻模拟代币操作,不依赖智能合约而依赖链下索引器,引发去中心化争议;尽管拓展了比特币功能、提升矿工收入、体现公平发行精神,但也导致网络拥堵、费用高涨、…

    2026年5月10日
    000
  • 如何用Golang实现指针安全访问_Golang 指针安全操作实践

    指针安全需确保初始化后使用,避免nil解引用,如用new()或&初始化;返回局部变量地址时依赖逃逸分析;并发访问时用sync.Mutex或atomic保护共享数据;通过接口封装降低暴露风险,始终假设指针可能为nil并协调共享访问。 在 Go 语言中,指针提供了对内存的直接访问能力,提升了性能…

    2026年5月10日
    000
  • 获取 Android WebView 新窗口 URL 的正确方法

    本文档旨在解决 Android WebView 中 `onCreateWindow` 方法无法直接获取 `window.open()` 打开的新窗口 URL 的问题。通过重写 `WebViewClient` 的 `shouldOverrideUrlLoading` 方法,并结合 `WebChrome…

    2026年5月10日
    000
  • FastAPI如何高效实现类似Django-filter的大于小于范围筛选?

    FastAPI高效实现数据范围筛选,媲美Django-filter Django的django-filter库提供便捷的数据库范围筛选功能。本文将探讨如何在FastAPI中高效实现类似功能,无需依赖额外库。 FastAPI本身不包含类似django-filter的工具,但我们可以巧妙地利用SQLAl…

    2026年5月10日
    000
  • Go语言:不使用 flags 包获取命令行参数的实践

    本文将深入探讨在Go语言中,如何在不依赖标准库flags包的情况下,直接获取和处理命令行参数。通过使用os.Args,开发者可以访问程序启动时传入的原始参数切片,这对于实现自定义的、符合特定规范(如GNU风格)的命令行解析器至关重要。文章将提供详细的代码示例,并解析os.Args的结构与应用场景,帮…

    2026年5月10日
    000
  • css怎么把导航栏固定住

    在css中,可以利用position属性把导航栏固定住,只需要给导航栏元素添加“position:fixed;”样式,将导航栏相对于浏览器窗口进行固定定位即可,这样被固定的导航栏元素就不会随着滚动条的拖动而改变位置。 本教程操作环境:windows7系统、CSS3&&HTML5版、D…

    2026年5月10日
    000
  • 将React组件转换为Qwik组件:qwik-react 的使用与考量

    本文旨在阐述如何使用 `qwik-react` 将 React 组件集成到 Qwik 应用中。我们将深入探讨 `qwikify$` 的作用机制,分析其在迁移 React 应用到 Qwik 时的优势与局限性,并强调过度使用 `qwikify$` 可能带来的性能问题。同时,本文还将讨论在 Qwik 项目…

    2026年5月10日
    000
  • 解决 Carbon::parse 无法解析复杂数据结构中的日期时间字符串问题

    本教程详细阐述了在使用 carbon 解析日期时间时,如何处理来自数据库查询结果或 json 字符串等复杂数据结构中嵌套的 `created_at` 字段。文章将通过示例代码演示如何正确提取日期时间字符串,并将其转换为 carbon 实例,从而避免常见的解析错误,并顺利进行日期时间操作,如添加天数和…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信