小白python入门 - 38. 动态内容:接口优先与自动化扫盲

1. 本课定位:是什么、为何重要

上一课我们假设:打开页面源码,数据就在 HTML 标签里,用选择器就能抽。可你一定遇到过另一种网站------浏览器里列表清清楚楚,一查看网页源代码却是转圈空壳。那不是你选择器没写好,而是数据根本稍后才通过 XHR/Fetch 拉 JSON 填上去。

这一课主线叫「接口优先」:先找到 JSON 接口,用 requests 直接拿字段;浏览器自动化只作半页扫盲,不是必会实战。它把 Day33/34 的 HTTP 肌肉和 Day37 的解析场景接起来,并告诉你何时不该爬页面。

第 37 课假设 HTML 里已经有 要抽的字。

现实中很多站:首屏 HTML 是空壳,列表数据由浏览器再发 XHR/FetchJSON 填上------这就是「页面上看得到,View Source 里没有」。

路径 做法 评价
硬爬最终 HTML 等 JS 渲染完再解析 慢、脆、重
接口优先(主菜) 直接请求 JSON 接口 稳、省、好存
浏览器自动化(半页) Playwright / Selenium 最后手段

为何重要: 能少爬页面就少爬;能走官方/公开 API 就走 API------采集与对接业务接口是同一套 HTTP 肌肉(Day33/34)。

对比已学:

Day37 静态 HTML 本课
选择器抽文本 JSON 键取值
怕改版 class 怕接口鉴权与限流
BeautifulSoup requests + r.json()
本地 sample 可控 真实 API 有限额与字段变更

2. 为什么会有「空壳页」?

先用一张浏览器时序图建立直觉:先拿到壳 HTML,再请求 /api/items,JS 再渲染。你以为数据在 HTML,实际在第二次请求。

想通这一点,后面「打开 Network」才有动力。只 requests 页面 URL 可能一无所获;改请求 API 才能拿到数组字段。

典型前端流程:

text 复制代码
浏览器
  |-- GET /page        -->  得到壳 HTML(转圈、空列表)
  |-- GET /api/items   -->  得到 JSON 数据
  |-- JS 把 JSON 填进 DOM --> 你才「看见」列表
你以为 实际
数据在 HTML 里 数据在第二次请求里
该加强选择器 该打开 Network 找 API

修改前(只 requests 页面 URL): 可能只有 loading 结构。

修改后(请求 /api/items): 直接拿到数组字段。


3. 本质、约束与坑

动态页本质是壳加数据请求;数据请求往往就是普通 HTTP API。接口优先三步:Network、筛 XHR、用客户端复现。

同时摊开约束:鉴权、限流、合规、字段变更;以及一上来就 Selenium、漏 Header、死磕选择器等坑。技术选择之前,先把边界立住。

本质: 动态页 =「壳 HTML」+「数据请求」。数据请求往往就是普通 HTTP API。

接口优先三步:

  1. 开发者工具 → Network
  2. 筛选 Fetch/XHR,找响应为 JSON 的请求
  3. 复制 URL / 方法 / 必要 Header,改写成 requests / httpx

HTML 方式: 下大页 + 易碎 CSS。

API 方式: 字段如 full_namestargazers_count 直接可用。

约束:

  1. 有的接口要登录 Cookie / Token。
  2. 有频率限制(如 GitHub 匿名限额)。
  3. 未授权乱抓可能违法违规------本课只用公开 API 演示。
  4. 字段名可能变更,要写容错(.get)。

常见坑:

说明
一上来就上 Selenium 成本高,维护难
忽略 Request Headers 缺 UA/Token 会 401/403
把 HTML 解析失败全怪选择器 可能根本不该解析 HTML
把浏览器里的「查询参数」抄错 漏参数导致空数据
无 timeout 程序挂死(Day34 教训)

4. 能力分组

把本课能力拆成发现、复现、抽取、存储、自动化扫盲五类,对应工具从 DevTools 到 requests 再到 sqlite。

分组是为了学习路径清晰:你不是在学「又一个库」,而是在学一条从浏览器到入库的工作流。

类别 做什么 工具
发现 Network 里找 JSON 请求 浏览器 DevTools
复现 带齐必要头发请求 requests / httpx
抽取 data["key"] / 多层 dict Python
存储 入库 sqlite3(Day39)
自动化扫盲 知步骤与成本 Playwright/Selenium 概念

5. Network 面板怎么看(操作说明)

即使本课演示直接给了公开 API,你也必须会自己在浏览器里找接口------这是工作中的核心技能。

按步骤走:F12、筛 Fetch/XHR、刷新或点加载更多、看 Headers 与 Preview。像侦探一样:页面是海报,出货单在 API。

即使本课实践直接给公开 API,你也要会自己找:

步骤 动作
1 F12 → Network
2 勾选 Fetch/XHR(或 All 里找 type=json)
3 刷新页面或点一下「加载更多」
4 点开请求 → Headers 看 URL/方法
5 Preview/Response 看是否为 JSON 列表
6 若需要,看 Request Headers 里的 Authorization

像侦探: 页面只是海报,真正的货在仓库出货单(API)上。


6. JSON 抽取小步

找到 JSON 后,取值比 HTML 简单得多:dict 的键。但要用 get 做容错,避免 KeyError。

这一节用最小 dict 例子练 full_name、嵌套 slideshow,为后面 GitHub 实战预热。

python 复制代码
data = {
    "name": "cpython",
    "full_name": "python/cpython",
    "stargazers_count": 1,
}
print(data.get("full_name"))
print(data.get("stargazers_count"))
print(data.get("not_exist"))  # None,不抛错

预期输出:

text 复制代码
python/cpython
1
None

多层时:

python 复制代码
slideshow = data.get("slideshow") or {}
title = slideshow.get("title")

7. 实践:公开 JSON API(主菜)

用 GitHub 公开仓库接口跑通「不打开浏览器也能拿元数据」。带 UA、timeout、raise_for_status,打印字段。

star 数会变,正常。重点是链路跑通,并理解 print 不会改远端数据。自动化示意只打印 JSON 说明,不要求装驱动。

GitHub 公开仓库接口(无需浏览器):

bash 复制代码
mkdir -p ~/python-lab/src/day38
cd ~/python-lab/src/day38
pip install requests

Windows 推荐 Cygwin 或 WSL。

bash 复制代码
cat > api_first_demo.py << 'EOF'
# Day38: API-first over scraping HTML
import json

import requests


def main():
    url = "https://api.github.com/repos/python/cpython"
    print("--- fetch json api ---")
    r = requests.get(
        url,
        timeout=20,
        headers={"User-Agent": "python-lab-day38/1.0", "Accept": "application/json"},
    )
    r.raise_for_status()
    data = r.json()
    print("name:", data.get("name"))
    print("full_name:", data.get("full_name"))
    print("stargazers_count:", data.get("stargazers_count"))
    print("language:", data.get("language"))
    print("html_url:", data.get("html_url"))

    print("--- compare ---")
    print("HTML way: download big page + CSS selectors, brittle when layout changes")
    print("API way: stable fields in JSON, fewer surprises, easier to store")

    print("--- automation sketch (not required this lesson) ---")
    sketch = {
        "tool": "playwright or selenium",
        "steps": ["launch browser", "goto url", "wait selector", "text_content"],
        "cost": "slow, fragile, heavy",
        "prefer": "official API / XHR JSON first",
    }
    print(json.dumps(sketch, ensure_ascii=False))


if __name__ == "__main__":
    main()
EOF

python3 api_first_demo.py

实测输出(star 数会变):

text 复制代码
--- fetch json api ---
name: cpython
full_name: python/cpython
stargazers_count: 73867
language: Python
html_url: https://github.com/python/cpython
--- compare ---
HTML way: download big page + CSS selectors, brittle when layout changes
API way: stable fields in JSON, fewer surprises, easier to store
--- automation sketch (not required this lesson) ---
{"tool": "playwright or selenium", "steps": ["launch browser", "goto url", "wait selector", "text_content"], "cost": "slow, fragile, heavy", "prefer": "official API / XHR JSON first"}

调用前: 只有 URL。

调用后: 本地 dict 持有仓库元数据;GitHub 上的 star 不会 因你 print 而改变。

7.1 为什么要带 User-Agent?

部分服务对默认/空 UA 不友好;教学与对接时写明自己的客户端名,便于对方识别与排错。

7.2 raise_for_status 在这里的意义
状态 不 raise 的风险
404 把错误页当 JSON 解析
403 误以为字段缺失
5xx 用脏数据入库

8. HTML 方式 vs API 方式(对照加深)

同一目标「拿 cpython 的 star」,对比爬主页 HTML 与打 REST API 的步骤与成本。

结论几乎总是:有 API 走 API。HTML 是退路,不是默认首选。

假设目标:拿 python/cpython 的 star 数。

步骤 HTML 思路 API 思路
1 GET 仓库主页 HTML GET /repos/python/cpython
2 找显示 star 的 span data["stargazers_count"]
3 class 一变就挂 字段相对稳定(仍可能变)
4 体积大 JSON 小

结论: 同目标时 API 几乎总是更优;HTML 是没有接口时的退路。


9. 自动化半页扫盲(非本课必装驱动)

当确认没有接口、又必须浏览器事件时,才出现 Playwright/Selenium。这里只讲步骤与成本。

本课验收不要求安装浏览器驱动。避免一遇到动态站就条件反射上自动化。

确实没有可用接口、又必须依赖浏览器事件时:

工具 角色
Playwright 现代、自动等元素较方便
Selenium 历史长、资料多

概念步骤:

text 复制代码
启动浏览器 → 打开 URL → 等待选择器出现 → 取文本/点击 → 关闭
python 复制代码
# 伪代码 / 示意,不是本课必跑
# from playwright.sync_api import sync_playwright
# with sync_playwright() as p:
#     browser = p.chromium.launch()
#     page = browser.new_page()
#     page.goto("https://example.com")
#     print(page.locator("h1").inner_text())
#     browser.close()
成本 说明
真渲染页面
要浏览器内核
UI 文案/结构一变就挂
难部署 CI/服务器环境更麻烦

本课验收:会跑 API 脚本即可,不要求安装 Playwright/Selenium。


10. 伦理与法律(必读)

技术能做不等于允许做。合规、授权、限流、禁止撞库与未授权攻击------和数据课安全篇同一精神。

公开 API 也有配额与条款。红线举例帮助建立敬畏,而不是吓退学习。

  • 遵守服务条款与 robots;有授权再抓
  • 控制频率;不撞库、不做验证码黑产链路
  • 禁止未授权攻击与隐私窃取
  • 教学与内部系统优先官方 API
  • 公开 API 也要遵守 rate limit 与署名要求

红线举例: 绕过付费墙批量扒取、打码平台破解登录、扫未授权内网接口。


11. 常见问答

Cookie、大 JSON、和 Scrapy 关系、star 数变化如何断言------集中答疑。

减少「我是不是该上框架/自动化」的焦虑,回到接口优先。

Q:接口要 Cookie 怎么办?

A:先确认是否允许;用官方 OAuth/Token;不要随手导出别人的登录 Cookie 滥用。

Q:JSON 很大怎么办?

A:只取需要字段;分页参数;流式/分批入库(进阶)。

Q:和「爬虫框架 Scrapy」关系?

A:框架帮你管调度与管道;本课先掌握「接口优先」的判断力。

Q:star 数每次不一样?

A:正常,真实数据在变;断言应用「有该字段且为 int」而不是写死数字。


12. 落地场景

同步仓库元数据、内部 list 接口、老站无接口、登录点选报表------分别优先什么策略。

场景是为了让你出门后会选型,而不是只会跑本课 demo。

场景 优先策略
同步 GitHub 仓库元数据 REST API
内部后台表格(有 list 接口) 复现 XHR
纯展示、无接口的老站 静态 HTML 或自动化(评估成本)
需要登录点选的报表 自动化或 RPA(合规前提下)

13. 请求头最小集合(复现 XHR 时)

从 DevTools 复现请求时,容易把浏览器几十个头全抄上。这一节强调最小必要集合。

只加需要的 UA、Accept、Authorization 等,保持请求干净可维护。

Header 何时需要
User-Agent 经常需要
Accept: application/json 明确要 JSON
Authorization 私有接口
Cookie 仅限授权场景,慎用
Referer / 自定义头 少数站校验

原则: 只加必要头;从 DevTools 对照,而不是一次复制全部乱七八糟的浏览器头。


14. 状态码决策表(接 Day33/34)

接口优先仍是 HTTP:200 解析,401 查鉴权,429 降速,不要用 Selenium 硬闯权限。

把状态码从「背数字」变成「下一步动作」,和 Day34 稳健客户端衔接。

接口优先场景下的动作
200 解析 JSON、取字段
401/403 检查 Token/权限,不要改用 Selenium「硬闯」
404 URL 抄错或资源不存在
429 降速、退避重试
5xx 有限重试,仍失败则报警

15. 「什么时候才上自动化」检查单

用检查单克制自动化冲动:无接口、有授权、真依赖浏览器、能接受慢脆。

不满足就回去找 API 或静态 HTML。

同时满足再考虑:

  • 已确认没有可用 JSON/XML 接口
  • 有合规授权
  • 交互确实依赖浏览器事件(复杂点击/验证码合规方案另议)
  • 能接受慢与脆,并有维护预算

否则:继续接口或静态 HTML。


16. 字段容错模板

真实 JSON 可能缺字段或类型不对。给一个 pick_repo 式模板,避免流水线轻易崩溃。

修改前硬下标会炸,修改后可降级并继续------第 39 课 store 前很需要这习惯。

python 复制代码
def pick_repo(data: dict) -> tuple[str, int]:
    name = data.get("full_name") or data.get("name") or ""
    stars = data.get("stargazers_count")
    try:
        stars_i = int(stars)
    except (TypeError, ValueError):
        stars_i = 0
    return name, stars_i

修改前: data["stargazers_count"] 缺失直接炸。

修改后: 降级为 0,流水线可记录问题行。


17. 自我检查清单

打勾:空壳页、三步走、requests 拉 JSON、自动化非必须、合规。

过关即可进入流水线项目课。

  • 能说明空壳页与 XHR 的关系
  • 会描述接口优先三步
  • 会用 requests 拉公开 JSON 并打印字段
  • 知道自动化成本与非必选项
  • 知道合规红线

18. 从浏览器复制为 cURL 再翻译(思路)

工作中常用 Copy as cURL,再翻译成 requests。比猜选择器快。

步骤:复制、识别方法 URL 头体、改写、删多余头。这是接口优先的实操路径。

许多浏览器支持:请求右键 → Copy as cURL。

步骤 说明
1 复制 cURL
2 识别 -X 方法、URL、-H 头、--data
3 改写成 requests.get/post(..., headers=..., json=...)
4 删掉明显无用的浏览器私有头,保留鉴权相关

这是工作中「接口优先」的常用路径,比猜选择器快。


19. 与第 37 / 39 课的分工

用流程图总结:能 API 吗→38/39;HTML 有数据吗→37;否则才评估自动化。

三课分工清晰,避免工具混用时脑子乱。

数据形态 你的动作
37 静态 HTML 选择器解析
38 JSON API / XHR 本课:发现并请求
39 多源 API 流水线入库验收
text 复制代码
能 API 吗? --是--> 38/39
    |
   否
    v
HTML 里有数据吗? --是--> 37
    |
   否
    v
才评估自动化(半页认知)

20. 术语表(本课)

XHR、空壳页、接口优先、自动化、限流------一页小抄。

盖住解释自述一遍,查漏补缺。

术语 含义
XHR / Fetch 浏览器异步拉数据的请求
空壳页 首屏 HTML 几乎无业务数据
接口优先 先找 JSON/API 再考虑解析页面
自动化 用驱动操控真浏览器
限流 429 或配额,需降速

21. 课堂 10 分钟小练习(可不联网)

不联网也能练:给定假 JSON,打印 title,并回答还要不要渲染 HTML。

用来巩固「数据已在 JSON 里」的直觉。

给定假响应:

python 复制代码
payload = {
    "items": [
        {"id": 1, "title": "A"},
        {"id": 2, "title": "B"},
    ]
}

请写出:打印所有 title 的循环;并说明若这是 XHR 结果,你还需要浏览器渲染吗?

参考:

python 复制代码
for it in payload["items"]:
    print(it["title"])
# 不需要再渲染 HTML,数据已在 JSON 中

22. 再对比一次「错误路径」

三种路径对照:只存空壳 HTML、Selenium 点详情、一次 API 拉全量。

把「快、稳、合法」设为默认优化目标,结束本课技术讨论。

错误路径 结果
只保存整页 HTML 到文件,从不看 Network 可能存了一堆空壳
上 Selenium 点开每个详情 极慢,维护成本高
找到 /api/list 一次拉全量 快,字段清晰

把「快、稳、合法」当作默认优化目标。


总结

动态页优先 JSON 接口;自动化补充认知;与 37 互补;合规底线。

下一课把多源 API 拉通成可验收的入库流水线。

  • 动态页优先挖 JSON 接口,再用 Day34 肌肉请求。
  • 自动化只作补充认知;本课以 API 实践过关。
  • 与第 37 课互补:有 HTML 用解析,有接口用接口。
  • 合规与限流是底线;密钥不进仓库。

小练笔

自测题含概念与可选换仓库实践。先做后对。

可选实践请真实请求并观察字段。

题 1

Network 面板应优先看哪类请求找数据接口?

题 2

判断:所有动态站都必须上 Selenium 才能拿数据。

题 3

自动化主要缺点各举一个。

题 4

接口优先三步是什么?

题 5

判断:本课实践会修改 cpython 仓库在 GitHub 上的 star 数。

题 6

为什么空壳页会导致 BeautifulSoup「选不中」?

题 7

data.get("x")data["x"] 在字段缺失时更安全的点是?

题 8

判断:只要网站能在浏览器打开,就可以无限制地高频抓取。

题 9(可选实践)

把 URL 换成 https://api.github.com/repos/psf/requests,打印 full_namestargazers_count

题 10

列出两种「不该用自动化」的情况。


小练笔参考答案

先独立完成。意思对即可。

与接口优先、合规冲突的理解需修正。

题 1

Fetch/XHR(或返回 JSON 的请求)。

题 2

题 3

慢、脆、资源占用高(合理即可)。

题 4

Network → 筛 XHR/JSON → 用客户端复现。

题 5

(只读公开 API)。

题 6

数据不在首屏 HTML 里,而在后续接口响应中。

题 7

缺失时返回 None 而不是 KeyError。(合理即可)

题 8

题 9

以你运行输出为准。

题 10

已有稳定官方 API;无授权/违反条款时。(合理即可)

相关推荐
卷无止境1 小时前
模块与包:Python 代码组织的两层逻辑
后端·python
夏日清风有你2 小时前
OpenDataLab 数据集下载
python
黑客-秋凌2 小时前
使用Python+selenium实现第一个自动化测试脚本
开发语言·自动化测试·软件测试·python·selenium·测试工具
geovindu2 小时前
CSharp: Iterative Algorithms
开发语言·后端·算法·c#·.net·迭代算法
一只月月鸟呀2 小时前
移动端tap与click的区别 && 点透事件
开发语言·前端·javascript
雨落在了我的手上2 小时前
Java数据结构(六):链表的介绍
java·开发语言·数据结构
影寂ldy2 小时前
C# HttpClient 分片下载、断点续传、暂停取消(完整项目知识点)
开发语言·c#
独隅2 小时前
DevEco Code Plan+Build 双 Agent 协同开发效率实测
java·开发语言
DogDaoDao3 小时前
【GitHub】WorldMonitor:一个工程极致主义的实时全球情报仪表盘深度解析
python·程序员·架构·github·go语言·worldmonitor·实时全球情报