如何解决BeautifulSoup结合pd.read_html出现的ValueError: No tables found?
问题描述
我使用BeautifulSoup从网站提取表格时,提取DAX年末行情数据(元素ID为HistKurseYear)操作完全正常,但提取阿迪达斯年末行情数据(元素ID同样为histKurseYear)时,执行以下代码触发错误:
page_Ad = requests.get( "https://www.boerse.de/historische-kurse/Adidas-Aktie/DE000A1EWWW0") soup_Ad = BeautifulSoup(page_Ad.content, 'html.parser') element_Ad = soup_Ad.find(id='histKurseYear') df_Adidas = pd.read_html(str(element_Ad))[0]
错误栈信息:
ValueError Traceback (most recent call last) <ipython-input-8-03cb2123ccf1> in <module> ----> 1 df_Adidas = pd.read_html(str(element_Ad))[0] 5 frames /usr/local/lib/python3.9/dist-packages/pandas/io/html.py in _parse_tables(self, doc, match, attrs) 567 568 if not tables: ---> 569 raise ValueError("No tables found") 570 571 result = [] ValueError: No tables found
另外,提取该网站月度末行情表格操作成功,且Excel可正常获取目标表格。请问如何获取所需的阿迪达斯年末行情表格?
解决思路与方案
1. 问题根源
直接用requests.get只能获取页面初始HTML代码,而阿迪达斯的年末行情表格是页面加载后通过JavaScript异步渲染生成的,初始HTML里并没有完整的表格结构,所以BeautifulSoup找不到有效表格,导致pd.read_html报错。而DAX的表格可能是服务器端直接渲染好的,所以能正常提取。
2. 可行解决方案
方案一:用Selenium模拟浏览器渲染
模拟浏览器完整加载页面(包括执行JS),等表格渲染完成后再提取:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import pandas as pd # 初始化Chrome浏览器(需提前安装对应版本的chromedriver) driver = webdriver.Chrome() driver.get("https://www.boerse.de/historische-kurse/Adidas-Aktie/DE000A1EWWW0") # 等待目标表格加载完成,最长等待10秒 wait = WebDriverWait(driver, 10) table = wait.until(EC.presence_of_element_located((By.ID, 'histKurseYear'))) # 将表格HTML转为DataFrame df_Adidas = pd.read_html(table.get_attribute('outerHTML'))[0] # 关闭浏览器 driver.quit()
方案二:直接抓取数据接口(更高效)
通过浏览器开发者工具抓包找到加载年末行情的API接口,直接请求接口获取JSON数据,再转成DataFrame:
- 打开浏览器F12进入开发者工具,切换到「Network」标签
- 刷新页面,筛选「XHR/Fetch」请求,搜索包含
year或histKurse的请求,找到返回行情数据的接口 - 复制接口URL和请求头,用
requests请求:
import requests import pandas as pd # 替换为实际找到的API接口地址 api_url = "https://example.com/historische-kurse/yearly-data" # 复制浏览器请求时的headers,避免被反爬 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Referer": "https://www.boerse.de/historische-kurse/Adidas-Aktie/DE000A1EWWW0" } response = requests.get(api_url, headers=headers) data = response.json() # 根据接口返回的JSON结构整理数据,示例: df_Adidas = pd.DataFrame(data['data']['yearlyPrices'])
3. 为什么Excel能正常获取?
Excel的「从网页获取数据」功能会模拟浏览器环境执行JavaScript,自动加载动态生成的内容,因此能拿到目标表格。
内容的提问来源于stack exchange,提问作者T-Dawg
相关产品推荐
相关产品推荐

