
本文详解当网页源码不包含浏览器所见内容时(如 valencia 马拉松成绩页),如何通过定位 iframe 源地址、结合 requests + beautifulsoup + pandas 快速提取结构化表格数据,避开 selenium 的高开销。
当你在浏览器中右键查看“查看页面源代码”(View Page Source)却找不到页面上清晰显示的运动员姓名、完赛时间等关键数据时,这通常意味着该内容并非静态 HTML 内置,而是由 JavaScript 动态渲染,或——更常见且更易处理的情况——数据实际来自嵌套的 。Valencia 马拉松官网正是典型例子:主页面仅作为容器,真实排行榜位于 iframe 的独立 URL 中。
幸运的是,这类场景往往无需启动浏览器自动化工具(如 Selenium)。只要定位到 iframe 的 src 属性指向的真实数据页 URL,即可直接用轻量级 HTTP 请求获取其 HTML,并用标准解析库提取内容。
以修正后的目标 URL 为例:
https://resultados.valenciaciudaddelrunning.com/en/2021/maraton.php?y=2021
该页面中,成绩表格被包裹在具有 ID tabPodium 的
元素内。我们可按以下步骤高效抓取:
- 使用 requests 获取 iframe 页面的原始 HTML;
- 用 BeautifulSoup 解析并精准定位目标表格元素;
- 利用 pandas.read_html()(支持从 HTML 字符串解析表格)一键转为 DataFrame,自动处理表头与行列结构。
from io import StringIO
import pandas as pd
import requests
from bs4 import BeautifulSoup
url = "https://resultados.valenciaciudaddelrunning.com/en/2021/maraton.php?y=2021"
# 获取页面内容
response = requests.get(url)
response.raise_for_status() # 确保请求成功
soup = BeautifulSoup(response.content, "html.parser")
# 定位带成绩的表格(ID 为 tabPodium)
table = soup.select_one("#tabPodium")
if not table:
raise ValueError("未找到 ID 为 'tabPodium' 的表格,请检查页面结构是否变更")
# 将表格 HTML 转为字符串并交由 pandas 解析
df = pd.read_html(StringIO(str(table)))[0]
print(df)运行后将输出结构化成绩数据:
Unnamed: 0 Name Official time Country
0 1 CHERONO, LAWRENCE 2:05:12 KEN
1 2 DESO, CHALU 2:05:16 ETH
2 3 KACHERAN, PHILEMON 2:05:19 KEN
⚠️ 注意事项与建议:
-
始终检查 robots.txt 并遵守网站的 Terms of Service;本例属公开赛事结果,通常允许合理抓取,但请添加 User-Agent 头并控制请求频率(如加 time.sleep(1));
- 若目标表格无唯一 ID,可用 soup.find("table", class_="...") 或 CSS 选择器组合精确定位;
- pandas.read_html() 默认返回列表(因页面可能含多个表格),务必通过索引 [0] 显式选取,或用 match= 参数匹配表头关键词增强鲁棒性;
- 对于真正依赖复杂 JS 渲染(如需点击分页、筛选按钮才加载数据)的页面,Selenium 或 Playwright 才是必要选择——但本例中 iframe 源页是纯服务端渲染的静态 HTML,完全无需。
掌握识别 iframe 源、直连真实数据端点的能力,是高效 Web 抓取的关键一环:它兼顾速度、稳定性与低资源消耗,远优于盲目启用浏览器自动化。