0

0

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

聖光之護

聖光之護

发布时间:2025-09-23 11:32:40

|

939人浏览过

|

来源于php中文网

原创

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 BeautifulSoup
import requests
from rich.pretty import pprint

text = "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 BeautifulSoup
import requests
from rich.pretty import pprint

text = "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("###############")

代码解析:

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

注意事项与最佳实践

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

总结

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

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

746

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

634

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

758

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

617

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1260

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

577

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

705

2023.08.11

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

80

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.8万人学习

CSS教程
CSS教程

共754课时 | 18.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号