㊗️本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~
㊙️本期爬虫难度指数:⭐⭐⭐
🉐福利: 一次订阅后,专栏内的所有文章可永久免费看,持续更新中,保底1000+(篇)硬核实战内容。

全文目录:
-
-
- [🌟 开篇语](#🌟 开篇语)
- [0️⃣ 前言(Preface)](#0️⃣ 前言(Preface))
- [1️⃣ 摘要(Abstract)](#1️⃣ 摘要(Abstract))
- [2️⃣ 背景与需求(Why)](#2️⃣ 背景与需求(Why))
- [3️⃣ 合规与注意事项(必写)⚠️](#3️⃣ 合规与注意事项(必写)⚠️)
- [4️⃣ 技术选型与整体流程(What/How)](#4️⃣ 技术选型与整体流程(What/How))
- [5️⃣ 环境准备与依赖安装(可复现)](#5️⃣ 环境准备与依赖安装(可复现))
- [6️⃣ 核心实现:请求层(监听器 Fetcher)](#6️⃣ 核心实现:请求层(监听器 Fetcher))
- [7️⃣ 核心实现:解析层(Parser)](#7️⃣ 核心实现:解析层(Parser))
- [8️⃣ 数据存储与导出(Storage)](#8️⃣ 数据存储与导出(Storage))
- [9️⃣ 运行方式与结果展示(必写)](#9️⃣ 运行方式与结果展示(必写))
- [🔟 常见问题与排错(Troubleshooting)](#🔟 常见问题与排错(Troubleshooting))
- [1️⃣1️⃣ 进阶优化(可选)🚀](#1️⃣1️⃣ 进阶优化(可选)🚀)
- [1️⃣2️⃣ 总结与延伸阅读](#1️⃣2️⃣ 总结与延伸阅读)
- [🌟 文末](#🌟 文末)
-
- [✅ 专栏持续更新中|建议收藏 + 订阅](#✅ 专栏持续更新中|建议收藏 + 订阅)
- [✅ 互动征集](#✅ 互动征集)
- [✅ 免责声明](#✅ 免责声明)
-
🌟 开篇语
哈喽,各位小伙伴们你们好呀~我是【喵手】。
运营社区: C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO
欢迎大家常来逛逛,一起学习,一起进步~🌟
我长期专注 Python 爬虫工程化实战 ,主理专栏 《Python爬虫实战》:从采集策略 到反爬对抗 ,从数据清洗 到分布式调度 ,持续输出可复用的方法论与可落地案例。内容主打一个"能跑、能用、能扩展 ",让数据价值真正做到------抓得到、洗得净、用得上。
📌 专栏食用指南(建议收藏)
- ✅ 入门基础:环境搭建 / 请求与解析 / 数据落库
- ✅ 进阶提升:登录鉴权 / 动态渲染 / 反爬对抗
- ✅ 工程实战:异步并发 / 分布式调度 / 监控与容错
- ✅ 项目落地:数据治理 / 可视化分析 / 场景化应用
📣 专栏推广时间 :如果你想系统学爬虫,而不是碎片化东拼西凑,欢迎订阅专栏👉《Python爬虫实战》👈,一次订阅后,专栏内的所有文章可永久免费阅读,持续更新中。
💕订阅后更新会优先推送,按目录学习更高效💯~
0️⃣ 前言(Preface)
👋 大家好!今天我们要攻克的是 Figma Community 。
如果你尝试过右键查看 Figma 社区的源代码,你会发现里面全是复杂的 React 组件和随机 Class 名。传统的 HTML 解析在这里寸步难行。
今天我们将使用 Playwright 的网络拦截功能 。我们不解析网页,而是让 Playwright 启动浏览器,像真实用户一样访问,然后在后台静默监听网页发起的数据请求(XHR/Fetch),直接截获原始的 JSON 数据包。这是爬虫界"四两拨千斤"的顶级技巧!
✨ 读完这篇你将获得:
- 网络拦截技能 :学会使用
page.on('response', ...)监听并捕获后台数据。 - 混合开发模式:结合浏览器的自动化操作与 API 的数据纯度。
- 清洗复杂的嵌套数据:从原始 JSON 中提取插件元数据。
1️⃣ 摘要(Abstract)
本文介绍了一种基于 Playwright 的网络监听爬虫方案。针对 Figma 社区高度动态化的特点,我们放弃 DOM 解析,转而通过拦截 api/community_search 等核心接口的响应,直接获取结构化的 JSON 数据。这种方法既避开了复杂的反爬验证(由浏览器自动处理),又保证了数据的完整性和准确性。
2️⃣ 背景与需求(Why)
🔍 为什么要爬:
Figma 插件生态爆发式增长。开发者想知道:"现在做什么类型的插件最容易火?"、"同类插件的下载量天花板是多少?"。我们需要一份精确的榜单数据来辅助决策。
🎯 目标站点: https://www.figma.com/community/plugins
📋 目标字段清单:
- Plugin Name (插件名)
- Author/Publisher (作者/发布者)
- Install Count (安装量 - 核心指标)
- Like/Love Count (点赞/评分)
- Description (简介)
3️⃣ 合规与注意事项(必写)⚠️
- 数据边界 :我们只采集公开的社区索引数据,严禁尝试爬取用户的私有设计文件(Figma Files),这不仅违规而且技术上很难实现(需要鉴权)。
- 请求频率:虽然我们是监听浏览器请求,但滚屏加载过快依然会触发 Figma 的限流(429)。保持"像人一样"的操作节奏。
- 版权声明:Figma 社区内容归原作者所有,采集的数据仅供分析,不可用于复制抄袭。
4️⃣ 技术选型与整体流程(What/How)
🛠 技术选型:
- Request/BS4:❌ 页面是空的,且 API 有复杂的签名(Signature),逆向难度极大。
- Playwright (DOM 模式):⚠️ 可以,但提取数字(如 "1.5k")不精确,且 DOM 结构常变。
- Playwright (Network 模式) :✅ 完美。浏览器帮我们搞定签名和 Cookie,我们只负责"捡"回来的数据。
⚙️ 流程图:
[ 启动浏览器 ] ➡️ [ 注册 Response 监听器 ] ➡️ [ 打开 Figma 社区 ] ➡️ [ 模拟滚动 ] ➡️ [ 触发 API 响应 ] ➡️ [ 拦截并保存 JSON ] ➡️ [ 清洗入库 ]
5️⃣ 环境准备与依赖安装(可复现)
💻 Python 版本:3.8+
📦 依赖安装:
bash
pip install playwright pandas
playwright install chromium
📂 项目结构:
text
figma_interceptor/
├── main.py
└── data/
└── figma_plugins.csv
6️⃣ 核心实现:请求层(监听器 Fetcher)
这是本篇的核心!我们需要编写一个回调函数,当浏览器接收到特定 URL 的响应时,自动把数据存下来。
python
import asyncio
from playwright.async_api import async_playwright
import json
import random
# 用于在内存中暂存拦截到的数据
captured_plugins = []
async def handle_response(response):
"""
这是我们的'窃听器'函数。
当浏览器收到任何响应时,都会经过这里。
"""
# 1. 过滤 URL:我们只关心包含 'search' 或 'feed' 的接口
# 经过 F12 观察,Figma 社区主要接口类似:https://www.figma.com/api/community_search/...
if "api/community_search" in response.url and response.status == 200:
print(f"🕵️♂️ Intercepted API: {response.url[:60]}...")
try:
# 2. 获取 JSON 数据
data = await response.json()
# 3. 解析数据结构 (Figma 的结构非常深)
# 通常在 meta -> resources 或者 result -> meta 里面
# 这里需要根据实际抓包结果调整路径,以下是基于经验的通用路径
resources = data.get('meta', {}).get('resources', [])
for resource in resources:
# 只要插件 (resource_type == 'plugin')
if resource.get('resource_type') == 'plugin':
plugin_info = {
'id': resource.get('id'),
'name': resource.get('name'),
'author': resource.get('publisher', {}).get('name', 'Unknown'),
'install_count': resource.get('install_count', 0),
'like_count': resource.get('like_count', 0),
'created_at': resource.get('created_at')
}
captured_plugins.append(plugin_info)
print(f" ✅ Captured {len(resources)} items from this packet.")
except Exception as e:
# 忽略非 JSON 响应或解析错误
pass
async def run_scraper():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False) # 有头模式,方便看效果
context = await browser.new_context()
page = await context.new_page()
# 🔥 核心:注册监听器
# 只要发生网络响应,就调用 handle_response
page.on("response", handle_response)
print("🌍 Navigating to Figma Community...")
# 访问热门插件页
await page.goto("https://www.figma.com/community/plugins?sort_by=popular", timeout=60000)
# 等待首屏加载
await page.wait_for_timeout(5000)
# --- 模拟滚动加载 (Pagination) ---
# Figma 是无限滚动,我们滚它个 5-10 次
for i in range(5):
print(f"📜 Scrolling page... ({i+1}/5)")
await page.keyboard.press("End")
# 随机等待,让 API 有时间响应
await page.wait_for_timeout(random.randint(3000, 5000))
print("🏁 Scraping finished.")
await browser.close()
7️⃣ 核心实现:解析层(Parser)
在上面的代码中,解析逻辑已经融合在 handle_response 里了。
为什么不分开写?
因为在拦截模式下,数据是流式进来的,拿到响应的瞬间解析是最简单的。
不过,我们可以补一个数据清洗函数 ,把内存里的 captured_plugins 整理成最终格式。
python
import pandas as pd
def process_data(raw_data):
"""
清洗、去重、格式化
"""
if not raw_data:
print("⚠️ No data captured.")
return pd.DataFrame()
df = pd.DataFrame(raw_data)
# 1. 去重 (因为滚动时API可能会返回重复数据)
df.drop_duplicates(subset=['id'], inplace=True)
# 2. 格式化数字 (Figma API 返回的是整数,不需要去 'k',非常爽!)
# 我们可以加一个 'Formatted Installs' 方便阅读
df['install_fmt'] = df['install_count'].apply(lambda x: f"{x/1000:.1f}k" if x > 1000 else str(x))
# 3. 排序
df.sort_values(by='install_count', ascending=False, inplace=True)
return df
8️⃣ 数据存储与导出(Storage)
python
import os
def save_to_csv(df, filename="figma_plugins.csv"):
if df.empty:
return
os.makedirs('data', exist_ok=True)
filepath = os.path.join('data', filename)
df.to_csv(filepath, index=False, encoding='utf-8-sig')
print(f"💾 Saved {len(df)} plugins to {filepath}")
# 打印前 5 名
print("\n🏆 Top 5 Popular Figma Plugins:")
print(df[['name', 'author', 'install_count']].head(5).to_markdown(index=False))
9️⃣ 运行方式与结果展示(必写)
启动脚本 (main.py):
python
# 整合入口
if __name__ == "__main__":
# 1. 运行爬虫
asyncio.run(run_scraper())
# 2. 处理数据
print(f"📊 Total items intercepted: {len(captured_plugins)}")
df_clean = process_data(captured_plugins)
# 3. 保存
save_to_csv(df_clean)
示例运行结果 (Console):
text
🌍 Navigating to Figma Community...
🕵️♂️ Intercepted API: https://www.figma.com/api/community_search/search_results...
✅ Captured 48 items from this packet.
📜 Scrolling page... (1/5)
🕵️♂️ Intercepted API: https://www.figma.com/api/community_search/search_results...
✅ Captured 24 items from this packet.
...
🏁 Scraping finished.
📊 Total items intercepted: 144
💾 Saved 120 plugins to data/figma_plugins.csv
🏆 Top 5 Popular Figma Plugins:
| name | author | install_count |
| :--- | :--- | :--- |
| Unsplash | Unsplash | 1500000 |
| Iconify | Iconify | 1200000 |
| Content Reel | Microsoft | 980000 |
| Lorem Ipsum | David | 850000 |
| Remove BG | Aaron | 720000 |
🔟 常见问题与排错(Troubleshooting)
-
没有拦截到数据 (API URL 变了):
- 原因 :Figma 更新了 API 路径,比如从
community_search变成了search_v2。 - 解决 :打开浏览器 F12 -> Network -> XHR,手动滚动一下,看那个最大的 JSON 响应是谁,把它的 URL 关键词填进
handle_response的if判断里。
- 原因 :Figma 更新了 API 路径,比如从
-
数据字段报错 (KeyError):
- 原因:JSON 结构嵌套很深,容易取空。
- 解决 :一定要用
.get()方法,比如data.get('meta', {}).get('resources', []),千万别直接用data['meta']['resources'],否则一个空包就让程序挂了。
-
浏览器卡死:
- 原因:Figma 页面非常吃内存(Canvas 渲染)。
- 解决 :在
launch时添加参数args=['--disable-gl-drawing-for-tests']可以禁用一部分图形渲染,减轻负担。
1️⃣1️⃣ 进阶优化(可选)🚀
-
全量搜索:
- 通过
page.goto(".../search?query=icon")配合关键词字典,可以按类别把所有插件都扫一遍。
- 通过
-
数据库入库:
- 数据量如果很大,建议用
SQLite替代 CSV。Playwright 拦截的数据直接INSERT OR IGNORE进数据库,实现实时持久化,防止程序跑了一半崩溃数据全丢。
- 数据量如果很大,建议用
-
无头模式 (Headless):
- 调试完成后,把
headless=False改为True,部署到服务器上每天定时跑一次,监控"新晋黑马插件"。
- 调试完成后,把
1️⃣2️⃣ 总结与延伸阅读
🎉 复盘:
今天我们展示了爬虫技术的"第三条路":Playwright 网络拦截 。
相比于笨拙的 DOM 解析和极难的 API 逆向,这种方法是目前应对现代 SPA(单页应用)性价比最高的方案。我们利用浏览器作为"代理人",轻松拿到了 Figma 官方最纯净的源数据。
👀 下一步:
这项技术在爬取 Twitter/X 、Instagram 、Airbnb 等无限滚动且高度动态的网站时同样威力无穷。只要你能看到数据在加载,你就能用这个方法拦截下来!
去试试拦截你喜欢的网站吧,记得看 F12 的 Network 标签页,那里藏着金矿!💰
🌟 文末
好啦~以上就是本期的全部内容啦!如果你在实践过程中遇到任何疑问,欢迎在评论区留言交流,我看到都会尽量回复~咱们下期见!
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦~
三连就是对我写作道路上最好的鼓励与支持! ❤️🔥
✅ 专栏持续更新中|建议收藏 + 订阅
墙裂推荐订阅专栏 👉 《Python爬虫实战》,本专栏秉承着以"入门 → 进阶 → 工程化 → 项目落地"的路线持续更新,争取让每一期内容都做到:
✅ 讲得清楚(原理)|✅ 跑得起来(代码)|✅ 用得上(场景)|✅ 扛得住(工程化)
📣 想系统提升的小伙伴 :强烈建议先订阅专栏 《Python爬虫实战》,再按目录大纲顺序学习,效率十倍上升~

✅ 互动征集
想让我把【某站点/某反爬/某验证码/某分布式方案】等写成某期实战?
评论区留言告诉我你的需求,我会优先安排实现(更新)哒~
⭐️ 若喜欢我,就请关注我叭~(更新不迷路)
⭐️ 若对你有用,就请点赞支持一下叭~(给我一点点动力)
⭐️ 若有疑问,就请评论留言告诉我叭~(我会补坑 & 更新迭代)
✅ 免责声明
本文爬虫思路、相关技术和代码仅用于学习参考,对阅读本文后的进行爬虫行为的用户本作者不承担任何法律责任。
使用或者参考本项目即表示您已阅读并同意以下条款:
- 合法使用: 不得将本项目用于任何违法、违规或侵犯他人权益的行为,包括但不限于网络攻击、诈骗、绕过身份验证、未经授权的数据抓取等。
- 风险自负: 任何因使用本项目而产生的法律责任、技术风险或经济损失,由使用者自行承担,项目作者不承担任何形式的责任。
- 禁止滥用: 不得将本项目用于违法牟利、黑产活动或其他不当商业用途。
- 使用或者参考本项目即视为同意上述条款,即 "谁使用,谁负责" 。如不同意,请立即停止使用并删除本项目。!!!
