从雅虎财经爬取表格后拼接DataFrame遇ValueError报错求助
解决雅虎财经爬取财报表格拼接时的
ValueError: No objects to concatenate问题 Hey there, let's break down why you're hitting that error and fix your script step by step.
问题根源分析
- 循环逻辑冗余且重复:你嵌套了两个
range(CalendarDays)循环(外层用了trange,内层又用普通range),这会导致你重复请求同一个日期多次(比如CalendarDays=3时,会请求3次今天、3次明天、3次后天),完全没必要,还可能触发网站的反爬限制。 - 空列表触发拼接失败:如果所有日期的请求都没成功拿到表格(比如某段时间没有财报发布、请求被拦截,或者页面结构变化导致
pd.read_html没找到表格),你的tables列表会是空的,pd.concat()自然会报错说没有对象可以拼接。 - 异常捕获不全面:当前只捕获了
ValueError,但网络请求失败、页面没有表格导致url[0]索引错误这些情况都会让表格无法添加到列表里,这些异常没被处理的话,脚本会直接中断或者跳过有效数据的收集。
修正后的脚本
import sys import datetime import pandas as pd from tqdm import trange CalendarDays = 3 # 指定要抓取的财报发布天数 tables = [] # 存储表格的空列表 # 用trange直接遍历日期,同时显示进度条 for i in trange(CalendarDays, file=sys.stdout, desc=f'Grabbing earnings releases for the next {CalendarDays} days'): date = (datetime.date.today() + datetime.timedelta(days=i)).isoformat() pd.set_option('display.max_columns', None) try: # 添加请求头模拟浏览器访问,避免被反爬拦截 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' } # pd.read_html支持通过requests参数传递请求头 url_tables = pd.read_html( f"https://finance.yahoo.com/calendar/earnings?day={date}", header=0, requests_kwargs={'headers': headers} ) # 检查是否拿到了表格 if len(url_tables) > 0: table = url_tables[0] table['Earnings Release Date'] = date tables.append(table) print(f"Successfully fetched data for {date}") else: print(f"No tables found for {date}") except Exception as e: # 捕获所有异常并打印,方便排查问题 print(f"Error fetching data for {date}: {str(e)}") continue # 拼接前先检查列表是否为空 if tables: df = pd.concat(tables, ignore_index=True) print(f"Successfully concatenated {len(tables)} tables into a DataFrame!") # 可以在这里添加保存或查看数据的代码 # df.to_csv('earnings_data.csv', index=False) else: print("No valid tables were fetched. Cannot concatenate.")
关键改动说明
- 简化循环结构:去掉了冗余的内层循环,直接用
trange遍历日期,同时保留进度条功能。 - 添加请求头:模拟浏览器请求,降低被雅虎财经反爬拦截的概率,这是很多爬取失败的常见原因。
- 增加表格存在性检查:在拿到
url_tables后先判断长度,避免因为页面结构变化导致url[0]索引错误。 - 全面异常捕获:用
Exception捕获所有异常并打印错误信息,方便你排查具体是哪一天的请求出了问题。 - 空列表预检查:在调用
pd.concat()前先判断tables是否有内容,避免触发原错误,同时给出明确提示。
额外建议
- 如果还是拿不到数据,先手动访问对应的URL(比如
https://finance.yahoo.com/calendar/earnings?day=2024-05-20),看看页面是否有财报数据,或者是否需要登录。 - 雅虎财经的页面结构可能会更新,如果
pd.read_html无法识别表格,可能需要改用BeautifulSoup手动解析页面元素。
内容的提问来源于stack exchange,提问作者June Smith
相关产品推荐
相关产品推荐

