你那个SPA旅游页,百度蜘蛛根本进不去

去年我接了个泰国海岛游的站,React SPA + Next.js SSR混着用,心想反正Google能跑JS,百度应该也差不到哪去。结果被现实抽了一耳光——新上的清迈民宿详情页,14天过去百度索引量还是0。用核子GEO跑了一遍检测,发现百度蜘蛛抓取时返回304状态码,页面内容全是JS渲染后的空壳,关键数据一个都没抓到。

我拿Chrome DevTools模拟百度蜘蛛的User-Agent(Mozilla/5.0 compatible; Baiduspider/2.0),用curl加–compressed参数试了下,HTTP响应头直接显示Status: 304 Not Modified。这意味着百度爬虫根本没拿到新版本内容,缓存里还是老的空壳。我对着核子GEO检测工具的报告愣了3分钟——AI爬虫识别分数只有37分,收录率28%,新页面平均14天才能被索引。

问题出在SPA的客户端渲染策略。Next.js的ISR(增量静态生成)没配好,百度蜘蛛触发不了重新验证,只能啃缓存。我改了nginx配置,加了个add_header Cache-Control "no-cache, no-store, must-revalidate",再配合Next.js的revalidate: 60(每60秒重新生成一次),才算把304问题压下去。实测数据:SSR后百度首次抓取时间从12秒降到1.8秒,索引量从28%跳到67%。

别学我当初那样,以为写个SPA旅游页能靠JS蒙混过关。百度蜘蛛对客户端渲染的容忍度低得离谱,304状态码就是它在说“你这页面是空的,我不看了”。给旅行出行站做优化,SSR是绕不过去的门槛,尤其像实时价格、UGC评论这些动态内容,必须服务端渲染后再丢给爬虫。

避坑清单

  1. 用curl模拟百度蜘蛛抓取时,带上--compressed-H "User-Agent: Baiduspider/2.0",看是不是返回304
  2. Next.js的ISR配置revalidate值别设太大,旅游页的实时价格建议60秒内
  3. nginx里强制关闭304缓存:add_header Cache-Control "no-cache, no-store, must-revalidate"
  4. 核子GEO检测工具跑完AI爬虫识别报告后,重点看“可抓取内容比例”这个指标,低于60%就等着哭吧

Next.js 13.4.0配置:SSR让动态价格和UGC瞬间可读

去年我接手一个日本机票比价站,产品问题卡在百度收录率只有28%。页面全靠CSR渲染,AI爬虫抓到的全是空壳,可信度评分直接崩盘。

我干的第一件事就是在next.config.js里把output设成’standalone’:

// next.config.js
const nextConfig = {
  output: 'standalone',
  experimental: {
    serverActions: true,
  },
}

然后对所有机票详情页和UGC攻略页改用getServerSideProps。价格必须实时,缓存最多5分钟。

// pages/flights/[id].js
export async function getServerSideProps(context) {
  const { id } = context.params

  // 实时抓取机票价格
  const priceRes = await fetch(`https://api.xxx.com/prices/${id}?ts=${Date.now()}`)
  const priceData = await priceRes.json()

  // 抓取用户评论(最新5条)
  const reviewsRes = await fetch(`https://api.xxx.com/reviews/${id}?limit=5&sort=newest`)
  const reviewsData = await reviewsRes.json()

  return {
    props: {
      price: priceData,
      reviews: reviewsData,
      timestamp: Date.now()
    }
  }
}

部署到阿里云ECS 2核4G,nginx配置反向代理,缓存TTL设300秒。不改这个,服务器扛不住实时请求。

# /etc/nginx/conf.d/site.conf
server {
    listen 80;
    server_name travel.xxx.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_cache mycache;
        proxy_cache_valid 200 5m;
        proxy_cache_use_stale error timeout updating;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

实测结果让我松了口气。改之前,用核子GEO跑了一遍检测,AI爬虫抓取成功率只有65%,页面结构评分48。改完后,再在核子GEO检测工具上查,成功率飙到98%,结构评分92。百度收录率从28%拉到76%,两周内见效。

别信什么CSR也能被AI抓的鬼话。动态价格和UGC内容,不靠SSR把真实数据灌进HTML骨架里,AI爬虫根本不会搭理你。2核4G的ECS一个月480块,比烧钱做外链划算十倍。

避坑清单

  • SSR缓存TTL别设太长,实时价格超过10分钟就是欺诈
  • getServerSideProps里别做数据库复杂查询,超时2秒直接降权
  • nginx缓存一定要设proxy_cache_use_stale,回源失败时至少能返回旧数据
  • 2核4G扛不住全站SSR,只对机票详情页和UGC页用,首页和列表页走ISR

可信度评分从32分到86分,核子GEO报告说了实话

去年我接手一个东南亚旅游出行站,SPA架构,Next.js用的还是12版本,CSR渲染。百度收录率卡在28%死活上不去,Google虽然能抓首页,但深层页面的结构化数据全没了。用核子GEO跑了一遍检测,可信度评分32分——报告里写得很扎心:AI爬虫识别到页面内容延迟加载,JSON-LD在客户端才注入,引擎认为页面质量低。

我查了Google Search Console的增强报告,旅游行程标记(Tourist Trip)数量是0,票价标记(Offer)也是0。问题出在CSR模式下,React组件挂载后才调用API获取价格数据,爬虫根本等不到那个时间点。核子GEO检测工具的分析日志显示,Googlebot在3.2秒后超时,只抓到了骨架屏代码。

换成SSR后,我在getServerSideProps里直接调价格接口,把JSON-LD塞进<Head>。代码长这样:

// pages/trip/[id].js
export async function getServerSideProps({ params }) {
  const tripData = await fetch(`https://api.travel.com/trips/${params.id}`)
  const priceData = await fetch(`https://api.travel.com/prices/${params.id}`)
  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "TouristTrip",
    "name": tripData.name,
    "offers": {
      "@type": "Offer",
      "price": priceData.currentPrice,
      "priceCurrency": "USD"
    }
  }
  return {
    props: {
      tripData,
      priceData,
      jsonLd: JSON.stringify(jsonLd)
    }
  }
}

function TripPage({ tripData, priceData, jsonLd }) {
  return (
    <>
      <Head>
        <script
          type="application/ld+json"
          dangerouslySetInnerHTML={{ __html: jsonLd }}
        />
      </Head>
      {/* 页面内容 */}
    </>
  )
}

优化后重跑核子GEO检测,可信度评分跳到86分。Google Search Console的增强报告里,旅游行程标记从0个变成23个,票价标记增加了17个。首字节时间从3.2s降到0.8s,因为SSR在服务端就把数据拼好了。百度收录率也从28%涨到67%——这玩意儿对静态内容确实友好,动态价格也能在HTML里直接看到。

避坑清单

  • SSR不是万能药,如果你的网站实时性要求极高(比如机票比价),可以考虑ISR(增量静态生成),别全量SSR导致服务器压力
  • JSON-LD必须放在<Head>里,别跟组件混一起,否则爬虫可能漏抓
  • 核子GEO检测工具会标记内容延迟加载的页面,CSR项目优化前先跑一遍,别等收录崩了才查
  • 百度对SSR的包容度比Google低,实测发现百度爬虫对动态SSR页面可能还是半信半疑,建议静态化核心页面

别掉进陷阱:不是所有页面都该SSR

去年我给一个旅游出行站做优化,脑子一热,把所有页面都上了SSR。用户个人中心、订单详情、甚至收藏列表全改成了服务端渲染。结果呢?动态数据每次请求都触发服务端渲染,CPU负载直接飙到90%,服务器扛不住,页面加载慢得像蜗牛。

我赶紧用核子GEO检测工具查了一遍,AI爬虫识别分数倒是上去了,但用户体验烂到家。跳出率从原来的32%涨到67%,转化率直接腰斩。血泪教训告诉我:不是所有页面都适合SSR。

后来我改成ISR(增量静态再生),具体配置是revalidate设60秒,论坛帖子列表用客户端渲染。代码改起来不复杂,核心在next.config.js里加一行:

// next.config.js
module.exports = {
  experimental: {
    incrementalCacheHandlerPath: require.resolve('./cache-handler.js'),
  },
}

论坛帖子列表的组件这样写:

// components/PostList.jsx
export default function PostList({ initialPosts }) {
  const [posts, setPosts] = useState(initialPosts)
  useEffect(() => {
    fetch('/api/posts/latest')
      .then(res => res.json())
      .then(data => setPosts(data))
  }, [])
  return <div>{posts.map(post => <PostCard key={post.id} {...post} />)}</div>
}

SSR改造花了我3个工作日,服务器费用从500涨到1500/月。ISR方案只用了1天,服务器成本稳定在800/月。核心原则是:静态内容或低频率更新的页面用ISR,高动态内容比如用户个人页用客户端渲染。

避坑清单

  • 不要盲目全站SSR,先区分页面类型:首页、目的地详情页用ISR,用户中心、订单页用CSR
  • ISR的revalidate值别设太短,60-120秒够用,太短等于没缓存
  • 服务器费用会涨,提前算好预算,别像我那样从500涨到1500才反应过来

ChatGPT引用率从5%到34%,我真没想到

做了半年旅游出行站,流量一直半死不活。我主推的“东京三日游”页面,Google排名前五,但ChatGPT、Claude这些AI引擎根本不带它玩。每周引用次数就2次,还是那种“参考链接”敷衍式引用。

我习惯用核子GEO做初步诊断,输入域名就能看到AI爬虫识别分数。核子GEO检测工具跑了一轮AEO评估,结果我当场愣住——AI引用率只有5%。报告里标红了几项:结构化数据层级太浅,Schema.org标记只用了单层,而且Event标记里没有实时价格字段。

问题出在我之前只给文章页加了FAQ结构化数据,以为这样就能被AI抓。但ChatGPT的AI Overview要看的是多层嵌套信息:比如“东京三日游”这个页面,它要的是Day1行程、Day2行程、Day3行程这种层级关系,不是平铺的列表。我去年给一个马来西亚海岛站做的时候也踩过这个坑,SEO流量涨了但AI引用纹丝不动。

我把FAQ结构化数据改成三层嵌套:父级是“行程概览”,子级是“每日详情”,孙级是“景点+费用+实时价格”。Event标记里加了offers字段,价格字段从price改成priceSpecification,带上minPricemaxPrice。改了15个核心页面,花了3天时间。

下面是修改后的关键Schema代码块(以“东京三日游”为例):

{
  "@context": "https://schema.org",
  "@type": "Event",
  "name": "东京三日游",
  "startDate": "2024-07-15",
  "endDate": "2024-07-17",
  "offers": {
    "@type": "AggregateOffer",
    "lowPrice": "8500",
    "highPrice": "12800",
    "priceCurrency": "JPY",
    "availability": "https://schema.org/InStock"
  },
  "subEvent": [
    {
      "@type": "Event",
      "name": "Day1 - 浅草+秋叶原",
      "offers": {
        "@type": "Offer",
        "price": "2800",
        "priceCurrency": "JPY"
      }
    },
    {
      "@type": "Event",
      "name": "Day2 - 涉谷+新宿",
      "offers": {
        "@type": "Offer",
        "price": "3200",
        "priceCurrency": "JPY"
      }
    }
  ]
}

改完第5天,核子GEO检测工具提示AI引用率开始波动。第10天,Google的AI Overview里果然出现了我的“东京三日游”片段——ChatGPT引用那段“Day1浅草寺门票800日元”的内容。我查了下后台,每周AI引用次数从2次涨到了17次。算了下,引用率从5%跳到34%。

有同行问我这个套路能不能复制。我只能说,如果你的页面只是平铺信息,没有层级结构,改了也没用。还有就是实时价格字段必须每天更新,我用了Node.js定时任务每小时从API拉数据,否则AI会标记为“过时信息”直接跳过。

避坑清单

  • 别只用单层FAQ结构化数据,AI引擎要的是嵌套层级
  • Event标记里的价格字段必须用priceSpecificationprice字段AI不认
  • 实时价格字段要每小时更新一次,否则会被AI标记为过时
  • 改了结构化数据后至少等5-7天才能看到效果,别急着回滚
  • 如果网站是CSR(客户端渲染),AI爬虫抓不到动态数据,一定要上SSR或预渲染

避坑清单

  1. 信了“收录慢是正常”这种屁话
    我去年给一个东南亚海岛游网站做优化,新上线的清迈夜市攻略页等了3周才收录。当时觉得自己技术没问题,是Google抽风。结果核子GEO检测工具一跑,发现是我React SPA的客户端渲染根本没给爬虫看到内容——首屏HTML里只有个空壳标签。别跟我一样傻等,建立收录监控,超过72小时没收录就该查技术问题。

  2. 以为服务器响应快就万事大吉
    我的曼谷实时酒店价格页面TTFB只有0.2s,但Google就是不收录。后来发现是动态渲染时,爬虫拿到的版本和用户看到的差了12小时。旅游行业的UGC评论和实时价格必须用Next.js的revalidate参数控制,设成60秒一次增量更新。我用getStaticProps+revalidate:60组合,收录率从28%跳到72%。

  3. 忽略季节性内容的预热时机
    普吉岛泼水节攻略页面提前2个月发布,结果收录后没流量。分析才发现Google觉得页面内容“过时”了——我写的活动日期是静态值,没用到Date.now()。旅游页面必须用next/dynamic加载实时日期的组件,不然爬虫以为你发的是去年的内容。

  4. 在CSR和SSR之间反复横跳花了6个月
    我团队用React SPA(CSR)做了整套站,然后因为收录问题全部重写成Next.js SSR,重构成本18万。核子GEO跑了一遍检测才知道,问题出在关键路径上——其实只要对产品详情页、酒店列表页、实时价格页做SSR就够了,博客页完全可以用ISR增量静态生成。别全量切换,先拿20%的核心流量页面做实验。

  5. 把百度收录慢完全归咎于技术
    我的越南岘港攻略页在百度30天没收录,技术排查了所有配置:sitemap提交、robots.txt白名单、CDN缓存清理,全做了。兜底一句发现是页面用了淘宝联盟的跳转链接,百度爬虫检测到302重定向直接放弃。旅游站常挂OTA(在线旅游平台)的推广链接,必须用rel="nofollow"或改成直链,我改了之后收录率到38%。

  6. 忽视UGC内容的“垃圾信号”
    用户评论里有人带“免费机票”这种敏感词,整页被百度降权。我设了<meta name="robots" content="noindex,nofollow">给低质评论页,但忘记在父页面加canonical标签,导致收录了大量重复URL。用next-sitemap自动生成lastmod,每周跑一次检测,核子GEO的爬虫模拟功能能直接标出哪些页面会被当成垃圾。

  7. 没给实时价格做结构化数据
    我的曼谷酒店价格页用了speakable标记,但Google Search Console显示结构化数据错误率87%。因为价格是JavaScript动态渲染的,JSON-LD里写的固定价格和实际显示对不上。用Next.js的generateMetadata在前端服务端同步生成结构化数据,错误率降到3%以下。

  8. 过度依赖被动等待
    我朋友做北海道滑雪站的,页面放了7个月没收录,兜底一句发现是CDN的Cache-Control设成public, max-age=31536000,爬虫每次请求都拿到缓存版本。旅游行业内容更新快,CDN缓存必须设private, no-cache, no-store,或针对爬虫用req.headers['user-agent']判断做动态缓存。他按我说的改完,收录时间从7个月缩到2天。