You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高效爬取ADF Page的可行方案咨询 无需启动完整浏览器的实现方法

可行优化方案

方案1:优化现有Puppeteer逻辑(改造成本最低,性能提升最明显)

当前单次15秒的耗时90%以上来自每次请求都重复启动、销毁浏览器实例,调整为复用实例即可将单次参数获取耗时压缩到1秒以内:

  • 全局复用同一个浏览器实例,不要每次调用都执行launch和close
  • 启动时添加轻量化配置,禁用不必要的资源加载:
// 全局初始化一次浏览器即可
let browser: Browser
const initBrowser = async () => {
  browser = await puppeteer.launch({
    headless: 'new', // 新版无头模式性能更高
    args: [
      '--no-sandbox',
      '--disable-dev-shm-usage',
      '--disable-gpu',
      '--blink-settings=imagesEnabled=false', // 禁用图片
      '--disable-stylesheets' // 禁用CSS加载
    ]
  })
}

const sessionParams = async () => {
  if (!browser) await initBrowser()
  const page = await browser.newPage()
  // 不用等全页加载,只要目标输入框出现就取值
  await page.goto('https://sia.unal.edu.co/ServiciosApp/facespublico/public/servicioPublico.jsf?taskflowId=task-flow-AC_CatalogoAsignaturas')
  await page.waitForSelector('input[name="Adf-Window-Id"]')
  
  const params = {
    windowId: await page.$eval('input[name="Adf-Window-Id"]', input => input.value),
    viewState: await page.$eval('input[name="javax.faces.ViewState"]', input => input.value),
    // 把当前页面的Cookie也一起返回,后续POST请求要携带同一份Cookie参数才有效
    cookies: await page.cookies()
  }
  await page.close()
  return params
}
  • 额外可加参数缓存逻辑:在参数有效期内(通常和会话Cookie绑定,有效期10-30分钟)重复使用,不需要每次发起业务请求都重新获取参数。

方案2:逆向前端逻辑,完全摆脱浏览器依赖(性能最优,毫秒级获取参数)

拿到winnoloop是因为ADF Faces的校验逻辑:首次返回的静态HTML里隐藏框默认值就是winnoloop,只有执行了页面附带的JS初始化逻辑后,才会替换成合法的Adf-Window-Id和ViewState。
你可以直接提取页面中负责生成这两个参数的JS代码,用Node.js的vm模块直接执行即可,不需要启动任何浏览器实例,单次获取参数耗时仅几十毫秒:

  1. 首次用GET请求拉取页面内容,提取所有<script>标签里的代码和外链JS文件内容
  2. 定位负责修改隐藏输入框值的逻辑,剥离无关代码后直接在Node.js环境运行
  3. 注意GET请求拿到的Cookie要和后续POST请求携带的Cookie保持一致,否则参数会被后端判定为无效。

方案3:轻量JS运行环境替代完整浏览器

如果不想做逆向,也可以用jsdom这类轻量JS运行环境替代Puppeteer,资源占用和执行速度都比完整浏览器好很多:

import { JSDOM } from 'jsdom'
import fetch from 'node-fetch'

const sessionParams = async () => {
  const res = await fetch('https://sia.unal.edu.co/ServiciosApp/facespublico/public/servicioPublico.jsf?taskflowId=task-flow-AC_CatalogoAsignaturas')
  const html = await res.text()
  const cookies = res.headers.get('set-cookie')
  
  // 用jsdom加载页面并执行所有JS
  const dom = new JSDOM(html, { runScripts: 'dangerously', resources: 'usable' })
  // 等待JS执行完成后取值
  await new Promise(resolve => setTimeout(resolve, 500))
  const windowId = dom.window.document.querySelector('input[name="Adf-Window-Id"]').value
  const viewState = dom.window.document.querySelector('input[name="javax.faces.ViewState"]').value
  
  return { windowId, viewState, cookies }
}

内容的提问来源于stack exchange,提问作者Rendxn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 21:15:00