如何匹配末尾带随机字符的CSS标签实现网页爬取
问题本质
带随机后缀的类名是网站用CSS Modules、styled-components等前端方案构建时自动生成的,每次前端版本迭代后缀就会变化,写死完整类名的爬取规则非常容易失效,是爬取现代前端站点时的常见问题。
动态类名页面的爬取方案
- 用CSS属性选择器匹配类名固定片段:不需要写全整个类名,通过前缀、包含匹配规则即可选中目标元素。针对你遇到的
media-story-card__body__3tRWy类名,固定前缀是media-story-card__body,直接用div[class^="media-story-card__body"]作为选择器,就能忽略后面的随机后缀命中所有目标元素:[class^="xxx"]:匹配class属性以xxx开头的元素[class*="xxx"]:匹配class属性包含xxx片段的元素[class$="xxx"]:匹配class属性以xxx结尾的元素
- 跳过类名找稳定定位锚点:不要死盯着类名,优先找不会随构建变动的属性做定位,比如
data-testid、aria-label、role这类语义化属性——比如搜索结果容器通常带role="list"属性,单个结果项带role="listitem"属性,这类属性是为无障碍访问设置的,极少改动。也可以根据DOM结构定位,比如找搜索结果区里所有带文章链接的a标签,稳定性比依赖动态类名高很多。 - 直接抓后端数据接口:现在大部分网站的搜索结果都是前端异步拉取的,打开浏览器F12开发者工具切到「网络」面板,筛选Fetch/XHR请求,触发一次搜索就能看到页面加载结果调用的接口,接口直接返回结构化JSON数据,不需要解析HTML,完全不受类名变动影响,爬取效率和稳定性都远高于解析渲染后的页面。
查找规范易爬链接的方法
- 优先尝试旧版页面、移动端页面:很多网站的旧版功能不会立刻下线,移动端域名(多为m.开头)的页面为了提升加载速度,结构更简单,很少使用动态生成的类名,反爬限制也相对宽松。
- 优先使用官方结构化数据源:正规内容站点一般会提供RSS订阅源、公开开放API,这类数据源格式固定,不会随意调整结构,比爬取普通网页可靠得多。
- 尝试特殊场景页面:比如打印预览页、纯文本模式页、无障碍访问版本页,这类页面为了适配特定场景,会去掉冗余的动态样式和交互,DOM结构和类名都非常规范,爬取难度低。
修改后的参考代码
from bs4 import BeautifulSoup import requests from rich.pretty import pprint text = "hello" url = f"https://www.reuters.com/site-search/?query={text}" # 必须加合法User-Agent,否则会被反爬拦截 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" } response = requests.get(url, headers=headers) soup = BeautifulSoup(response.text, "lxml") # 用类名前缀匹配替代完整类名匹配 results = soup.select('div[class^="media-story-card__body"]') for result in results: pprint(result) pprint("###############")
提示:如果加了请求头还是拿不到结果,说明页面内容是JS动态渲染的,直接按前面说的方法抓数据接口即可,不需要硬解析HTML。
内容的提问来源于stack exchange,提问作者KapJ1coH
相关产品推荐
相关产品推荐

