如何抓取鼠标悬停后弹出的多组日期与价格数据点?
解决Prishistorik价格历史数据抓取问题
问题分析
你的代码仅能获取一条数据,核心原因有两点:
- 元素定位错误:你用CSS选择器选中的
rect元素是图表的背景容器,而非单个价格数据点,导致prices列表仅包含一个元素; - 悬停后元素定位不稳定:固定的长XPath易受页面结构变化影响,且未确保悬停后弹出框完全加载。
解决方案一:修正Selenium元素定位与悬停逻辑
步骤1:定位正确的数据点元素
打开目标页面开发者工具,检查Prishistorik图表,会发现每个价格点对应<circle>标签(或带特定class的元素),需替换原选择器为数据点的定位规则。
步骤2:优化后的代码
from selenium.webdriver.common.by import By from selenium.common.exceptions import TimeoutException, StaleElementReferenceException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver import ActionChains from selenium import webdriver chrome_options = webdriver.ChromeOptions() chrome_options.add_argument("start-maximized") chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) chrome_options.add_experimental_option('useAutomationExtension', False) DRIVER_PATH = r'd:\8278\Downloads\chromedriver.exe' browser = webdriver.Chrome(options=chrome_options, executable_path=DRIVER_PATH) browser.get("https://prisjagt.dk/lyd-billede/horetelefoner-tilbehor/hovedtelefoner/apple-airpods-pro-2nd-generation-2022--p7054034") browser.maximize_window() explicit_wait20 = WebDriverWait(browser, 20) price_history_data = [] try: # 等待价格图表容器加载 chart_container = explicit_wait20.until( EC.visibility_of_element_located((By.CSS_SELECTOR, '.PriceHistoryWrapper-sc-1yjg8cb-3.ejhsba')) ) # 定位所有价格数据点(以circle为例,需根据实际DOM调整) data_points = explicit_wait20.until( EC.visibility_of_all_elements_located((By.CSS_SELECTOR, '.PriceHistoryWrapper-sc-1yjg8cb-3.ejhsba svg g circle')) ) for point in data_points: try: # 模拟悬停并等待弹出框渲染 ActionChains(browser).move_to_element(point).pause(0.5).perform() # 定位弹出框并提取文本 tooltip = WebDriverWait(browser, 5).until( EC.visibility_of_element_located((By.CSS_SELECTOR, '.PriceHistoryTooltip-sc-1yjg8cb-4')) ) # 分割日期与价格,整理为结构化数据 date, price = tooltip.text.split('\n') price_history_data.append({"日期": date, "价格": price}) except (TimeoutException, StaleElementReferenceException): # 跳过无法获取的异常点 continue finally: browser.quit() # 输出所有抓取到的数据 for item in price_history_data: print(f"{item['日期']}: {item['价格']}")
关键优化点
- 用短class选择器替代冗长层级CSS,避免页面结构变动导致定位失效;
- 加入
pause(0.5)确保悬停后弹出框完全渲染; - 捕获元素过期异常,避免单次失败中断整个抓取流程;
- 将弹出框文本分割为日期和价格,输出结构化数据。
解决方案二:直接提取页面JS数据(更高效稳定)
多数图表数据会预先存储在页面JS变量中,无需模拟鼠标操作,直接提取即可:
from selenium import webdriver chrome_options = webdriver.ChromeOptions() chrome_options.add_argument("start-maximized") chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) chrome_options.add_experimental_option('useAutomationExtension', False) DRIVER_PATH = r'd:\8278\Downloads\chromedriver.exe' browser = webdriver.Chrome(options=chrome_options, executable_path=DRIVER_PATH) browser.get("https://prisjagt.dk/lyd-billede/horetelefoner-tilbehor/hovedtelefoner/apple-airpods-pro-2nd-generation-2022--p7054034") # 执行JS脚本提取价格历史(变量名需根据实际页面调整) price_history = browser.execute_script(""" const productData = window.__NEXT_DATA__.props.pageProps.product; return productData.priceHistory; """) # 整理并输出数据 for entry in price_history: date = entry['date'] price = f"{entry['price']} kr" print(f"{date}: {price}") browser.quit()
优势
- 无需模拟鼠标悬停,抓取速度更快、稳定性更高;
- 直接获取原始结构化数据,无需处理文本分割。
内容的提问来源于stack exchange,提问作者R. Plate
相关产品推荐
相关产品推荐

