Selenium爬取finq.com股票数据遇List out of index及空DataFrame问题
代码问题修复方案
报错根源
第一个版本List out of index报错
- 登录流程中切换到了登录iframe,登录成功后没有切回主文档上下文,后续所有页面操作都局限在已无内容的登录iframe内,解析源码时找不到
tbody标签,取索引[0]直接触发越界。 - 固定等待3秒不足以支撑动态行情数据渲染,源码中无目标表格内容。
第二个版本返回空DataFrame
- 同样存在上下文未切换、数据未加载完成的问题,找不到匹配的
tr/td元素。 - 未校验
col的长度,遇到无足够td的行时触发隐式异常,循环终止无数据写入。 - 未加
ignore_index=True参数,append操作未生效。
修正后可运行代码
你需要在登录点击操作后先切回主文档,爬取部分替换为显式等待+Selenium直接定位,不需要转BeautifulSoup解析:
import pandas as pd from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium import webdriver # finq credentials username = "xxxxxx@gmail.com" password = "xxxxxxxxx" # initialize the Chrome driver driver = webdriver.Chrome(executable_path=r'C:\Users\snyder\seaborn-data\chromedriver.exe') driver.maximize_window() driver.implicitly_wait(5) driver.get("https://www.finq.com/en/login") wait = WebDriverWait(driver, 10) wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[id='login']"))) # 输入账号密码登录 driver.find_element_by_id("login_username").send_keys(username) driver.find_element_by_id("login_password").send_keys(password) driver.find_element_by_css_selector("button[id='submit_login']").click() # 新增:登录成功后切回主文档上下文,这是核心遗漏步骤 driver.switch_to.default_content() # 登录结果校验 WebDriverWait(driver=driver, timeout=10).until( lambda x: x.execute_script("return document.readyState === 'complete'") ) error_message = "Incorrect username or password." errors = driver.find_elements_by_class_name("flash-error") if any(error_message in e.text for e in errors): print("[!] 登录失败") else: print("[+] 登录成功") wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.fn-close-popup.popup-actions"))).click() # ====== 修正后的爬取逻辑 ====== url = "https://live-cosmos.finq.com/trading-platform/#trading/Shares/Global/USA/All/FACEBOOK" driver.get(url) # 显式等待表格行加载完成,替换不稳定的固定sleep wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "tbody tr"))) df = pd.DataFrame(columns=["Instrument", "Sell", "Buy", "Change"]) # 直接用Selenium定位所有行 rows = driver.find_elements_by_css_selector("tbody tr") for row in rows: # 定位当前行的所有td cols = row.find_elements_by_tag_name("td") # 校验td数量足够再取值,避免越界 if len(cols) >=4: Instrument = cols[0].text.strip() Sell = cols[1].text.strip() Buy = cols[2].text.strip() Change = cols[3].text.strip() df = df.append({ "Instrument":Instrument, "Sell":Sell, "Buy":Buy, "Change":Change }, ignore_index=True) print(df)
额外注意事项
- 如果目标数据还是渲染在独立iframe中,可在打开行情页后,用显式等待找到对应iframe再切换进入后再定位元素。
- 原代码中重复导入了
webdriver、WebDriverWait,修正后的代码已经清理了冗余导入。
内容的提问来源于stack exchange,提问作者Snyder Fox
相关产品推荐
相关产品推荐

