You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python BeautifulSoup如何定位第n个子节点并提取打印文本

问题根因

你报'NoneType' object has no attribute 'p'是三个核心问题导致的:

  • 裸发requests请求没带请求头,CoinMarketCap会直接返回反爬拦截页,你拿到的源码里根本没有目标DOM节点,soup.find()自然返回None
  • 你写的sc-1rmt1nr-0 sc-1rmt1nr-2 iMyvIy是前端打包生成的动态哈希类名,网站发版就会变化,全量匹配类名的写法稳定性极差
  • 元素遍历逻辑错误:find_all()返回的是列表,你取[1]拿到的是单个标签,对单个标签做for循环实际是遍历它的所有子节点,很容易拿到非币种行的节点,后续find()找不到目标元素就返回None,再调用.p就会触发报错。
可运行的修正代码

不要硬编码全量动态类名,用板块标题+类名片段做定位,加浏览器请求头绕过基础反爬:

from bs4 import BeautifulSoup
import requests

# 携带正常浏览器UA,绕过基础反爬校验
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"
}
resp = requests.get('https://coinmarketcap.com/', headers=headers)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, 'lxml')

# 定位Biggest Gainers板块,避开动态类名变化的影响
gainers_section = None
for block in soup.find_all('div', class_=lambda v: v and 'sc-1rmt1nr-0' in v):
    block_title = block.find('h3')
    if block_title and 'Biggest Gainers' in block_title.get_text(strip=True):
        gainers_section = block
        break

if not gainers_section:
    print("未找到涨幅榜板块,请检查请求是否被拦截")
else:
    # 提取前3个币种条目
    top3 = gainers_section.find_all('a', href=lambda x: x and x.startswith('/currencies/'))[:3]
    for rank, coin_entry in enumerate(top3, 1):
        coin_name = coin_entry.find('p').get_text(strip=True)
        print(f"涨幅榜第{rank}名:{coin_name}")
定位第n个子板块的通用方法

不要硬编码子节点索引[1],网站调整板块顺序后代码会直接失效,通用逻辑如下:

  • 先拿到所有同层级的板块容器
  • 遍历每个容器,读取容器的标题文本,匹配到目标板块(比如Biggest Gainers、Trending)后再做后续解析
  • 所有find()操作拿到结果后先判断是否为None,再读取子节点、文本属性,避免触发AttributeError

内容的提问来源于stack exchange,提问作者neverlandcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:51:17