You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python股票爬取遇3位数字值失败:KeyError问题求助

嘿,我来帮你搞定这个爬虫问题!

首先得澄清一个误解:你遇到的KeyError: 03位数字的股票数值完全没关系,本质是你的代码在尝试访问一个空DataFrame的索引0——简单说就是,你要找的日期在网页表格里根本没有对应数据,导致筛选后的结果为空,这时候硬取row.loc[0,...]自然会报错。

错误原因拆解

从错误栈和你的代码来看,问题出在这一行:

value = (row.loc[0,'Erster Schluss'].split()[0]).replace(',','.')

df[df['Datum']== previous.strftime('%d.%m.%y')]没有匹配到任何行时,得到的是一个空DataFrame,哪怕reset_index()之后,它依然没有索引为0的行,直接调用loc[0]就会抛出KeyError: 0。你误以为是3位数字导致的,只是刚好那些日期的历史数据在网页里缺失而已。

另外你的代码还有一个隐藏bug:你把网页解析的代码(src = response.contentsoup = BeautifulSoup(...))放在了while循环里,但response只请求了一次!这意味着你每次循环都在重复处理同一个页面的内容,根本没有获取新日期的数据。

解决方案

1. 先检查DataFrame是否为空,再访问数据

在尝试取row.loc[0,...]之前,先判断筛选后的结果是否有数据,避免空指针错误:

row = df[df['Datum']== previous.strftime('%d.%m.%y')].reset_index()
# 先确认row不是空的
if not row.empty:
    value = row.loc[0,'Erster Schluss'].split()[0].replace(',','.')
    print(value)
    date = previous.strftime('%d.%m.%y')
    shareValues.append([value, date])
else:
    print(f"⚠️ 没有找到{previous.strftime('%d.%m.%y')}的历史数据")

2. 优化网页解析逻辑,避免重复解析

把网页请求和解析的代码移到循环外面,只执行一次(如果该页面包含你需要的所有历史数据):

def loadFromWebsite(company,ISIN):
    count = 28
    URL = "https://www.boerse.de/historische-kurse/{0}-Aktie/{1}".format (company, ISIN)
    shareValues = []
    
    # 只请求一次网页,避免重复请求浪费资源
    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'
    }
    response = requests.get(URL, headers=headers)
    src = response.content
    soup = BeautifulSoup(src, 'html.parser')
    tables = soup.find_all("table")
    
    date_object = datetime.datetime.now()
    start = date_object + datetime.timedelta(days = -1)
    previous = start
    
    while count > 0:
        if previous.weekday() < 5:
            target_date = previous.strftime('%d.%m.%y')
            data_found = False
            for table in tables:
                if target_date in table.text:
                    df = pd.read_html(str(table))[0]
                    row = df[df['Datum'] == target_date].reset_index()
                    if not row.empty:
                        # 不管是几位数字,这里都能正常处理
                        value = row.loc[0,'Erster Schluss'].split()[0].replace(',','.')
                        print(f"{target_date}: {value}")
                        shareValues.append([value, target_date])
                        data_found = True
                        break  # 找到对应日期的表格就退出循环
            if not data_found:
                print(f"⚠️ 无数据:{target_date}")
        count -= 1
        previous = previous + datetime.timedelta(days = -1)
    return shareValues

# 调用函数
loadFromWebsite("TecDax","DE0007203275")

3. 额外优化建议

  • 加入User-Agent请求头:避免被网站的反爬机制拦截,模拟浏览器请求
  • 打印df.columns确认列名:有时候网页表格的列名可能有空格或特殊字符,确保你用的Erster Schluss是准确的列名

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

火山引擎 最新活动