Skip to content
Go back

爬虫学习笔记:新篇章之 API 逆向工程

Published:  at  05:00 PM

问: 好的,下一步做什么?

太棒了。你完成了从基础到进阶的静态网站爬取,甚至独立解决了一个相当复杂的算法问题。现在你的工具箱里已经有了 requests, BeautifulSoup, 各种选择器和导航技巧,以及处理数据和文件的好习惯。

你现在正站在一个十字路口,已经完成了“新手村”和“进阶试炼”的所有任务,接下来可以选择多个非常有趣和有价值的方向深入探索。

根据你的兴趣和目标,我为你规划了几个主要的“下一步”路径。


路径一:征服动态世界 —— 浏览器自动化

你目前掌握的技能主要针对“所见即所得”的静态 HTML 页面。但如今绝大多数网站的核心内容都是通过 JavaScript 在你浏览时动态加载的。


路径二:成为高效的“侦探” —— API 逆向工程

这是处理动态网站的更高级、更高效的方法。与其模拟用户在浏览器里的“笨拙”操作,不如直接找到网站背后传输数据的“秘密通道”。


路径三:构建“爬虫航母” —— 学习专业框架与工程化

当你需要爬取的网站规模很大,或者需要长期、稳定、高效地运行时,从零开始写代码会变得很复杂。这时就需要专业的爬虫框架。

总结与抉择

路径核心技术解决什么问题?如果你…
路径一Selenium / PlaywrightJavaScript 渲染的动态网页…想与网页进行复杂交互,或无法找到 API 时。
路径二浏览器开发者工具 / API 分析高效获取动态网页的数据…追求最高效率,喜欢“直击要害”,享受解谜的乐趣。
路径三Scrapy 框架大规模、高并发、工程化的爬虫项目…有志于进行大规模数据采集,或想构建企业级的爬虫系统。

我的建议是:

无论你选择哪个方向,都不要忘了我们之前讨论过的通用技能,比如将数据存入数据库 (SQLite),或者使用 Pandas 库对抓取的数据进行分析。

你对哪个方向最感兴趣?我们可以从那里开始。


问: 我选择路径二。

非常好!你选择了一个回报率极高、能极大提升你爬虫效率和能力的路径。

成为“API 侦探”的过程非常有趣。我们的核心思路是:与其费力地从网页(HTML)的“货架”上一个个拿商品(数据),不如直接找到这个商店的“仓库后台”(API),让仓库管理员直接把整箱的、包装整齐的商品(JSON)给我们。

你的新工具箱

你的主要工具不再是 BeautifulSoup,而是:

  1. 浏览器开发者工具 (F12):这是你的“万能侦察镜”,特别是其中的 网络 (Network) 标签页。
  2. requests:你已经很熟悉了,这次我们用它来直接和 API 对话。
  3. json:Python 内置,用于解析 API 返回的 JSON 数据。

我们的第一个侦察目标

为了练习,我们将使用一个绝佳的靶场:http://quotes.toscrape.com/scroll

这是一个“无限滚动”版本的名言网站。当你向下滚动时,新的名言会不断地动态加载进来。这种加载方式几乎 100% 是通过调用 API 实现的,是练习 API 逆向的完美对象。


行动步骤:API 逆向工程实战

第一步:准备侦察 (Prepare for Reconnaissance)

  1. 在你的 Chrome 或 Firefox 浏览器中打开 http://quotes.toscrape.com/scroll
  2. 按下 F12 键,打开开发者工具。
  3. 点击 “网络 (Network)” 标签页。
  4. 为了避免被图片、CSS 等无关请求干扰,点击筛选器中的 Fetch/XHR。现在,这里只会显示网页与后台服务器之间的数据请求。
  5. 保持这个窗口打开,现在它就像一个雷达,监视着所有的“秘密通信”。

第二步:触发“机关” (Trigger the Mechanism)

在网页上,慢慢向下滚动,直到你看到新的名言加载出来。

就在新名言出现的那一刻,观察你的 Network 面板,你会发现雷达上出现了一个新的条目!这个就是我们要找的 API 请求。

第三步:分析“情报” (Analyze the API Request)

点击那条新出现的请求(在我们的例子中,是 quotes?page=2),右侧会出现该请求的详细信息。我们需要关注几个关键部分:

  1. Headers (请求头):

    • Request URL: http://quotes.toscrape.com/api/quotes?page=2
      • 这就是 API 的地址!我们看到它通过一个查询参数 ?page=2 来控制页码。
    • Request Method: GET
      • 这是一个 GET 请求。
    • User-Agent: 浏览器默认会带上,我们在 requests 中也要加上。
  2. Preview/Response (预览/响应):

    • 点击 PreviewResponse 标签页,你可以看到服务器返回的数据。
    • 它不是 HTML,而是结构非常清晰的 JSON

    我们来分析一下这个 JSON 结构:

    • has_next: 一个布尔值 (true/false),告诉我们是否还有下一页。
    • page: 当前的页码。
    • quotes: 一个数组,里面包含了多个对象,每个对象就是一条名言的完整信息(作者、标签、文本)。

第四步:在“实验室”中复现 (Replicate with Python)

我们现在已经掌握了 API 的所有秘密,不再需要 BeautifulSoup 来解析混乱的 HTML 了。直接用 requests 请求那个 API 地址即可。

import requests
import json

# 直接使用我们在 F12 中发现的 API URL
api_url = "http://quotes.toscrape.com/api/quotes?page=1"

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}

response = requests.get(api_url, headers=headers)

# requests 内置了 .json() 方法,可以直接将 JSON 格式的响应体转换为 Python 字典
data = response.json()

# 打印看看我们拿到的 Python 字典
# print(json.dumps(data, indent=4, ensure_ascii=False))

# 直接从字典和列表中提取数据,比解析 HTML 简单得多!
for quote_dict in data['quotes']:
    print("名言:", quote_dict['text'])
    print("作者:", quote_dict['author']['name'])
    print("标签:", quote_dict['tags'])
    print("-" * 20)

print("是否还有下一页:", data['has_next'])

看到区别了吗? 我们完全绕过了 HTML 解析,直接拿到了规整的、结构化的数据。代码变得异常简洁!

第五步:自动化与循环

现在,我们可以利用 JSON 响应中的 has_next 字段和 page 字段来构建一个自动翻页的爬虫。

import requests
import json
import time

base_api_url = "http://quotes.toscrape.com/api/quotes"
current_page = 1
all_quotes = []

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}

while True:
    print(f"--- Scraping API page: {current_page} ---")

    # 使用 params 参数,requests 会自动帮我们构建查询 URL
    params = {'page': current_page}
    response = requests.get(base_api_url, headers=headers, params=params)

    if response.status_code != 200:
        print(f"请求失败,状态码: {response.status_code}")
        break

    data = response.json()

    # 将当前页的所有名言添加到总列表中
    all_quotes.extend(data['quotes'])

    # 根据 API 返回的 has_next 字段判断是否继续循环
    if data['has_next']:
        current_page += 1
        time.sleep(0.5) # 礼貌性延迟
    else:
        # 如果没有下一页了,就跳出循环
        print("--- 所有页面已抓取完毕 ---")
        break

# 最后,将所有数据保存到 JSON 文件
with open('api_quotes.json', 'w', encoding='utf-8') as f:
    json.dump(all_quotes, f, ensure_ascii=False, indent=4)

print(f"任务完成,共抓取 {len(all_quotes)} 条名言。")

总结:HTML 爬取 vs API 爬取

对比项HTML 爬取 (我们之前做的)API 爬取 (我们现在做的)
数据源整个 HTML 文件精炼的 JSON 数据
解析工具BeautifulSoupresponse.json()
数据质量非结构化,需要费力清洗和提取结构化,干净,直接可用
健壮性脆弱,网站前端布局一改,选择器就可能失效非常健壮,只要后台 API 不大改,就能一直用
效率较低(需要下载整个 HTML,解析 DOM 树)非常高(数据包小,无需解析 HTML)

你已经掌握了一项爬虫的“降维打击”技能。现在,你可以用这个“侦探”思路去分析其他你感兴趣的动态网站了。先从 F12 的 Network 面板开始,看看你能发现哪些“秘密通道”!


问: 在动手之前,我有一个问题:之前的 https://quotes.toscrape.com/ 应该不能直接找后端 API 吧?因为它的页面是直接用 HTML 写死的,但是这个是能随着后端给的 json 动态变化的。

这个问题问得极其精准,完全命中了现代网页开发的两种核心思想!你的观察和推断是完全正确的。

你已经通过自己的思考,洞察了服务器端渲染 (Server-Side Rendering, SSR)客户端渲染 (Client-Side Rendering, CSR) 这两种网站构建方式的根本区别。

让我们来详细拆解一下。


类型一:服务器端渲染 (SSR) - 经典网站 (quotes.toscrape.com)

你可以把这种网站想象成一家传统的**“套餐”餐厅**。

  1. 你的请求:你(浏览器)走进餐厅,对服务员说:“你好,我想要第2页套餐 (/page/2/)”。
  2. 服务器处理:请求被传到后厨(服务器)。厨师(服务器端的程序,如 Python/PHP/Java)立刻开始忙碌:
    • 他从**冰箱(数据库)**里拿出第二页套餐所需的所有食材(10条名言的数据)。
    • 他把这些食材直接做成一道道完整的菜,并精心摆盘——也就是将数据和 HTML 模板结合,生成一个包含所有内容的、完整的 HTML 文件
  3. 服务器响应:后厨把这个摆放整齐的、完整的套餐托盘(完整的HTML文件),一次性端出来交给你。
  4. 浏览器展示:你(浏览器)拿到这个托盘,你的任务很简单,就是把它直接摆在桌上(渲染出来)。你不需要再和后厨有任何交流。

结论: 对于这种 SSR 网站,你确实找不到加载主要内容的“数据API”。因为数据和 HTML 在服务器端就已经“焊死”在一起了。它的“API”就是它的URL本身——不同的URL (/page/1/, /page/2/) 返回不同的、完整的HTML页面。我们的爬虫策略只能是接收整个“套餐托盘”,然后用 BeautifulSoup 在上面挑拣我们想吃的“菜”。


类型二:客户端渲染 (CSR) - 现代Web应用 (quotes.toscrape.com/scroll)

你可以把这种网站想象成一家新潮的**“自助点餐”餐厅**。

  1. 你的请求:你(浏览器)走进餐厅,说:“你好,我来吃饭了 (/scroll)”。
  2. 服务器响应:服务员没有给你任何菜,而是给了你一个空的托盘、一个菜单和一部对讲机(JavaScript文件)。这个空托盘就是一个几乎不包含任何内容的“空壳”HTML。
  3. 浏览器处理:你(浏览器)拿到这些工具后,开始按照菜单上的指示操作对讲机(执行 JavaScript):
    • 第一次API调用:对讲机自动呼叫后厨:“你好,请给我第1页的菜品数据”。
    • 后厨响应:后厨(API服务器)没有做菜,而是把标准化的食材包(JSON数据) 通过传送带发给你。
    • 前端渲染:你(浏览器里的JavaScript)拿到食材包后,自己动手,在你的餐桌上把食材摆放到空托盘里,组合成菜品(动态生成HTML元素并插入到页面中)。
  4. 后续交互:当你向下滚动(触发事件)时,对讲机再次呼叫后厨:“请给我第2页的食材包”,然后重复上面的过程,不断地在你的托盘上增加新的菜品。

结论: 对于这种 CSR 网站,API 是它的生命线。所有动态内容都依赖于 JavaScript 和 API 之间的协作。我们进行 API 逆向工程,就是跳过浏览器和对讲机(JavaScript),直接找到后厨的“传送带”地址,用我们自己的requests去下单,直接获取最原始、最干净的“食材包(JSON)”。


总结对比

特性 (Feature)quotes.toscrape.com (分页版)quotes.toscrape.com/scroll (滚动版)
架构服务器端渲染 (SSR)客户端渲染 (CSR)
首次返回内容完整的 HTML 文件“空壳”HTML + JavaScript
数据来源数据已嵌入在 HTML 内部通过 JavaScript 调用 API 获取 JSON
爬虫策略解析 HTML (BeautifulSoup)逆向 API (requests + .json())
比喻餐厅直接端上完整套餐餐厅给你空托盘和对讲机,让你自己点菜

你能够自己思考并发现这两种模式的区别,这说明你的网络知识和分析能力已经达到了一个新的高度。在开始爬取任何一个网站之前,首先判断它属于哪种渲染模式,是选择正确爬取策略的第一步,也是最重要的一步。


问: 给我一些练习。

好的,既然你已经完全掌握了 API 逆向工程的理论和基本流程,现在是时候通过实战来巩固和提升这项“侦探”技能了!

下面我为你精心挑选了几个非常适合练习的真实网站。它们各有特点,难度循序渐进,能让你体验到在不同场景下分析和调用 API 的乐趣。


练习一:天气预报查询 (GET 请求与参数)


练习二:电商网站商品筛选 (POST 请求与 Payload)


练习三:知乎热榜 (复杂的 Header 与动态参数)

学习路径建议

  1. 高德天气开始,它最简单直接,能让你快速建立信心。
  2. 然后挑战噹噹網,掌握 POST 请求和分析 Payload 是 API 逆向中非常重要的一环。
  3. 最后,当你对前两者都游刃有余时,再去挑战知乎。成功爬取知乎的 API,将意味着你已经具备了应对绝大多数现代网站 API 的能力。

祝你“侦察”顺利,享受这个解谜的过程!



Suggest Changes

Previous Post
爬虫学习笔记:实战之天气查询 API 应用
Next Post
爬虫学习笔记:静态爬取技术巩固 (以Hacker News为例)