requests 抓不到数据?用 Playwright 爬虫轻松搞定 JS 动态渲染

🕷️ 经典场景:你用 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))
设置真实 viewportnew_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

Leave a Comment

Your email address will not be published. Required fields are marked *