Selenium新手求助:抓取印尼央行2015-2020年汇率表时筛选控件报错
解决Selenium操作印尼央行汇率页面下拉框时的
elementsFromPoint错误 嘿,作为Selenium新手遇到这个问题太正常了!我来帮你拆解一下问题根源,然后一步步给出可行的解决方案~
问题根源分析
你碰到的JavascriptException: Failed to execute 'elementsFromPoint' on 'Document': The provided double value is non-finite错误,本质上是Selenium尝试点击的元素坐标无效,常见原因包括:
- 元素不在当前可视区域内(比如在屏幕外,导致浏览器计算坐标时出错)
- 元素还没完全加载完成就被触发点击
- 直接通过索引定位下拉选项太不稳定(页面结构一变就失效)
- 下拉框本身需要先展开,才能点击里面的选项(你直接定位选项点击,可能下拉框还没激活)
分步解决方案
我把代码重新调整了,不仅解决下拉框的问题,还帮你处理日期筛选和表格抓取的部分,更可靠:
1. 初始化浏览器并确保页面加载完成
先最大化窗口避免元素被遮挡,用WebDriverWait替代固定等待,确保核心元素加载好再操作:
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 from selenium.webdriver.support.ui import Select from bs4 import BeautifulSoup import time # 初始化浏览器,可选无头模式后台运行 options = webdriver.ChromeOptions() # options.add_argument("--headless=new") # 不需要可视化的话可以打开 driver = webdriver.Chrome(options=options) driver.maximize_window() # 最大化窗口,减少元素被遮挡的概率 driver.get("https://www.bi.go.id/id/moneter/informasi-kurs/transaksi-bi/Default.aspx") # 等待页面核心容器加载完成,最多等10秒 wait = WebDriverWait(driver, 10) wait.until(EC.presence_of_element_located((By.ID, "ctl00_PlaceHolderMain_biWebKursTransaksiBI_pnlKurs")))
2. 正确操作货币筛选下拉框
不要直接定位选项,先处理下拉框本身:如果是标准的<select>标签,用Select类最省心;如果是JS渲染的自定义下拉框,就先点击展开再选选项:
情况1:标准<select>下拉框(推荐)
如果ctl00_PlaceHolderMain_biWebKursTransaksiBI_ddlmatauang1是标准select标签,直接用Select类操作,稳定又简单:
# 等待下拉框可点击 currency_select = wait.until(EC.element_to_be_clickable((By.ID, "ctl00_PlaceHolderMain_biWebKursTransaksiBI_ddlmatauang1"))) select = Select(currency_select) # 推荐用文本选择,比索引稳定太多!比如选美元 select.select_by_visible_text("USD") # 如果你一定要用索引,注意HTML里option的索引从0开始,你之前的option[24]对应索引23 # select.select_by_index(23)
情况2:自定义JS下拉框
如果是点击才展开的自定义下拉框,就先触发展开,再定位选项:
# 点击下拉框展开选项列表 currency_dropdown = wait.until(EC.element_to_be_clickable((By.ID, "ctl00_PlaceHolderMain_biWebKursTransaksiBI_ddlmatauang1"))) currency_dropdown.click() # 等待目标选项加载完成,比如选USD target_option = wait.until(EC.element_to_be_clickable((By.XPATH, "//select[@id='ctl00_PlaceHolderMain_biWebKursTransaksiBI_ddlmatauang1']/option[text()='USD']"))) # 如果选项在屏幕外,先滚动到它的位置 driver.execute_script("arguments[0].scrollIntoView();", target_option) target_option.click()
3. 设置日期筛选(2015年11月-2020年11月)
页面的日期输入框可以直接输入日期,注意页面的日期格式是DD/MM/YYYY:
# 填充起始日期:2015年11月1日 start_date = wait.until(EC.element_to_be_clickable((By.ID, "ctl00_PlaceHolderMain_biWebKursTransaksiBI_txtStartDate"))) start_date.clear() start_date.send_keys("01/11/2015") # 填充结束日期:2020年11月30日 end_date = wait.until(EC.element_to_be_clickable((By.ID, "ctl00_PlaceHolderMain_biWebKursTransaksiBI_txtEndDate"))) end_date.clear() end_date.send_keys("30/11/2020") # 点击查询按钮 search_btn = wait.until(EC.element_to_be_clickable((By.ID, "ctl00_PlaceHolderMain_biWebKursTransaksiBI_btnSearch"))) search_btn.click() # 等待结果表格加载完成 wait.until(EC.presence_of_element_located((By.ID, "ctl00_PlaceHolderMain_biWebKursTransaksiBI_gvKurs")))
4. 抓取汇率表格数据
表格加载好后,用BeautifulSoup解析提取数据:
# 获取页面源码,解析表格 page_source = driver.page_source soup = BeautifulSoup(page_source, "html.parser") rate_table = soup.find("table", id="ctl00_PlaceHolderMain_biWebKursTransaksiBI_gvKurs") # 遍历表格行,跳过表头 for row in rate_table.find_all("tr")[1:]: cols = row.find_all("td") if cols: date = cols[0].text.strip() currency = cols[1].text.strip() buy_rate = cols[2].text.strip() sell_rate = cols[3].text.strip() print(f"日期: {date}, 货币: {currency}, 买入价: {buy_rate}, 卖出价: {sell_rate}")
几个关键提醒
- 别用索引定位元素:页面更新后索引会变,用文本或ID定位才是长久之计
- 一定要等元素可交互:用
element_to_be_clickable确保元素能被点击,而不是仅仅存在于DOM中 - 处理元素不可视:如果元素在屏幕外,用
scrollIntoView()滚动过去再点击 - 检查元素类型:区分标准select和自定义下拉框,用对应的操作方式
内容的提问来源于stack exchange,提问作者adinda aulia
相关产品推荐
相关产品推荐

