视频加载失败

Python 爬虫接口实战:翻页取完再累加(CH-002)

1089 字
5 分钟
Python 爬虫接口实战:翻页取完再累加(CH-002)

本文是 LearnSpider 第 2 关的解密教程。这一关的数据不在 HTML 里,只能从分页接口拿;答案是全部电影「评分总人数」的累加值。重点是:怎么找到接口、怎么确认它没把总量直接给你、以及怎么把 21 页稳稳翻完。

现象:源码里没有数据了#

打开 /movies?challenge=CH-002,电影卡片正常显示。但「查看源代码」里搜不到任何一个电影名 —— 页面是 Vue 渲染的,数据只能来自 XHR。

F12 → Network → Fetch/XHR,刷新页面,会看到一个请求:

GET /api/movies?page=1&page_size=12

响应长这样(字段是精简过的):

{
"items": [
{
"title": "肖申克的救赎",
"rating": 9.7,
"rating_text": "9.7",
"rating_count_text": "3235402人评价",
"rating_count": 3235402
}
],
"page": 1,
"page_size": 12,
"total_movies": 249
}

接口故意不给你的东西#

/api/movies 不会下发整批统计字段:

字段状态
total_rating_score(评分总和)被剥掉了
total_rating_count(评价人数总和)被剥掉了 ← 正是答案
top_movie(评分最高那部)被剥掉了
total_movies(共多少部)✅ 有,用来算要翻几页

所以「直接读一个字段就交卷」这条路被堵死了,必须一页一页取回来自己累加。

顺带说一句:page_size 上限是 100。想「一次要 1000 条」也会被服务端截回 100。

数据规模#

  • 共 249 部电影,每页 12 条 → 21 页(最后一页可能不满)。
  • 判断翻页结束的两种写法:page * page_size >= total_movies,或者某一页返回的 items 为空。

完整脚本#

"""CH-002:答案 = 全部电影「评分总人数」之和"""
import re
import time
import requests
BASE = "https://spider.jsnote.top"
API_URL = f"{BASE}/api/movies"
PAGE_SIZE = 12
session = requests.Session()
session.headers.update({
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Referer": f"{BASE}/movies?challenge=CH-002",
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36"
),
})
# 数据是按账号派生的,所以要带登录态:
# 浏览器登录后 F12 -> Application -> Cookies -> 复制 session 的值
session.cookies.set("session", "<把浏览器里的 session cookie 粘到这里>",
domain="spider.jsnote.top")
def rating_count(movie):
"""优先用字段,字段缺失/为 0 时回头从 '3235402人评价' 里抠数字。"""
count = movie.get("rating_count") or 0
if count:
return int(count)
match = re.search(r"([\d,]+)\s*人评价", movie.get("rating_count_text", ""))
return int(match.group(1).replace(",", "")) if match else 0
def main():
page = 1
total_movies = None
total_count = 0
movies = 0
while True:
response = session.get(
API_URL, params={"page": page, "page_size": PAGE_SIZE}, timeout=10
)
response.raise_for_status()
payload = response.json()
items = payload.get("items", [])
if not items:
break
total_movies = payload.get("total_movies", total_movies)
for movie in items:
total_count += rating_count(movie)
movies += 1
print(f"第 {page:>2} 页:{len(items)} 条,累计 {movies} 条,"
f"评价人数小计 {total_count}")
if total_movies and movies >= total_movies:
break
page += 1
time.sleep(0.5) # 别把靶场当压力测试
print(f"\n共 {movies} 部电影,评价人数总和:{total_count}")
if __name__ == "__main__":
main()

把最后的数字提交到 CH-002 答题框即可。

排查清单#

  1. 源码里搜不到数据 → 打开 Network 的 Fetch/XHR,找首屏那个请求。
  2. 右键 → Copy as cURL,先在终端跑通一次,确认只差 Cookie。
  3. 看响应里有没有现成的总量字段;有就省事,没有就老老实实翻页。
  4. 翻页前先拿 total_movies 和 page_size 算出总页数,别写成死循环。
  5. 每页间隔 0.5s 以上。
  6. 解析用字段优先、文本兜底(rating_count 拿不到就正则 ([\d,]+)人评价)。
  7. 累加前把一千分隔符去掉("1,234" → 1234)。
  8. 结束条件写成「取到的条数 ≥ 总数」或「这一页为空」,不要写「拿到 21 页」。

常见问题#

为什么我直接写 page_size=1000 也只能拿到 100 条?#

服务端有上限(min(100, max(1, page_size))),超了就按 100 处理。这是接口很常见的保护写法。

数据为什么每个人不一样?#

电影数据是共用的一份,但很多关卡的数据是按账号派生的(这道题的答案会不会变,取决于靶场实现)。所以别抄别人的答案,自己跑一遍。

需要登录吗?#

/api/movies 本身公开可读;提交答案必须登录。

只抓到 20 页就停了?#

说明结束条件写得不对:最后一页可能只有 9 条(不满 12 条),这时要停,但前面 20 页都是满的。用「累计条数 ≥ total_movies」判断最稳。

最后提醒#

翻页是很典型的「礼貌爬取」场景:按页取、留间隔、别并发轰炸。真实站点上,疯狂翻页最容易触发限流甚至封号。

去挑战广场提交,然后进 CH-003:数据不再是文本,而是一个你猜不到路径的文件。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Python 爬虫接口实战:翻页取完再累加(CH-002)
https://jsnote.top/posts/ls-ch2/
作者
xiajiao
发布于
2026-10-02
许可协议
CC BY-NC-SA 4.0
相关文章智能推荐
1
Python 爬虫入门实战:服务端渲染页面怎么取数(CH-001)
爬虫靶场本文是 LearnSpider 第 1 关的解密教程。它练的不是「怎么破加密」,而是先判断数据到底在哪:这一关的数据只在服务端渲染出来的 HTML 里,源码里没有接口。答案是第一页 HTML 源码的字符数。
2
Python 爬虫接口签名实战:参数签名 + 会话绑定(CH-005)
爬虫靶场本文是 LearnSpider 第 5 关的解密教程。这一关的接口参数要签名,而且取数只认一个「会话标识」(uuid)—— 这个 uuid 是页面自己生成的、并且已经在后端和你的账号绑定过。答案是 5 页共 50 个数字的总和。
3
Python 爬虫验证码实战:AES 加密报文 + 每页算术验证码(CH-009)
爬虫靶场本文是 LearnSpider 第 9 关的解密教程。这一关把政务站点常见的一套反爬凑齐了:请求/响应都是 AES-ECB 加密的 hex,还要带一个前端写死的 Adam-AppKey,而且每翻一页都得先过一道算术验证码。目标是取 10 页…
4
Python 爬虫字体映射实战:HTML 里一个字都没有(CH-007)
爬虫靶场本文是 LearnSpider 第 7 关的解密教程。这一关把大众点评那套「字体库 + 坐标」搬了过来:页面 HTML 里只有随机类名,文字全在字体库(SVG 文字地图)里,而「每个类名要把图挪多少像素」是接口加密下发的。目标是拿到 5 段…
5
Python 爬虫实战:随机下发路径的资源怎么下载(CH-003)
爬虫靶场本文是 LearnSpider 第 3 关的解密教程。这一关要把图片下载下来,答案是这张图片的字节数。真正的考点是:拿到接口给的 image_id / image_url 之后,别把「字节」和「字符」搞混,也别拖太久(图片是随机下发的)。
随机文章随机推荐

评论区

Profile Image of the Author
xiajiao
写爬虫,也写防爬虫的靶场。
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
站点统计
文章
15
分类
1
标签
33
总字数
22,317
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录