视频加载失败

Python 爬虫入门实战:服务端渲染页面怎么取数(CH-001)

1079 字
5 分钟
Python 爬虫入门实战:服务端渲染页面怎么取数(CH-001)

本文是 LearnSpider 第 1 关的解密教程。它练的不是「怎么破加密」,而是先判断数据到底在哪:这一关的数据只在服务端渲染出来的 HTML 里,源码里没有接口。答案是第一页 HTML 源码的字符数。

先搞清楚这一关在考什么#

前几关的坑通常藏在接口里,这一关反过来:页面是 Jinja2 服务端渲染的,电影数据直接写进了 HTML 源码。

所以拿到数据的方式只有一个:把页面请求下来,读源码。

但答案不是「抓到了哪些电影」,而是第一页源码有多少个字符。也就是说:

  1. 请求 GET /playground/movies/static(不加参数就是第 1 页);
  2. 把响应体当成文本(不是字节)数长度;
  3. 把数字提交到挑战广场。

现象:源码里全是数据#

浏览器打开靶场页 /playground/movies/static,页面上是电影卡片。右键「查看网页源代码」,能看到 <li> 里直接写着电影名、评分、评价人数:

<li class="movie-item">
<h3 class="movie-title">肖申克的救赎</h3>
<span class="movie-rating">9.7</span>
<span class="movie-rating-count">3235402人评价</span>
</li>

Network 面板里只有一个 document 请求,没有 XHR。这就说明数据在 HTML 里,而不是接口里。

三个最容易数错的地方#

写法数出来的是什么对不对
len(response.text)解码后字符数✅ 这一关要的就是这个
len(response.content)原始字节数(UTF-8 中文一个字 3 字节)❌ 会大好几倍
len(response.text.strip())去掉了首尾空白❌ 少几十个字符

还有一个隐蔽的坑:编码。如果 response.encoding 猜错了(比如把 UTF-8 当 ISO-8859-1),response.text 会变成乱码,字符数也就跟着错。

服务端已经声明了 Content-Type: text/html; charset=utf-8,正常情况下 requests 会照用。求稳可以显式指定:

response.encoding = "utf-8"

完整脚本#

"""CH-001:答案 = 第一页 HTML 源码的字符数"""
import sys
import requests
BASE = "https://spider.jsnote.top"
PAGE_URL = f"{BASE}/playground/movies/static"
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9",
"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"
),
}
response = requests.get(PAGE_URL, headers=headers, timeout=10)
response.raise_for_status()
response.encoding = "utf-8" # 显式指定,避免猜错编码导致字符数不对
html = response.text
print("状态码:", response.status_code)
print("Content-Type:", response.headers.get("Content-Type"))
print("源码字符数:", len(html))
print("源码字节数(对比用):", len(response.content))
print("页面里有没有电影名:", "movie-title" in html)
if len(sys.argv) > 1:
# 顺手核对一下第一页有多少部电影
print("电影卡片数:", html.count('class="movie-item"'))

跑完把 源码字符数 提交到挑战广场的 CH-001 答题框即可。参考实现见 参考代码/s1.py。

顺手确认一下「第 2 页也这样」#

page2 = requests.get(PAGE_URL, params={"page": 2}, headers=headers, timeout=10)
print(len(page2.text)) # 和第一页长度不同,说明确实在分页

这一关只需要第一页;但确认「改了参数内容会变」是好习惯 —— 能避免你把一个静态的缓存页当成接口。

排查清单#

  1. 源码里搜页面上确定存在的字(电影名),搜得到 → 数据在 HTML 里。
  2. 数长度前先确认 response.encoding,别让乱码影响字符数。
  3. 用 .text(字符)还是 .content(字节)先想清楚,两者差 2~3 倍。
  4. 不要 .strip()、不要 re.sub(r"\s+", "") —— 这一关答案要的就是原始长度。
  5. 提交答案要在登录状态下做。
  6. 如果数出来差一点点,先对比 len(html) 和 len(html.encode("utf-8")),确认自己数的是字符。

常见问题#

为什么答案不是「电影数量」?#

题面写的是「第一页源码的字符数」。这类题让你先确认源码就是数据源,再确认你拿到的响应体完整、没被二次处理。

用 requests.get(...).text 和浏览器「查看源代码」长度一样吗?#

一样(前提是编码一致、没做 gzip 之外的额外转换)。浏览器 DevTools 里看到的换行是 \n,requests 也不会替你改成 \r\n。

需要登录吗?#

这一关的靶场页本身不需要登录,但提交答案要登录,所以脚本里要不要带 cookie 取决于你是想直接提交,还是只想算出数字。

最后提醒#

这关的数据是自己靶场的练习数据。真实站点里,服务端渲染页通常还带缓存与 CDN,抓之前先看 robots 与条款,控制频率。

去挑战广场提交答案,然后进 CH-002:数据会从源码里消失,只剩接口。

文章分享

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

Python 爬虫入门实战:服务端渲染页面怎么取数(CH-001)
https://jsnote.top/posts/ls-ch1/
作者
xiajiao
发布于
2026-10-02
许可协议
CC BY-NC-SA 4.0
相关文章智能推荐
1
Python 爬虫接口实战:翻页取完再累加(CH-002)
爬虫靶场本文是 LearnSpider 第 2 关的解密教程。这一关的数据不在 HTML 里,只能从分页接口拿;答案是全部电影「评分总人数」的累加值。重点是:怎么找到接口、怎么确认它没把总量直接给你、以及怎么把 21 页稳稳翻完。
2
Python 爬虫实战:随机下发路径的资源怎么下载(CH-003)
爬虫靶场本文是 LearnSpider 第 3 关的解密教程。这一关要把图片下载下来,答案是这张图片的字节数。真正的考点是:拿到接口给的 image_id / image_url 之后,别把「字节」和「字符」搞混,也别拖太久(图片是随机下发的)。
3
Python 爬虫 TLS 指纹实战:requests 被挂住时怎么查(CH-004)
爬虫靶场本文是 LearnSpider 第 4 关的解密教程。这一关的接口数据本身是明文 JSON,难点在你根本连不上:requests 会一直卡到超时,服务端什么都不返回。答案是 5 页共 50 条关键词的 CPC 之和(保留 2 位小数)。
4
Python 爬虫验证码实战:AES 加密报文 + 每页算术验证码(CH-009)
爬虫靶场本文是 LearnSpider 第 9 关的解密教程。这一关把政务站点常见的一套反爬凑齐了:请求/响应都是 AES-ECB 加密的 hex,还要带一个前端写死的 Adam-AppKey,而且每翻一页都得先过一道算术验证码。目标是取 10 页…
5
Python 爬虫接口签名实战:参数签名 + 会话绑定(CH-005)
爬虫靶场本文是 LearnSpider 第 5 关的解密教程。这一关的接口参数要签名,而且取数只认一个「会话标识」(uuid)—— 这个 uuid 是页面自己生成的、并且已经在后端和你的账号绑定过。答案是 5 页共 50 个数字的总和。
随机文章随机推荐

评论区

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