㊗️本期内容已收录至专栏《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)
👋 大家好!今天我们要挑战的是设计界的霸主------Canva。
很多设计师想知道:"现在最火的 Instagram 帖子模板是什么风格?"、"哪种配色方案用的最多?"。
由于 Canva 的网页全是动态生成的(React),且 Class 名全是随机乱码(如 _1QoxDw),传统的爬虫手段在这里统统失效。
今天,我们将使用 Playwright 模拟真实浏览器,实现**"滚动翻页"**,抓取模板元数据,并统计出当下的设计流行趋势。
✨ 读完这篇你将获得:
- Playwright 实战能力:学会处理无限滚动(Infinite Scroll)页面。
- 抗混淆技巧:在 CSS Class 随机变动的情况下,如何用 XPath/CSS 选择器精准定位元素。
- 视觉化数据:从单纯的代码到可视化的热门关键词分析。
1️⃣ 摘要(Abstract)
本文针对 Canva 模板库的高动态特性,采用 Python 的 playwright 库驱动 Chromium 浏览器进行自动化采集。通过模拟鼠标滚动触发数据加载,抓取模板的标题、链接及付费状态(Pro/Free)。最终,我们将清洗数据并统计高频出现的关键词,洞察当前的设计热门标签。
2️⃣ 背景与需求(Why)
🔍 为什么要爬:
设计趋势瞬息万变。通过分析 Canva 首页推荐或特定分类下的"热门"模板,我们可以量化设计趋势(例如:现在是"极简主义"流行还是"复古风"流行?)。
🎯 目标站点: https://www.canva.com/templates/ (或特定的搜索结果页)
📋 目标字段清单:
- Template Name (模板名称/标题)
- Creator (创作者 - 若可见)
- Is Pro (是否为付费 Pro 版)
- Keywords (从标题中提取的推荐标签)
- Rank (在热门列表中的位置,作为"流行度"的替代指标)
(注:Canva 前端界面通常隐藏了具体的"使用次数",我们将用"热门排序下的位置"来代表流行度。)
3️⃣ 合规与注意事项(必写)⚠️
Canva 的反爬非常严格,请务必遵守:
- 频率控制 :极度重要! 不要开多线程并发!Playwright 模拟的是真实用户,请保持单线程并加上随机等待。
- Cloudflare 验证 :Canva 前置了 Cloudflare 盾。如果脚本启动时遇到验证码,请在"有头模式"(
headless=False)下手动点一下。 - 数据隐私:我们只采集公开的模板元数据,不涉及任何用户个人设计草稿。
4️⃣ 技术选型与整体流程(What/How)
🛠 技术选型:
- Requests:❌ 无法处理,页面全是 JS。
- Selenium:⚠️ 可以,但速度慢,驱动配置麻烦。
- Playwright:✅ 完美。原生支持异步,无需手动下载 Driver,且对现代 SPA 网页支持极好。
⚙️ 流程图:
[ 启动浏览器 ] ➡️ [ 打开 Canva 模板页 ] ➡️ [ 模拟鼠标滚动(加载更多) ] ➡️ [ 提取 DOM 元素 ] ➡️ [ 解析清洗 ] ➡️ [ 统计关键词 ]
5️⃣ 环境准备与依赖安装(可复现)
💻 Python 版本:3.8+
📦 依赖安装 :
我们需要安装 playwright 库以及 pandas。
bash
pip install playwright pandas
# 安装完成后,必须运行下面这就话来安装浏览器内核
playwright install chromium
📂 项目结构:
text
canva_scraper/
├── main.py
└── data/
└── canva_trends.csv
6️⃣ 核心实现:请求层(Fetcher)
我们将编写一个异步函数,启动浏览器并加载页面。为了防止被识别为机器人,我们需要设置一些特殊的 context 参数。
python
import asyncio
from playwright.async_api import async_playwright
import random
async def fetch_templates(keyword="instagram-post"):
"""
使用 Playwright 启动浏览器并抓取
"""
async with async_playwright() as p:
# ⚠️ 关键点:headless=False 让你可以看到浏览器运行,
# 如果遇到 Cloudflare 验证码,你可以手动点一下!
browser = await p.chromium.launch(headless=False, slow_mo=500)
# 伪装 User-Agent
context = await browser.new_context(
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',
viewport={'width': 1920, 'height': 1080}
)
page = await context.new_page()
# 访问 Canva 模板搜索页(按热门排序)
target_url = f"https://www.canva.com/templates/?query={keyword}"
print(f"🌍 Navigating to: {target_url}")
try:
await page.goto(target_url, timeout=60000, wait_until="networkidle")
except Exception as e:
print(f"⚠️ Page load timeout (common for heavy sites), continuing anyway... Error: {e}")
# --- 模拟滚动加载 (Infinite Scroll) ---
# 我们要抓取热门的前 100 个,大概需要滚动 3-5 次
for i in range(5):
print(f"📜 Scrolling page... ({i+1}/5)")
await page.keyboard.press("End") # 模拟按下 End 键到底部
await asyncio.sleep(random.uniform(2, 4)) # 等待新内容加载
# 返回页面内容供解析
content = await page.content()
# 在这里直接解析 DOM 元素,比把 HTML 传出去解析更稳,因为元素依然在内存中
# 我们将在下一步实现具体的提取逻辑
return page, browser # 返回 page 对象以便后续操作
7️⃣ 核心实现:解析层(Parser)
难点 :Canva 的 Class 名字全是随机的(例如 class="A82_za")。我们不能依赖 class。
策略 :依赖属性选择器 和层级关系 。通常模板是一个链接 a 标签,里面包含图片和标题。
python
async def parse_elements(page):
"""
从当前页面提取模板信息
"""
print("🕵️ Extracting template data...")
# Canva 的模板通常包裹在 a 标签里,且 href 包含 '/templates/'
# 我们使用 CSS 选择器定位所有包含 templates 路径的链接
# 注意:这需要根据 Canva 当时的实际 DOM 结构微调,以下是通用策略
# 查找所有可能是模板卡片的元素
# 这里的选择器逻辑:找所有 href 里带有 '/templates/' 的 <a> 标签
cards = await page.query_selector_all("a[href*='/templates/']")
results = []
seen_urls = set()
for card in cards:
try:
# 1. 提取链接
href = await card.get_attribute("href")
full_url = f"https://www.canva.com{href}"
# 去重:Canva 页面上可能有重复的推荐
if full_url in seen_urls:
continue
seen_urls.add(full_url)
# 2. 提取文本内容(包含标题)
# Canva 的标题通常在 aria-label 或者内部的某个 div 文本里
# 简单的做法是获取整个卡片的文本,然后清洗
text_content = await card.inner_text()
lines = text_content.split('\n')
# 简单启发式清洗:通常最长的且不是 'Pro'/'Free' 的就是标题
title = "Unknown"
is_pro = False
for line in lines:
if "Pro" in line or "Paid" in line:
is_pro = True
elif len(line) > 5 and title == "Unknown":
title = line.strip()
# 3. 如果标题还是拿不到,尝试拿 aria-label
if title == "Unknown":
aria = await card.get_attribute("aria-label")
if aria:
title = aria
results.append({
'Template Name': title,
'Is Pro': is_pro,
'URL': full_url,
'Raw Tags': title # 我们把标题作为原始标签来源
})
except Exception as e:
continue
print(f"✅ Extracted {len(results)} templates.")
return results
8️⃣ 数据存储与导出(Storage)
我们将数据存为 CSV,并做一个简单的"热门词频统计",把标题里的词拆开算作标签。
python
import pandas as pd
import os
from collections import Counter
import re
def save_and_analyze(data_list):
if not data_list:
print("❌ No data to save.")
return
df = pd.DataFrame(data_list)
# 1. 保存原始数据
os.makedirs('data', exist_ok=True)
df.to_csv('data/canva_trends.csv', index=False, encoding='utf-8-sig')
print("💾 Raw data saved to data/canva_trends.csv")
# 2. 热门标签分析 (简单 NLP)
# 把所有标题拼起来,转小写,正则提取单词
all_text = " ".join(df['Template Name'].astype(str).tolist()).lower()
# 过滤掉无意义词汇
stopwords = {'template', 'design', 'instagram', 'post', 'free', 'unknown', 'the', 'and', 'for', 'with'}
words = re.findall(r'\b\w+\b', all_text)
filtered_words = [w for w in words if w not in stopwords and len(w) > 2]
# 统计前 10 个热词
top_keywords = Counter(filtered_words).most_common(10)
print("\n🔥 === HOT DESIGN TRENDS (Top Keywords) ===")
for word, count in top_keywords:
print(f" #{word}: {count} occurrences")
# 保存热词统计
pd.DataFrame(top_keywords, columns=['Keyword', 'Count']).to_csv('data/trend_analysis.csv', index=False)
9️⃣ 运行方式与结果展示(必写)
启动脚本 (main.py):
python
# 整合上面的代码
async def main():
# 假设我们想看 "Instagram Story" 的设计趋势
page, browser = await fetch_templates(keyword="instagram-story")
if page:
data = await parse_elements(page)
save_and_analyze(data)
await browser.close()
if __name__ == "__main__":
asyncio.run(main())
示例运行结果 (Console):
text
🌍 Navigating to: https://www.canva.com/templates/?query=instagram-story
📜 Scrolling page... (1/5)
📜 Scrolling page... (2/5)
...
✅ Extracted 120 templates.
💾 Raw data saved to data/canva_trends.csv
🔥 === HOT DESIGN TRENDS (Top Keywords) ===
#minimalist: 45 occurrences
#beige: 32 occurrences
#aesthetic: 28 occurrences
#business: 15 occurrences
#fashion: 12 occurrences
📊 结果解读:
从输出可以看到,当前 Instagram Story 最火的设计风格是 Minimalist (极简) 和 Beige (米色调)。如果你是设计师,现在做米色极简风的模板肯定好卖!这就是数据的价值!💰
🔟 常见问题与排错(Troubleshooting)
-
卡在 Cloudflare 验证页面:
- 现象:浏览器打开后一直转圈,或者出现"Verify you are human"。
- 解决 :因为我们设置了
headless=False,请人工介入点一下验证框。或者尝试使用指纹浏览器插件(如playwright_stealth)。
-
找不到元素 (Selector Error):
- 现象 :
Extracted 0 templates。 - 原因:Canva 改版了 HTML 结构。
- 解决 :打开浏览器开发者工具 (F12),查看模板链接的特征。如果 href 规则变了,需要更新
parse_elements里的选择器。
- 现象 :
-
Playwright 安装失败:
- 解决 :确保运行了
playwright install chromium。
- 解决 :确保运行了
1️⃣1️⃣ 进阶优化(可选)🚀
-
图片色系分析:
- Playwright 可以对元素截图
element.screenshot()。你可以把每个模板截图下来,用OpenCV或Pillow分析图片的主色调(Dominant Color),做更深度的"色彩趋势报告"。
- Playwright 可以对元素截图
-
自动化登录:
- 如果需要抓取"我的收藏"或特定付费内容,可以编写 Playwright 脚本自动填充账号密码登录(注意:这会增加封号风险)。
-
无头模式优化:
- 调试通了之后,可以尝试把
headless=False改为True,并配合playwright-stealth库来尝试绕过检测,实现后台静默运行。
- 调试通了之后,可以尝试把
1️⃣2️⃣ 总结与延伸阅读
🎉 复盘:
今天我们完成了一个高难度的爬虫任务。面对 Canva 这种全动态、随机类名、强风控 的站点,传统的 requests 束手无策,但 Playwright 像一位全能特工,轻松模拟人类操作拿到了数据。
我们不仅抓取了数据,还通过简单的词频统计 ,把枯燥的列表变成了有价值的设计趋势报告。
👀 下一步:
- 试试用 Playwright 抓取 Pinterest?它和 Canva 一样也是瀑布流布局,非常适合练习。
- 研究一下
Scrapy-Playwright插件,将 Scrapy 的并发优势和 Playwright 的渲染能力结合起来。
保持对技术的热爱,你就是数据世界的探索者!🌟
🌟 文末
好啦~以上就是本期的全部内容啦!如果你在实践过程中遇到任何疑问,欢迎在评论区留言交流,我看到都会尽量回复~咱们下期见!
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦~
三连就是对我写作道路上最好的鼓励与支持! ❤️🔥
✅ 专栏持续更新中|建议收藏 + 订阅
墙裂推荐订阅专栏 👉 《Python爬虫实战》,本专栏秉承着以"入门 → 进阶 → 工程化 → 项目落地"的路线持续更新,争取让每一期内容都做到:
✅ 讲得清楚(原理)|✅ 跑得起来(代码)|✅ 用得上(场景)|✅ 扛得住(工程化)
📣 想系统提升的小伙伴 :强烈建议先订阅专栏 《Python爬虫实战》,再按目录大纲顺序学习,效率十倍上升~

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