(声明!本教程旨在进行技术了解与学习,不可用于恶意获取隐私信息、破坏互联网绿色环境等违法行为)
在教程(三)中,我们已经通过 XPath 解决了“精准打击”的问题,甚至处理了 CSS 代码干扰的突发状况。但你可能会发现,有些网页在浏览器里看着很全,可一旦用 requests 抓取源码,却发现关键数据变成了空壳,或者只有一串加密字符。
这就是教程(四)我们要攻克的难关:Ajax 动态加载与 API 逆向分析。
在现代网页(如微博、知乎、或者采用单页面架构的博客)中,为了提升加载速度,网页往往先加载“骨架”,然后再通过 Ajax 技术偷偷向服务器请求数据。所以我们的目标不再是网页源码,而是直接截获服务器发出的“原始数据包”。
当你发现直接请求 URL 拿不到数据时,请按照以下步骤进行“侦察”:
打开 F12,切换到 Network 标签页。
选择 Fetch/XHR:这里过滤掉了图片、CSS、JS 脚本,只留下纯粹的数据接口。
刷新页面:观察列表中出现的请求。
预览数据:点击请求,在 Preview 或 Response 中寻找你想要的那段文字。
确定接口:查看网络URL。作为爬取的准确网页接口。
我们拿最最最经典的豆瓣电影分类排行榜进行举例:
我们查看数据接口初始状态:

我们往下滑动页面,观察页面变化

这个时候可以发现,多了一条内容,正是加载过后才出现的,也就是说随着我们不断下滑,页面内容不断更新,会出现越来越多的接口信息。
我们查看信息具体的Response:

对应的电影信息就在其中。
确定了接口,我们就可以向其要数据了:
import requests
import csv
import time
def fetch_douban_movies(start_num, limit_num=20):
"""直接请求豆瓣 API 接口获取数据"""
# 1. 找到的 API 真实地址
api_url = 'https://movie.douban.com/j/chart/top_list'
# 2. 模拟浏览器,防止被拦截
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Referer': 'https://movie.douban.com/typerank' # 告诉服务器我从哪儿跳转来的
}
# 3. 参数构造:通过修改 start 实现自动翻页
params = {
'type': '11', # 11 代表剧情分类
'interval_id': '100:90', # 评分区间
'action': '',
'start': str(start_num), # 起始位置
'limit': str(limit_num) # 每次获取多少条
}
try:
response = requests.get(api_url, params=params, headers=headers, timeout=10)
if response.status_code == 200:
# 4. 直接返回解析后的 JSON 数据(Python 的字典列表)
return response.json()
else:
print(f"请求失败,状态码:{response.status_code}")
return []
except Exception as e:
print(f"发生异常:{e}")
return []
# --- 主程序:爬取前 60 名电影并保存 ---
if __name__ == "__main__":
all_movies = []
# 模拟翻页:每次取 20 条,取 5 次
for i in range(0, 100, 20):
print(f"正在抓取第 {i + 1} 到 {i + 20} 名...")
data = fetch_douban_movies(start_num=i)
all_movies.extend(data)
time.sleep(2) # 豆瓣反爬较严,慢一点
# 5. 存储到 CSV
with open('douban_top.csv', 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.writer(f)
writer.writerow(['排名', '电影名称', '评分', '评论人数', '链接'])
for m in all_movies:
writer.writerow([
m['rank'],
m['title'],
m['rating'][0],
m['vote_count'],
f"https://movie.douban.com/subject/{m['id']}/"
])
print(f"\n成功!已保存 {len(all_movies)} 部电影到 douban_top.csv")

我们就可以获得对应的电影数据了。
观察代码里的 params。在豆瓣这个案例中,如果你把 start 改为 20,你会发现抓到的是第 21-40 名。学会分析 API 参数,你就掌握了控制网页“翻页”和“筛选”的遥控器。
在本章案例中,我们完成了一次华丽的“绕后攻击”:
不再死磕 HTML:不用管 div、span 嵌套了多少层,不用担心 CSS 的干扰。
效率百倍提升:接口返回的数据是规整的 JSON,程序读取它只需要微秒级。
掌握翻页命门:通过观察 Network 发现 start 参数,我们不需要点碎鼠标,只要改个数字,就能轻松遍历整个数据库。
这就是 API 逆向的魅力:它直接触达数据的灵魂。
通过这一篇,你已经完成了从“网页表面”到“后端数据”的跨越。现在的你,不仅能爬静态站,也能应对绝大多数现代异步加载的动态站。但在进阶的过程中,你会发现有些 API 接口不是谁都能访问的——它们可能需要登录(Cookie/Session),或者带有复杂的加密签名(Token)。
在教程(五)中,我们将挑战“对抗期”:学习如何处理登录状态、如何维持 Session,以及如何使用 IP 代理池来躲避服务器的疯狂封锁!