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

Next.js 13本地可爬取网页,部署到Vercel后抓取失败求助

问题分析与解决方案

核心问题排查

  1. JSON解析错误根源
    你的catch块中返回NextResponse.json(console.error(error)),但console.error()返回的是undefined,这会导致接口返回无效JSON(甚至空内容),客户端解析时就会抛出SyntaxError: Unexpected token 'A'这类错误。

  2. Vercel部署后的反爬拦截
    Costco有反爬机制,Vercel的服务器IP大概率被识别为爬虫,导致fetch请求超时(对应504网关超时)或直接被拒绝(500内部错误),这是本地正常但部署失败的主要原因。

  3. 路径参数处理不严谨
    用req.url.split("scrape_costco/")[1]获取商品编号的方式不可靠,部署后Vercel的URL结构可能带有额外路径或查询参数,导致拆分失败。


分步修复方案

1. 修复错误返回逻辑

把catch块的代码改成正确返回结构化错误信息:

catch (error) {
  console.error(error);
  return NextResponse.json(
    { error: error.message || "Internal Server Error" },
    { status: error.message === "Product not found" ? 404 : 500 }
  );
}

这样客户端能收到标准JSON格式的错误信息,不会出现解析失败。

2. 绕过Costco反爬机制

给fetch请求添加浏览器请求头,模拟正常用户访问:

const res = await fetch(
  `https://www.costco.com/CatalogSearch?dept=All&keyword=${itemNumber}`,
  {
    headers: {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
      "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
      "Accept-Language": "en-US,en;q=0.5",
      "Referer": "https://www.costco.com/",
    },
    // 可选:设置缓存策略,避免重复请求触发反爬
    cache: "no-store"
  }
);

如果添加头后还是被拦截,可以尝试:

  • 启用Vercel的Edge Functions(比Serverless Functions更难被识别)
  • 使用第三方代理服务转发请求(注意合规性)

3. 规范路径参数获取

改用Next.js 13 App Router的动态路由,创建app/api/scrape_costco/[itemNumber]/route.js文件,直接从params获取商品编号:

import { NextResponse } from "next/server";
import { JSDOM } from "jsdom";

export async function GET(req, { params }) {
  const { itemNumber } = params;
  console.log("Item #: ", itemNumber);
  
  try {
    console.log("scraping costco");
    const res = await fetch(
      `https://www.costco.com/CatalogSearch?dept=All&keyword=${itemNumber}`,
      {
        headers: {
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
          "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
          "Accept-Language": "en-US,en;q=0.5",
          "Referer": "https://www.costco.com/",
        },
        cache: "no-store"
      }
    );

    if (!res.ok) throw new Error(`Costco request failed: ${res.status}`);

    const html = await res.text();
    const dom = new JSDOM(html);
    const document = dom.window.document;
    const productName = document.querySelector(".description a")?.textContent;

    if (!productName) throw new Error("Product not found");
    return NextResponse.json(productName.trim());
  } catch (error) {
    console.error(error);
    return NextResponse.json(
      { error: error.message || "Internal Server Error" },
      { status: error.message === "Product not found" ? 404 : 500 }
    );
  }
}

这种方式更可靠,避免URL拆分带来的潜在问题。

4. 额外检查项

  • 确认jsdom已添加到package.json的依赖中(不是devDependencies),部署时Vercel会安装生产依赖
  • 查看Vercel函数日志(Dashboard > Functions > 对应函数),获取更详细的错误信息,比如fetch的具体错误原因

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:03:23