如何用Python结合Selenium爬取墨西哥能源网站隐藏历史原油数据?
问题
需要自动化爬取墨西哥能源网站的历史原油数据,该网站动态表格默认仅展示2023年1月至5月的数据,需通过顶部选项将起始时间设置为2018年1月才能获取更早数据。目前仅能通过静态HTML爬取2023年数据,无法通过Selenium完成自动选择起始年份、点击确认按钮等交互操作;尝试直接用HTTP Headers加载数据也未成功,现有代码如下,需完善实现历史数据爬取。
解决方案
核心问题在于确认按钮的定位错误以及缺少显式等待(避免元素未加载完成就操作),同时原表格解析逻辑仅提取单行数据,需优化为提取全量数据。以下是修复后的完整代码:
import pandas as pd from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.select import Select from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 配置参数 url = "https://sie.energia.gob.mx/bdiController.do?action=cuadro&cvecua=PMXC1C01E" webdriver_path = 'my_path' # 替换为你的ChromeDriver实际路径 chrome_options = Options() # 可选:添加无头模式,后台运行浏览器 # chrome_options.add_argument("--headless=new") # chrome_options.add_argument("--disable-gpu") # 初始化浏览器 driver = webdriver.Chrome(service=Service(webdriver_path), options=chrome_options) wait = WebDriverWait(driver, 15) # 显式等待最长15秒 try: # 打开目标页面 driver.get(url) # 点击"Opciones"按钮,展开时间设置面板 opciones_btn = wait.until(EC.element_to_be_clickable((By.ID, "opciones"))) opciones_btn.click() # 选择起始年份为2018 start_year_select = Select(wait.until(EC.visibility_of_element_located((By.NAME, "anoini")))) start_year_select.select_by_value("2018") # 点击确认按钮(修正定位:按钮实际使用的是value属性而非name) aceptar_btn = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@value='Aceptar']"))) aceptar_btn.click() # 等待表格数据加载完成(通过等待目标表格元素出现判断) wait.until(EC.presence_of_element_located((By.CLASS_NAME, "level-0"))) # 获取页面源码 html_content = driver.page_source finally: # 确保浏览器关闭 driver.quit() # 解析HTML并提取全量表格数据 soup = BeautifulSoup(html_content, "html.parser") table = soup.find("table", class_="tabla_datos") # 定位整个数据表格 # 提取表头 headers = [th.text.strip() for th in table.find_all("th")] # 提取所有数据行 rows = [] for tr in table.find_all("tr")[1:]: # 跳过表头行 cells = [td.text.strip() for td in tr.find_all("td")] rows.append(cells) # 转换为DataFrame df = pd.DataFrame(rows, columns=headers) print(df.head()) # 可选:保存到CSV # df.to_csv("mexico_crude_oil_data_2018+.csv", index=False, encoding="utf-8-sig")
关键修复点说明
- 显式等待替代固定sleep:使用
WebDriverWait确保元素加载完成后再操作,避免因网络延迟导致的元素定位失败。 - 修正确认按钮定位:原代码通过
name="Aceptar"定位失败,实际按钮的name属性并非"Aceptar",改用XPATH通过value属性定位更可靠。 - 全量表格解析:原代码仅提取单行数据,修改为定位整个表格,提取表头和所有数据行,生成完整的DataFrame。
- 异常处理:添加
try-finally块确保浏览器无论是否出错都会关闭,避免资源泄漏。
内容的提问来源于stack exchange,提问作者jare2620
相关产品推荐
相关产品推荐

