爬虫能看到JS渲染的HTML吗?别被页面效果骗了

打开一个新闻网站,滚动到底部自动加载新文章;点开商品页,价格和库存是异步请求回来的;甚至有些博客首页根本没写死文字,全靠 JS 拼上去——这些你眼睛看到的,爬虫真能“看”到吗?

普通爬虫:只认源码,不等JS

requests、urllib 这类基础工具,发个 GET 请求回来,拿到的就是服务器吐出的原始 HTML 字符串。如果这个 HTML 里只有 <div id="content"></div>,后面所有内容都靠 fetch()axios 加载、再用 JS 插进去,那 requests 看到的就是空盒子。

举个真实例子:某招聘网站职位列表页,源码里就一段占位 <div class="job-list"></div>,真正岗位数据是 JS 调用 API 后动态渲染的。直接用 requests 抓,返回的 HTML 里压根没有职位标题、薪资、公司名。

想让爬虫“看见”JS内容,得换套路

有几种常见解法,看场景选:

1. 直接调用接口(最推荐)

打开浏览器开发者工具(F12),切到 Network → XHR/Fetch,刷新页面,找带数据的请求。比如看到 https://api.xxx.com/jobs?page=1 返回的是 JSON,那就绕过页面,直接请求这个地址。省资源、速度快、稳定性高。

2. 用无头浏览器(比如 Playwright / Puppeteer / Selenium)

它们本质是把浏览器“搬”进代码里,JS 能执行,DOM 能渲染,页面什么样,它就看到什么样。适合必须模拟点击、滑动、登录态等复杂交互的场景。

简单示例(Playwright Python):

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com")
    # 等待 JS 渲染完成
    page.wait_for_selector(".job-item", timeout=10000)
    html = page.content()  # 拿到渲染后的完整 HTML
    print(html)
    browser.close()

3. SSR 或预渲染(网站端配合)

如果你自己开发网站,又希望被搜索引擎或简单爬虫抓取,可以用 Next.js、Nuxt 的服务端渲染,或者用 prerender-spa-plugin 做静态预渲染。这样用户看到的是 JS 动态效果,爬虫拿到的却是提前生成好的完整 HTML。

一个小技巧:快速判断页面是否依赖JS

在浏览器地址栏按 Ctrl+U(或右键→查看网页源代码),搜索关键词,比如你想抓的标题文字。如果搜不到,但页面上明明显示着——那八成就是 JS 渲染的。再打开 F12 → Elements 标签页,这时候看到的是最终 DOM,已经包含 JS 插入的内容,对比下就知道差在哪了。

说白了:爬虫不是人,它不会“等”,也不会“点”,更不会“猜”。它只认服务器最初给的那一口 HTML,或者你明确告诉它去哪拿数据、怎么操作浏览器。看清这点,很多“为啥抓不到”的问题,当场就解开了。