You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Playwright Python爬取弹窗建筑年份并存储到Pandas DataFrame

解决Playwright提取多建筑建造年份的加载与元素定位问题

问题背景

我在Jupyter Notebook中使用Playwright爬取房产评估网站数据,部分页面需点击View Building Details按钮才能查看多建筑信息。目前已实现点击按钮并切换至Building 2、3、4,但始终无法提取Structural Element for Building ###表格下的Year Built数据。尝试过Pandas的read_html、Playwright的wait_for_selector、wait_for_load_state("networkidle")等方法,仍存在加载相关问题。

解决方案

1. 精准等待目标元素,而非仅依赖网络状态

networkidle仅代表网络请求暂停,但动态渲染的表格可能仍未完成DOM插入。需直接等待Year Built所在的表格行出现,确保元素可被定位。

2. 使用更精准的元素选择器

避免用宽泛的表格选择器,结合表格标题和行文本定位目标单元格,比如用XPath关联表格标题与目标行,避免误定位其他建筑的表格。

3. 切换建筑后等待元素更新

切换建筑标签后页面通常是局部刷新,需等待旧表格元素消失、新表格元素加载完成,防止读取缓存的旧数据。

代码示例

from playwright.sync_api import sync_playwright
import pandas as pd

def extract_building_year(page, building_num):
    # 切换到目标建筑标签
    page.click(f"text=Building {building_num}")
    
    # 等待目标表格标题加载
    table_title_selector = f"h3:text('Structural Element for Building {building_num}')"
    page.wait_for_selector(table_title_selector, timeout=10000)
    
    # 用XPath定位Year Built对应的数值单元格
    year_xpath = (
        f"//h3[contains(text(), 'Structural Element for Building {building_num}')]"
        "/following-sibling::table//tr[td[normalize-space(text())='Year Built']]/td[2]"
    )
    year_element = page.wait_for_selector(year_xpath, timeout=10000)
    
    return year_element.inner_text().strip()

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    target_url = "你的目标房产页面URL"
    page.goto(target_url)
    
    # 展开建筑详情
    page.click("text=View Building Details")
    page.wait_for_load_state("domcontentloaded")
    
    # 获取总建筑数量(通过标签数量判断)
    building_tab_selector = "button:text-matches('Building \\d+')"
    page.wait_for_selector(building_tab_selector)
    total_buildings = len(page.query_selector_all(building_tab_selector))
    
    # 循环提取Building 2到n的年份
    for num in range(2, total_buildings + 1):
        try:
            built_year = extract_building_year(page, num)
            print(f"Building {num} 建造年份: {built_year}")
        except Exception as e:
            print(f"提取Building {num} 年份失败: {str(e)}")
    
    browser.close()

补充技巧

  • 监听AJAX请求:如果表格数据通过接口加载,可通过page.wait_for_response等待目标接口返回:
    response = page.wait_for_response(lambda r: "building-details" in r.url and r.status == 200)
    data = response.json()
    # 从返回的JSON中直接提取年份
    
  • 结合Pandas处理HTML:若仍想用read_html,需先获取当前页面的完整DOM:
    page.wait_for_selector("text=Year Built")
    html_content = page.content()
    dfs = pd.read_html(html_content)
    for df in dfs:
        if "Year Built" in df.iloc[:,0].values:
            year = df[df.iloc[:,0] == "Year Built"].iloc[0,1]
            print(year)
            break
    
  • Jupyter环境注意事项:优先使用Playwright同步模式,避免异步模式与Jupyter事件循环冲突;若用异步,需在单元格开头加%asyncio_mode=strict。

内容的提问来源于stack exchange,提问作者Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:55:17