接上篇《Playwright(Python) 解决iframe 上下文定位功能完整方案,附代码》,今天我们将带领大家继续学习“完整的实战代码”以及其“运行原理”等内容,正文如下:
from playwright.sync_api import sync_playwrightimport timedef find_element_with_iframe_context(page, selector, timeout=10, verbose=False):"""查找元素并确定它所在的iframe,同时收集iframe的详细信息参数:page: Playwright页面对象selector: 要查找的元素选择器timeout: 等待元素出现的超时时间(秒)verbose: 是否打印详细过程信息返回:包含元素和iframe信息的字典,如果找不到返回None"""start_time = time.time()last_frame_count = 0while time.time() - start_time < timeout:# 获取当前所有frame(包括主frame和iframe)frames = page.framesif verbose:print(f"\n检查帧... 当前帧数: {len(frames)}")if len(frames) != last_frame_count:print("帧数量变化,重新扫描")last_frame_count = len(frames)# 1. 首先在主frame中查找if verbose:print("检查主frame...")main_frame = frames[0]element = main_frame.query_selector(selector)if element:if verbose:print("元素在主frame中找到")return {'element': element,'frame_type': 'main_frame','frame': main_frame,'frame_info': {'url': main_frame.url,'name': 'main_frame','title': main_frame.title(),'parent_frame': None}}# 2. 检查所有iframefor i, frame in enumerate(frames[1:], start=1):try:if verbose:print(f"检查iframe #{i}...")# 获取iframe元素句柄frame_element = frame.frame_element()# 尝试在iframe中查找元素element = frame.query_selector(selector)if element:if verbose:print(f"元素在iframe #{i}中找到")# 收集iframe的详细信息frame_info = {'url': frame.url,'name': frame.name or f"iframe_{i}",'title': frame.title(),'parent_frame': frame.parent_frame.url if frame.parent_frame else None,'html_attributes': {}}# 获取iframe元素的HTML属性attrs = ['id', 'class', 'src', 'width', 'height', 'title']for attr in attrs:value = frame_element.get_attribute(attr)if value:frame_info['html_attributes'][attr] = valuereturn {'element': element,'frame_type': 'iframe','frame': frame,'frame_info': frame_info}except Exception as e:if verbose:print(f"检查iframe #{i}时出错: {str(e)}")continue# 短暂等待后重试time.sleep(0.5)return None # 超时后仍未找到元素def print_frame_info(frame_info):"""打印frame的详细信息"""print("\n=== Frame信息 ===")print(f"类型: {'主frame' if frame_info['frame_type'] == 'main_frame' else 'iframe'}")print(f"URL: {frame_info['frame_info']['url']}")print(f"标题: {frame_info['frame_info']['title']}")if frame_info['frame_type'] == 'iframe':print("\niframe详细信息:")print(f"名称: {frame_info['frame_info']['name']}")print(f"父frame URL: {frame_info['frame_info']['parent_frame']}")print("HTML属性:")for attr, value in frame_info['frame_info']['html_attributes'].items():print(f" {attr}: {value}")def main():with sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()# 导航到测试页面(这里用包含iframe的示例页面)page.goto('https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_iframe')# 等待页面加载page.wait_for_load_state('networkidle')# 要查找的元素选择器(这里选择iframe内的h1元素作为示例)target_selector = 'h1'# 查找元素并确定iframe上下文result = find_element_with_iframe_context(page,selector=target_selector,timeout=15,verbose=True)if result:print("\n=== 元素找到 ===")print(f"元素选择器: '{target_selector}'")print(f"元素文本内容: {result['element'].inner_text()}")# 打印frame的详细信息print_frame_info(result)# 现在你可以使用result['frame']来操作这个frame# 例如: result['frame'].click(target_selector)else:print(f"\n未找到元素: '{target_selector}'")browser.close()if __name__ == '__main__':main()
代码运行原理
1、初始化阶段:
使用 sync_playwright() 创建 Playwright 实例;
启动浏览器并创建新页面;
导航到目标 URL。
2、查找元素过程:
函数 find_element_with_iframe_context 开始执行;
进入循环,在超时时间内不断尝试查找元素;
首先在主 frame (frames[0]) 中尝试查找元素;
如果主 frame 中找不到,则遍历所有 iframe (frames[1:]);
在每个 iframe 中尝试查找目标元素;
如果找到元素,收集该 iframe 的详细信息并返回。
3、信息收集:
对于找到元素的 iframe,收集以下信息:
URL;
名称(name属性);
标题(title);
父 frame 的 URL;
HTML 属性(id, class, src 等)。
4、结果输出:
打印找到的元素信息;
打印所在 frame 的详细信息。
参数详细说明
find_element_with_iframe_context 函数参数:
1、page (必需):
类型: playwright.sync_api.Page;
说明: Playwright 的页面对象,代表当前浏览器标签页;
2、selector (必需):
类型: str;
说明: 要查找的元素 CSS 选择器,如 '#my-button' 或 '.content h1'。
3、timeout (可选,默认10):
类型: int 或 float;
说明: 等待元素出现的最大时间(秒),超时后返回 None。
4、verbose (可选,默认False):
类型: bool;
说明: 是否打印详细的查找过程信息,用于调试。
返回值说明
返回一个包含以下键的字典(如果找到元素):
1、element:
类型: playwright.sync_api.ElementHandle;
说明: 找到的元素句柄,可用于后续操作。
2、frame_type:
类型: str;
说明: 'main_frame' 或 'iframe',表示元素所在 frame 类型。
3、frame:
类型: playwright.sync_api.Frame;
说明: 元素所在的 frame 对象,可用于后续操作。
4、frame_info:
类型: dict
说明: 包含 frame 详细信息的字典,包括:
url: frame 的当前 URL;
name: frame 的 name 属性;
title: frame 的标题;
parent_frame: 父 frame 的 URL (如果是 iframe);
html_attributes: iframe 元素的 HTML 属性(id, class 等)。
链接:
https://juejin.cn/post/7528128417356775466
本文为51Testing经授权转载,转载文章所包含的文字来源于作者。如因内容或版权等问题,请联系51Testing进行删除

