使用BeautifulSoup提取沙特证券交易所数据仅获列名问题求助
问题分析
- 代码语法错误:
mydata = pd.DataFrame(columns = headers)被放在了遍历表头的for循环内部,导致每次循环都会重新创建空的DataFrame,最终表头循环结束后,mydata仅为基于最后一个表头的空数据结构。 - 动态内容加载:沙特证券交易所该页面的表格数据是通过JavaScript动态渲染的,直接用
requests.get()只能获取静态HTML框架,实际的表格行数据并未包含在返回的页面内容中。
修复方案
步骤1:修正代码语法错误
先将DataFrame的初始化移到表头循环外部,确保仅创建一次:
import requests import pandas as pd from bs4 import BeautifulSoup url = 'https://www.saudiexchange.sa/wps/portal/saudiexchange/newsandreports/reports-publications/historical-reports/!ut/p/z1/04_Sj9CPykssy0xPLMnMz0vMAfIjo8ziTR3NDIw8LAz8DTxCnA3MDILdzUJDLAyNXE30I4EKzHEqMDTTDyekoCA7zRMAIkY09Q!!/' page = requests.get(url) soup = BeautifulSoup(page.text, 'lxml') table1 = soup.find('div', id='tab1Content') headers = [] for i in table1.find_all('th'): title = i.text.strip() # 去除多余空白字符 headers.append(title) # 移到表头循环外,仅初始化一次DataFrame mydata = pd.DataFrame(columns=headers) # 检查静态页面中的行数(会输出0,说明无动态加载的行数据) rows = table1.find_all('tr')[1:] print(f"找到的行数:{len(rows)}") for j in rows: row_data = j.find_all('td') row = [i.text.strip() for i in row_data] if row: mydata.loc[len(mydata)] = row print(mydata)
步骤2:使用Selenium获取动态渲染的页面
由于页面依赖JavaScript加载数据,需用Selenium模拟浏览器打开页面,等待数据加载完成后再提取内容:
- 先安装依赖:
pip install selenium
- 编写代码(需下载对应浏览器驱动,如ChromeDriver,确保版本与浏览器匹配):
from selenium import webdriver from selenium.webdriver.chrome.service import Service 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 from bs4 import BeautifulSoup import time # 配置ChromeDriver路径,替换为你的实际路径 service = Service(executable_path='path/to/chromedriver') driver = webdriver.Chrome(service=service) url = 'https://www.saudiexchange.sa/wps/portal/saudiexchange/newsandreports/reports-publications/historical-reports/!ut/p/z1/04_Sj9CPykssy0xPLMnMz0vMAfIjo8ziTR3NDIw8LAz8DTxCnA3MDILdzUJDLAyNXE30I4EKzHEqMDTTDyekoCA7zRMAIkY09Q!!/' driver.get(url) try: # 等待表格容器加载完成,最多等待10秒 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, 'tab1Content')) ) # 额外等待2秒确保数据完全渲染 time.sleep(2) # 获取渲染后的页面源代码 page_source = driver.page_source soup = BeautifulSoup(page_source, 'lxml') table1 = soup.find('div', id='tab1Content') # 提取表头 headers = [th.text.strip() for th in table1.find_all('th')] # 提取行数据并组装成DataFrame rows = table1.find_all('tr')[1:] mydata = pd.DataFrame(columns=headers) for row in rows: row_data = [td.text.strip() for td in row.find_all('td')] if len(row_data) == len(headers): mydata.loc[len(mydata)] = row_data print(mydata) finally: # 关闭浏览器 driver.quit()
注意事项
- 浏览器驱动版本需与本地浏览器版本完全匹配,否则会出现兼容性错误。
- 频繁请求可能触发网站反爬机制,建议根据实际情况调整等待时长。
内容的提问来源于stack exchange,提问作者Goldman Clarck
相关产品推荐
相关产品推荐

