在Google Colab中爬取钱币网站数据至Pandas DataFrame遇报错求助
问题:爬取钱币网站Mint字段时出现AttributeError错误
我正在指导一名痴迷钱币的学生,在Google Colab Notebook中编写Python代码,目标是爬取指定钱币网站的特定数据,并将其添加到已手动构建好的Pandas DataFrame中。目前尝试爬取单枚钱币页面的Mint字段时,遇到了AttributeError错误。
已构建的Pandas DataFrame代码
import pandas as pd pennies = pd.DataFrame({ 'category': ['Indian Head'], 'coin': ['1859 1C MS'], 'mint': ['Philadelphia'], 'mintage': [36400000], 'composition': ['Copper-Nickel'], 'weight_grams': [4.67], 'diameter_mm': [19], 'edge': ['Plain'], 'obverse_url': ['https://s3.amazonaws.com/ngccoin-production/us-coin-explorer/5747236-003o.jpg'], 'reverse_url': ['https://www.ngccoin.com/coin-explorer/united-states/cents/indian-cents-1859-1909/12057/1859-1c-ms/'] }) pennies['date'] = pennies['coin'].apply(lambda x: x[:4]) pennies = pennies[['category', 'coin', 'date', 'mint', 'mintage', 'composition', 'weight_grams', 'diameter_mm', 'edge', 'obverse_url', 'reverse_url']] pennies.head()
爬取Mint字段的报错代码
import requests from bs4 import BeautifulSoup url = 'https://www.ngccoin.com/coin-explorer/united-states/cents/indian-cents-1859-1909/12058/1860-1c-ms/' response = requests.get(url) soup = BeautifulSoup(response.content, 'html.parser') specs_list = soup.find('ul', class_='ce-coin__specs-list') mint_element = specs_list.find('strong', string='Mint:').find_next_sibling('span').text.strip() print(mint_element)
错误信息
AttributeError Traceback (most recent call last) <ipython-input-29-e47935119dab> in <cell line: 10>() 8 9 specs_list = soup.find('ul', class_='ce-coin__specs-list') ---> 10 mint_element = specs_list.find('strong', string='Mint:').find_next_sibling('span').text.strip() 11 12 print(mint_element) AttributeError: 'NoneType' object has no attribute 'find_next_sibling'
问题分析与修复方案
错误原因
报错显示'NoneType' object has no attribute 'find_next_sibling',说明specs_list.find('strong', string='Mint:')返回了None,即找不到匹配的元素。核心原因有两点:
- 页面结构细节差异:比如
strong标签的文本前后存在空格,或者网站更新了页面布局; - 反爬拦截:直接用
requests.get请求可能被网站识别为爬虫,返回的内容不完整。
修复后的代码
import requests from bs4 import BeautifulSoup import re url = 'https://www.ngccoin.com/coin-explorer/united-states/cents/indian-cents-1859-1909/12058/1860-1c-ms/' # 模拟浏览器请求头,规避基础反爬 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } response = requests.get(url, headers=headers) soup = BeautifulSoup(response.content, 'html.parser') specs_list = soup.find('ul', class_='ce-coin__specs-list') mint_value = None if specs_list: # 遍历所有列表项,鲁棒性查找Mint字段 for list_item in specs_list.find_all('li'): strong_tag = list_item.find('strong') # 用正则匹配文本,允许前后空格 if strong_tag and re.match(r'^\s*Mint:\s*$', strong_tag.text.strip()): span_tag = list_item.find('span') if span_tag: mint_value = span_tag.text.strip() break if mint_value: print(f"获取到Mint字段值:{mint_value}") else: print("未找到Mint字段,可能页面结构已变更或请求被拦截")
代码说明
- 添加
User-Agent请求头,模拟真实浏览器访问,避免被网站基础反爬拦截; - 使用正则匹配
strong标签文本,允许文本前后存在空格,提升匹配的鲁棒性; - 增加多层判断(检查
specs_list、strong_tag、span_tag是否存在),避免因单个元素缺失直接抛出异常; - 最终根据结果输出对应信息,方便调试。
将爬取结果添加到DataFrame示例
如果成功获取到Mint字段值,可以将新数据行添加到已有的DataFrame中:
if mint_value: new_coin_data = { 'category': 'Indian Head', 'coin': '1860 1C MS', 'date': '1860', 'mint': mint_value, 'mintage': None, # 可后续扩展爬取该字段 'composition': None, 'weight_grams': None, 'diameter_mm': None, 'edge': None, 'obverse_url': None, 'reverse_url': url } # 合并新数据到原DataFrame pennies = pd.concat([pennies, pd.DataFrame([new_coin_data])], ignore_index=True) # 查看更新后的DataFrame print(pennies)
内容的提问来源于stack exchange,提问作者Jason Sheinkopf
相关产品推荐
相关产品推荐

