(二十一)观察动态页面的数据来源
1. 初始 HTML 与点击后的 DOM
练习站的 /dynamic/ 先交回一个空的 results 容器和“加载目录”按钮。点击后,脚本才请求 /api/catalog?page=1,再把返回的 items 写成 article。普通 HTTP 客户端读到的是最初那份 HTML:
# 项目文件:demos/dynamic_source.py
# 普通客户端取得初始 HTML,卡片要到浏览器执行点击事件后才出现。
from bs4 import BeautifulSoup
import httpx
from crawlsite import running_site
if __name__ == "__main__":
with running_site() as site, httpx.Client(timeout=1, trust_env=False) as client:
response = client.get(site.base_url + "/dynamic/")
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
print("初始卡片", len(soup.select("#results article")))
print("按钮", soup.select_one("#load").get_text(strip=True))输出 初始卡片 0 和 按钮 加载目录。即使 Beautiful Soup 能解析其中的 script 标签,也不会因此执行 JavaScript,更不会自动发出脚本中的 fetch。
2. 从浏览器 Network 找到实际请求
在浏览器打开练习页,开发者工具切到 Network,再点击“加载目录”。观察 Fetch/XHR 中的 /api/catalog?page=1,查看请求查询、响应状态与 JSON 正文;随后查看 Elements 中新增的 article。前者解释数据来自哪里,后者解释屏幕上的元素怎样形成。
这个接口可以直接用前面的 HTTPX 读取;需要执行点击、等待页面更新或取得浏览器运行后的 DOM 时,再让 Playwright 驱动相同过程。工具选择跟着任务需要走,不根据页面上有没有 script 标签就替整份站点下结论。