🕷️ 经典场景:你用 requests.get(url) 拿到的 HTML 里,根本没有你想要的数据——只有一堆 <div id="app"></div>。这是因为目标页面用了 JavaScript 动态渲染,而 requests 不执行 JS。这时候,Playwright 就是你需要的工具。
requests 抓不到的根本原因
现代网站大量使用 React、Vue、Angular 等前端框架,页面内容在浏览器执行 JavaScript 后才会渲染出来。requests 只是一个 HTTP 客户端,它拿到的是服务器返回的原始 HTML 字符串,不会运行任何 JS。所以你看到的只是一个空壳页面。
常见的”抓不到”症状包括:返回的 HTML 里只有 <div id="root"> 或 <div id="app">;商品价格、评论列表、搜索结果不在 HTML 中;需要登录后才能看到的内容;以及需要点击”加载更多”才会出现的数据。
Playwright 的解决思路完全不同:它启动一个真实的浏览器(Chromium / Firefox / WebKit),让浏览器完整执行页面的 JS,等内容渲染完毕后再提取数据。对目标网站来说,这和一个真实用户打开浏览器访问没有任何区别。
安装 Playwright
Playwright 提供官方 Python 库,安装分两步:安装 Python 包,然后下载浏览器驱动。
# 第一步:安装 Python 包
pip install playwright
# 第二步:下载浏览器(Chromium / Firefox / WebKit)
playwright install
# 只装 Chromium 节省空间
playwright install chromium安装完成后,Playwright 会把浏览器下载到本地,后续运行不需要系统已安装 Chrome。
最简单的爬虫:同步写法
下面是一个最基础的 Playwright 爬虫,抓取页面标题和指定元素的文本内容:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
# 启动浏览器,headless=True 表示后台运行(不弹出窗口)
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 打开目标页面
page.goto("https://example.com")
# 等待某个元素出现(JS 渲染完成的标志)
page.wait_for_selector("h1")
# 提取文本
title = page.inner_text("h1")
print(title)
# 获取完整渲染后的 HTML
html = page.content()
browser.close() 💡 关键点:wait_for_selector() 是 Playwright 爬虫最重要的一步。它告诉浏览器”等到这个元素出现再继续”,避免在 JS 还没执行完时就抓取空内容。
实战:抓取动态列表数据
以抓取一个商品列表页为例,展示更完整的爬虫写法,包括等待渲染、提取多个元素和处理翻页:
from playwright.sync_api import sync_playwright
import json
def scrape_products(url):
results = []
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
# 设置 User-Agent,模拟真实浏览器
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
)
page = context.new_page()
page.goto(url, wait_until="networkidle") # 等网络请求静止
# 等待商品卡片出现
page.wait_for_selector(".product-card")
# 提取所有商品
cards = page.query_selector_all(".product-card")
for card in cards:
name = card.query_selector(".product-name").inner_text()
price = card.query_selector(".product-price").inner_text()
results.append({"name": name, "price": price})
browser.close()
return results
data = scrape_products("https://your-target-site.com/products")
print(json.dumps(data, ensure_ascii=False, indent=2))处理”加载更多”和无限滚动
很多网站的数据需要点击按钮或向下滚动才会加载。Playwright 可以直接模拟这些操作:
# 点击"加载更多"按钮
while True:
try:
btn = page.query_selector("button.load-more")
if not btn:
break
btn.click()
page.wait_for_timeout(1500) # 等待新内容加载
except:
break
# 无限滚动:模拟滚动到底部
for _ in range(5):
page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
page.wait_for_timeout(2000)反爬应对:几个实用技巧
Playwright 虽然使用真实浏览器,但某些网站仍会检测自动化特征。以下几个配置可以降低被识别的概率:
| 技巧 | 代码示例 |
|---|---|
| 隐藏自动化特征 | context = browser.new_context() 配合 stealth 插件 |
| 设置随机延迟 | page.wait_for_timeout(random.randint(1000,3000)) |
| 设置真实 viewport | new_context(viewport={"width":1366,"height":768}) |
| 有头模式调试 | launch(headless=False) 可视化观察页面行为 |
requests vs Playwright:怎么选?
Playwright 功能强大,但并不是所有场景都需要它。启动浏览器有额外的资源消耗,速度也比纯 HTTP 请求慢。一个简单的原则:先用 requests,遇到 JS 渲染再换 Playwright。
- 静态页面、API 接口 → requests / httpx,速度快、资源少
- JS 动态渲染、需要交互操作 → Playwright
- 需要高并发大规模抓取 → Playwright 异步模式(
async_playwright) - 只是需要渲染,不需要交互 → 也可以考虑 Splash 或直接找背后的 API 接口
🔍 小技巧:抓取前先打开浏览器开发者工具 → Network 面板,刷新页面,找带数据的 XHR / Fetch 请求。很多”JS 渲染”网站其实只是调用了一个 JSON API,直接用 requests 请求那个接口,效率远高于 Playwright。
写在最后
Playwright 是目前 Python 爬虫生态中处理 JS 渲染页面最成熟的方案之一,官方文档完善,选择器支持 CSS 和 XPath,还可以录制操作自动生成代码(playwright codegen),上手门槛并不高。
想了解更多 Python 爬虫实战技巧、工具推荐和开发资源?欢迎访问 Sorabin.com,持续更新对开发者真正有用的内容。
Playwright 官方文档与更多示例可参考:playwright.dev/python

