BeautifulSoup爬取谷歌加密货币价格报NoneType无find属性错误
报错根因
报错是因为soup.find('div', attrs= {'class': 'card-section PZPZlf'})这一步直接返回了None,对空值调用.find()自然会抛出属性错误。
你已经验证过URL能正常打开、soup能输出内容,但漏掉了最关键的点:默认requests请求拿到的谷歌页面,和你浏览器里看到的页面根本不是同一个。谷歌有基础反爬校验,不带浏览器标识的请求会被识别为爬虫,要么返回人机验证页,要么返回结构大幅简化的搜索页,这种页面里根本不存在你在开发者工具里看到的价格卡片节点,class选择器当然匹配不到结果。
解决方案
- 给requests请求添加真实浏览器的User-Agent请求头,模拟正常用户访问,才能拿到和浏览器端结构一致的页面
- 拆分链式
find调用,每一步匹配后做非空判断,避免直接崩溃,也方便快速定位是哪一层节点匹配失败 - 如果加了请求头还是匹配不到,把
soup.prettify()输出的内容存为本地html文件打开,对照实际返回的DOM结构调整选择器——谷歌搜索结果页的class类名是动态生成的,不同地区、不同时间访问拿到的类名可能存在差异,不要硬记固定class值
修正后可运行代码
import requests from bs4 import BeautifulSoup def getCurrentPrice(cc): url = f'https://www.google.com/search?q={cc}+price+euros' # 替换为自己浏览器的User-Agent,可在任意网页的开发者工具-请求头中找到 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' } resp = requests.get(url, headers=headers) soup = BeautifulSoup(resp.text, 'html.parser') # 逐段查找+判空,避免链式调用直接抛错 parent_card = soup.find('div', attrs={'class': 'card-section PZPZlf'}) if not parent_card: print("未匹配到价格父卡片,检查请求头或页面结构") return None price_el = parent_card.find('div', attrs={'class': 'pclqee'}) if not price_el: print("未匹配到价格节点") return None price_text = price_el.text.strip() print(f'Current Price: {price_text} EUR') return price_text # 功能测试 getCurrentPrice('bitcoin')
补充说明
如果加了合法User-Agent还是匹配不到对应class,可以换定位逻辑:比如直接在页面文本里搜索包含EUR的价格片段,向上回溯父元素定位,比硬写动态class的稳定性更高。
内容的提问来源于stack exchange,提问作者Aryan Bhobe
相关产品推荐
相关产品推荐

