🔥本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~持续更新中!!

全文目录:
-
- [🌟 开篇语](#🌟 开篇语)
-
- [📚 上期回顾](#📚 上期回顾)
- [🎯 本篇目标](#🎯 本篇目标)
- [💡 为什么需要 Playwright?](#💡 为什么需要 Playwright?)
- [🔧 Playwright 是什么?](#🔧 Playwright 是什么?)
- [🛠️ 安装 Playwright](#🛠️ 安装 Playwright)
- [📖 基础操作:打开页面](#📖 基础操作:打开页面)
- [⏳ 核心难点:等待策略](#⏳ 核心难点:等待策略)
-
- [策略 1:等待页面加载完成(load)](#策略 1:等待页面加载完成(load))
- [策略 2:等待网络空闲(networkidle)](#策略 2:等待网络空闲(networkidle))
- [策略 3:等待特定元素出现](#策略 3:等待特定元素出现)
- [策略 4:等待固定时间(不推荐)](#策略 4:等待固定时间(不推荐))
- [📸 实战:截图 + HTML dump](#📸 实战:截图 + HTML dump)
- [🎨 调试技巧](#🎨 调试技巧)
-
- [技巧 1:有头模式 + 慢动作](#技巧 1:有头模式 + 慢动作)
- [技巧 2:截图是最好的调试工具](#技巧 2:截图是最好的调试工具)
- [技巧 3:打印 HTML 长度判断](#技巧 3:打印 HTML 长度判断)
- [⚠️ 新手常见坑](#⚠️ 新手常见坑)
-
- [坑 1:没有等待就提取内容](#坑 1:没有等待就提取内容)
- [坑 2:超时设置不合理](#坑 2:超时设置不合理)
- [坑 3:忘记关闭浏览器](#坑 3:忘记关闭浏览器)
- [📊 性能优化](#📊 性能优化)
-
- [优化 1:禁用图片/CSS(提速)](#优化 1:禁用图片/CSS(提速))
- [优化 2:复用浏览器实例](#优化 2:复用浏览器实例)
- [🎯 下期预告](#🎯 下期预告)
- [🌟 文末](#🌟 文末)
-
- [📌 专栏持续更新中|建议收藏 + 订阅](#📌 专栏持续更新中|建议收藏 + 订阅)
- [✅ 互动征集](#✅ 互动征集)
🌟 开篇语
哈喽,各位小伙伴们你们好呀~我是【喵手】。
运营社区: C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO
欢迎大家常来逛逛,一起学习,一起进步~🌟
我长期专注 Python 爬虫工程化实战 ,主理专栏 👉 《Python爬虫实战》:从采集策略 到反爬对抗 ,从数据清洗 到分布式调度 ,持续输出可复用的方法论与可落地案例。内容主打一个"能跑、能用、能扩展 ",让数据价值真正做到------抓得到、洗得净、用得上。
📌 专栏食用指南(建议收藏)
- ✅ 入门基础:环境搭建 / 请求与解析 / 数据落库
- ✅ 进阶提升:登录鉴权 / 动态渲染 / 反爬对抗
- ✅ 工程实战:异步并发 / 分布式调度 / 监控与容错
- ✅ 项目落地:数据治理 / 可视化分析 / 场景化应用
📣 专栏推广时间 :如果你想系统学爬虫,而不是碎片化东拼西凑,欢迎订阅/关注专栏《Python爬虫实战》
订阅后更新会优先推送,按目录学习更高效~
📚 上期回顾
恭喜你完成第 6 章!现在你的爬虫已经有了"增量采集"、"断点续爬"、"幂等去重"三大杀器。对于普通的静态网站,你已经游刃有余了。
但真实世界总有新挑战:你打开浏览器能看到商品列表,用 requests.get() 却只拿到一个空壳 HTML;你在页面上能点击"加载更多",代码里却找不到下一页的 URL。
这不是你的问题,而是你遇到了动态渲染网站------数据藏在 JavaScript 里,必须等浏览器执行完才能看到。😤
今天,我们就用 Playwright 来破局!
🎯 本篇目标
看完这篇,你能做到:
- 理解动态渲染原理(为什么 requests 抓不到)
- 安装并启动 Playwright(自动化浏览器)
- 打开页面并等待加载(等待策略很关键)
- 提取渲染后的 HTML(截图 + HTML dump)
验收标准:**用 Playwright 打开一个动态网站,保存截图和完
💡 为什么需要 Playwright?
场景对比
静态网站(requests 能搞定):
json
浏览器请求 → 服务器返回完整 HTML → 直接展示
用 requests.get() 拿到的就是最终页面。
动态网站(requests 无能为力):
json
浏览器请求 → 服务器返回空壳 HTML + JS 代码
↓
浏览器执行 JS
↓
发送 Ajax 请求获取数据
↓
JS 把数据渲染到页面
用 requests.get() 只能拿到空壳,看不到真正的数据。
真实案例
打开某电商网站的商品列表:
浏览器看到的:
html
<div class="product-list">
<div class="item">商品A - ¥99</div>
<div class="item">商品B - ¥199</div>
...
</div>
requests 拿到的:
html
<div class="product-list">
<!-- 数据将由 app.js 渲染 -->
</div>
<script src="app.js"></script>
数据在 app.js 里,必须等浏览器执行才能出现!
🔧 Playwright 是什么?
Playwright 是微软开发的自动化测试工具,但我们拿来做爬虫刚刚好。
核心能力:
- ✅ 控制真实浏览器(Chrome/Firefox/Safari)
- ✅ 等待 JavaScript 执行完成
- ✅ 模拟用户操作(点击、滚动、输入)
- ✅ 截图、录屏、拦截网络请求
类似工具对比:
| 工具 | 优点 | 缺点 |
|---|---|---|
| Selenium | 老牌稳定 | 速度慢、API 繁琐 |
| Playwright | 快、现代、API 友好 | 社区相对小 |
| Puppeteer | 轻量 | 只支持 Chrome |
新手推荐 Playwright,生态成熟且文档清晰。👍
🛠️ 安装 Playwright
第一步:安装 Python 库
bash
pip install playwright
第二步:安装浏览器
Playwright 需要下载浏览器驱动(首次使用):
bash
playwright install chromium
这会下载约 300MB 的 Chromium 浏览器(和 Chrome 一样的内核)。
也可以安装其他浏览器:
bash
playwright install firefox
playwright install webkit # Safari 内核
验证安装
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # 有头模式,能看到浏览器
page = browser.new_page()
page.goto('https://www.baidu.com')
print(f"✅ 页面标题:{page.title()}")
browser.close()
如果能看到浏览器弹出并打开百度,说明安装成功!🎉
📖 基础操作:打开页面
最简单的例子
python
from playwright.sync_api import sync_playwright
def crawl_with_playwright(url):
"""用 Playwright 打开页面"""
with sync_playwright() as p:
# 1. 启动浏览器
browser = p.chromium.launch(headless=True) # headless=True 无界面运行
# 2. 创建新页面(标签页)
page = browser.new_page()
# 3. 打开目标 URL
page.goto(url)
# 4. 获取页面标题
title = page.title()
print(f"📄 页面标题:{title}")
# 5. 关闭浏览器
browser.close()
# 使用
crawl_with_playwright('https://example.com')
代码解析
python
# headless=True # 无头模式(不显示浏览器窗口,适合服务器)
# headless=False # 有头模式(显示浏览器,适合调试)
browser = p.chromium.launch(
headless=True,
slow_mo=100 # 每个操作延迟 100ms(方便观察,调试时用)
)
⏳ 核心难点:等待策略
动态网站最大的坑就是加载时机不确定。你刚打开页面,数据可能还没渲染出来,就开始提取内容------结果一片空白。
Playwright 提供了多种等待策略:
策略 1:等待页面加载完成(load)
python
page.goto(url, wait_until='load') # 等待 load 事件(默认)
适用场景:传统网站,数据在 HTML 里。
缺点:Ajax 请求可能还在进行中。
策略 2:等待网络空闲(networkidle)
python
page.goto(url, wait_until='networkidle') # 等待网络请求结束
适用场景:单页应用(SPA),数据通过 Ajax 加载。
推荐用这个!
策略 3:等待特定元素出现
python
page.goto(url)
page.wait_for_selector('.product-list') # 等待商⭐⭐⭐
策略 4:等待固定时间(不推荐)
python
import time
page.goto(url)
time.sleep(3) # 硬等 3 秒
缺点:不灵活,可能等不够或浪费时间。
仅用于快速测试,生产环境不要用!
📸 实战:截图 + HTML dump
完整示例
python
from playwright.sync_api import sync_playwright
from pathlib import Path
from datetime import datetime
class PlaywrightSpider:
"""基于 Playwright 的爬虫基类"""
def __init__(self, headless=True):
self.headless = headless
self.output_dir = Path('output')
self.output_dir.mkdir(exist_ok=True)
def crawl_page(self, url, wait_selector=None):
"""
采集页面
Args:
url: 目标 URL
wait_selector: 等待的 CSS 选择器(可选)
Returns:
dict: {html, screenshot_path}
"""
with sync_playwright() as p:
browser = p.chromium.launch(headless=self.headless)
page = browser.new_page()
print(f"🔍 正 打开页面(等待网络空闲)
page.goto(url, wait_until='networkidle', timeout=30000)
# 如果指定了等待元素,额外等待
if wait_selector:
print(f"⏳ 等待元素出现:{wait_selector}")
page.wait_for_selector(wait_selector, timeout=10000)
# 生成文件名(带时间戳)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
# 保存截图
screenshot_path = self.output_dir / f"screenshot_{timestamp}.png"
page.screenshot(path=str(screenshot_path), full_page=True)
print(f"📸 截图已保存:{screenshot_path}")
# 获取渲染后的 HTML
html = page.content()
# 保存 HTML
html_path = self.output_dir / f"page_{timestamp}.html"
html_path.write_text(html, encoding='utf-8')
print(f"📄 HTML 已保存:{html_path}")
browser.close()
return {
'html': html,
'screenshot_path': str(screenshot_path),
'html_path': str(html_path)
}
# 使用示态网站
result = spider.crawl_page(
url='https://spa.example.com/products',
wait_selector='.product-list' # 等待商品列表出现
)
print(f"\n✅ 采集完成!")
print(f" HTML 长度:{len(result['html'])} 字符")
print(f" 截图路径:{result['screenshot_path']}")
🎨 调试技巧
技巧 1:有头模式 + 慢动作
python
browser = p.chromium.launch(
headless=False, # 显示浏览器
slow_mo=500 # 每个操作延迟 500ms
)
你能看到浏览器的每一步操作,方便排查问题。
技巧 2:截图是最好的调试工具
不确定页面加载到哪一步?截个图看看:
python
page.screenshot(path='debug.png')
print("📸 调试截图已保存,去看看加载成功了吗")
技巧 3:打印 HTML 长度判断
python
html = page.content()
print(f"📊 HTML 长度:{len(html)} 字符")
# 如果长度太短(如 < 1000),说明加载失败
if len(html) < 1000:
print("⚠️ 页面可能没加载完,检查等待策略")
⚠️ 新手常见坑
坑 1:没有等待就提取内容
现象HTML 是空的或不完整。
原因:页面还在加载,JS 还没执行完。
解决:
python
# ❌ 错误
page.goto(url)
html = page.content() # 可能太早了
# ✅ 正确
page.goto(url, wait_until='networkidle')
page.wait_for_selector('.data-container') # 双保险
html = page.content()
坑 2:超时设置不合理
现象:程序卡住不动,或者报 TimeoutError。
原因:网络慢或页面加载慢。
解决:
python
# 调局超时
page.set_default_timeout(60000) # 60 秒
# 或者针对单个操作
page.goto(url, timeout=60000)
page.wait_for_selector('.content', timeout=30000)
坑 3:忘记关闭浏览器
现象:内存占用越来越高,浏览器进程越来越多。
解决:
python
# ❌ 忘记关闭
browser = p.chromium.launch()
page = browser.new_page()
# ... 采集完就跑了,浏览器还开着
# ✅ 用 with 语句自动管理
with sync_playwright() as p:
browser = p.chromium.launch()
# ... 代码块结束自动关闭
或者手动:
python
try:
browser = p.chromium.launch()
# ... 采集逻辑
finally:
browser.close() # 确保关闭
📊 性能优化
优化 1:禁用图片/CSS(提速)
如果只要数据不要样式,可以禁用资源加载:
python
context = browser.new_context()
page = context.new_page()
# 拦截请求,屏蔽图片和样式
page.route("**/*.{png,jpg,jpeg,gif,svg,css}", lambda route: route.abort())
page.goto(url)
速度能提升 30%-50%!
优化 2:复用浏览器实例
不要每次采集都启动新浏览器,太慢了:
python
class PlaywrightSpider:
def __init__(self):
self.playwright = sync_playwright().start()
self.browser = self.playwright.chromium.launch(headless=True)
def crawl(self, url):
page = self.browser.new_page() # 复用浏览器,只开新标签
page.goto(url)
html = page.content()
page.close()
return html
def __del__(self):
self.pip install + playwright install)
- 打开页面(goto + 等待策略)
- 等待加载(networkidle + wait_for_selector)
- 保存结果(截图 + HTML dump)
记住核心原则:等待策略很关键,截图是最好的调试工具。遇到问题先截个图,90% 的情况能看出问题在哪。
🎯 下期预告
今天我们学会了"打开页面",但真实场景往往更复杂:商品列表有 200 条,需要点击"加载更多"按钮 10 次;新闻网站要滚动到底部才会触发下一页加载。
下一篇《动态列表:滚动加载/点击翻页(通用套路)》,我们会搞定滚动翻页 和点击翻页两大经典场景,让你能采集任何动态列表!
验收作业:用 Playwright 打开一个动态网站(如某电商或新闻站),保存截图和 HTML。把文件发我看看!加油!
🌟 文末
好啦~以上就是本期 《Python爬虫实战》的全部内容啦!如果你在实践过程中遇到任何疑问,欢迎在评论区留言交流,我看到都会尽量回复~咱们下期见!
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦~
三连就是对我写作道路上最好的鼓励与支持! ❤️🔥
📌 专栏持续更新中|建议收藏 + 订阅
专栏 👉 《Python爬虫实战》,我会按照"入门 → 进阶 → 工程化 → 项目落地"的路线持续更新,争取让每一篇都做到:
✅ 讲得清楚(原理)|✅ 跑得起来(代码)|✅ 用得上(场景)|✅ 扛得住(工程化)
📣 想系统提升的小伙伴:强烈建议先订阅专栏,再按目录顺序学习,效率会高很多~

✅ 互动征集
想让我把【某站点/某反爬/某验证码/某分布式方案】写成专栏实战?
评论区留言告诉我你的需求,我会优先安排更新 ✅
⭐️ 若喜欢我,就请关注我叭~(更新不迷路)
⭐️ 若对你有用,就请点赞支持一下叭~(给我一点点动力)
⭐️ 若有疑问,就请评论留言告诉我叭~(我会补坑 & 更新迭代)
免责声明:本文仅用于学习与技术研究,请在合法合规、遵守站点规则与 Robots 协议的前提下使用相关技术。严禁将技术用于任何非法用途或侵害他人权益的行为。