如何爬取需鼠标悬停触发的HTML popup tooltip数据?
悬停触发式Tooltip数据爬取方案
爬取网页时,部分数据存储在需要鼠标悬停才会加载渲染的popup tooltip中,未触发悬停时对应DOM节点不会出现在页面源码中,无法直接通过静态解析提取,可按以下优先级尝试解决:
方案1:直接抓后端接口(效率最高,优先选)
这种悬停才出的表格,本质是触发悬停事件后,前端发异步请求从后端拉数据再渲染成DOM,根本不需要模拟鼠标操作。
操作步骤:
- 打开浏览器F12开发者工具,切换到「网络」面板,筛选Fetch/XHR类型的请求
- 手动在页面上悬停一次触发tooltip,观察面板中新出现的请求,逐个看响应内容,找到包含目标数值(199275.89001155、4.46%、199.3k、451.6这类)的接口
- 后续爬虫直接构造请求调用这个接口拿结构化数据即可,速度比模拟浏览器快10倍以上,被反爬拦截的概率也更低。如果接口校验请求参数、请求头,就把手动触发时的请求头(尤其是cookie、referer字段)和参数原样带上即可。
方案2:接口加密无法直接调用时,用浏览器自动化工具模拟悬停
如果接口参数做了加密混淆,没法直接构造请求,就用支持真实浏览器交互的框架模拟人工操作。注意:纯静态爬取的库(比如requests+BeautifulSoup)无法执行JS,永远拿不到这部分动态加载的内容。
操作步骤:
- 选用Playwright或Selenium框架,启动浏览器实例加载目标页面
- 先定位到tooltip的触发元素(也就是平时鼠标放上去会弹出框的那个DOM节点)
- 调用框架内置的悬停方法触发事件,等待几百毫秒让tooltip的DOM渲染完成,再解析对应节点的内容即可。
示例代码(Playwright版本):
from playwright.sync_api import sync_playwright with sync_playwright() as p: # headless设为True可后台运行,不弹出浏览器窗口 browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto("替换为你的目标页面URL") # 替换为实际的悬停触发元素CSS选择器 trigger_ele = page.locator("替换为触发元素的选择器") # 模拟鼠标悬停 trigger_ele.hover() # 等待tooltip节点加载完成,可直接使用你提供的弹窗wrapper id定位 page.wait_for_selector("#popup-table-given-rdps-ability-17-0_wrapper", timeout=3000) # 提取表格内的所有文本 table_content = page.locator("#popup-table-given-rdps-ability-17-0").inner_text() print(table_content) browser.close()
- 如果页面有多个需要悬停的触发元素,写循环逐个处理即可:每个元素hover后等DOM加载,提取完数据后把鼠标移到空白区域关闭当前tooltip,再处理下一个。
方案3:排查是否为预加载隐藏内容
部分站点的tooltip内容在首次打开页面时就已经随主页面返回了,只是默认设置了隐藏样式(比如display: none、透明度为0、定位到屏幕外),悬停动作只是修改CSS让内容显示出来,根本没有发新请求。
这种情况直接在页面源码里搜索目标数值(比如199275.89),如果能搜到对应DOM节点,不管它是不是隐藏,直接解析节点内容就行,完全不需要触发悬停动作。
触发后可见的Tooltip源码参考
<div id="popup-table-given-rdps-ability-17-0_wrapper" class="dataTables_wrapper dt-jqueryui no-footer"><div class="fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix ui-corner-tl ui-corner-tr"></div><table width="100%" id="popup-table-given-rdps-ability-17-0" cellspacing="0" class="summary-table dataTable no-footer dtr-inline" role="grid"> <thead> <tr role="row"><th nowrap="" class="sorting ui-state-default" tabindex="0" aria-controls="popup-table-given-rdps-ability-17-0" rowspan="1" colspan="1" aria-label="Given By Ability: activate to sort column ascending"><div class="DataTables_sort_wrapper">Given By Ability<span class="DataTables_sort_icon css_right ui-icon ui-icon-caret-2-n-s"></span></div></th><th class="sorting ui-state-default sorting_desc" tabindex="0" aria-controls="popup-table-given-rdps-ability-17-0" rowspan="1" colspan="1" aria-sort="descending" aria-label="Amount: activate to sort column ascending"><div class="DataTables_sort_wrapper">Amount<span class="DataTables_sort_icon css_right ui-icon ui-icon-triangle-1-s"></span></div></th><th class="sorting ui-state-default" tabindex="0" aria-controls="popup-table-given-rdps-ability-17-0" rowspan="1" colspan="1" aria-label="DPS: activate to sort column ascending"><div class="DataTables_sort_wrapper">DPS<span class="DataTables_sort_icon css_right ui-icon ui-icon-caret-2-n-s"></span></div></th></tr> </thead> <tbody> <tr style="vertical-align:middle" role="row" class="odd"> <td style="min-width:120px" tabindex="0"> <img data-src="https://assets.rpglogs.com/img/ff/abilities/012000-012532.png" class="tiny-icon lazyload" "=" src="https://assets.rpglogs.com/img/ff/abilities/012000-012532.png"> <span class="Monk">Brotherhood</span>
内容的提问来源于stack exchange,提问作者Korean Monk
相关产品推荐
相关产品推荐

