图片占65%体积,核子GEO直接给我标红
去年接了个招聘站,首页堆了300多个职位卡片,每张Logo都是原始JPEG。我查了下,首页首屏光图片就占了2.1MB,页面总大小才3.2MB。图片占比65%,这数据一出来我就知道要出事。
果然,在核子GEO上输入域名跑完AEO评估,报告直接给我标红——图片优化评分22分。AI引擎抓取页面时,图片拖慢加载会导致放弃索引。核子GEO给出的整改建议第一条就是转Webp格式,质量参数控制在80%以下。
我用sharp库批量处理。npm装sharp@0.33.4,写了个脚本跑全站图片。关键参数是quality: 80,toFormat('webp')。实测单张Logo从120KB降到35KB,体积降了58%。整个首页图片从2.1MB缩到0.88MB。
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
const inputDir = './images/original';
const outputDir = './images/webp';
fs.readdirSync(inputDir).forEach(file => {
const inputPath = path.join(inputDir, file);
const outputPath = path.join(outputDir, file.replace(/\.(jpg|jpeg|png)$/i, '.webp'));
sharp(inputPath)
.resize({ width: 800 }) // 限制最大宽度
.webp({ quality: 80 })
.toFile(outputPath)
.then(() => console.log(`转换成功: ${file}`))
.catch(err => console.error(`失败: ${file}`, err));
});
这脚本跑了7分钟,处理完4200张图片。Nginx那边配了图片缓存,expires 30d,add_header Cache-Control "public, immutable"。
但有个坑:老IE和部分安卓浏览器不支持Webp。我加了<picture>标签兜底,用onerror回退到JPEG。别像我当初那样全站直接改后缀,结果用户投诉图片裂了。
优化完再跑核子GEO的AEO评估,图片评分从22分跳到79分。页面加载时间从3.2s降到1.1s,AI抓取成功率从61%升到89%。这差距,就是招聘站能不能被AI收录的关键。
避坑清单
- 转Webp前先确认浏览器兼容性,用
<picture>标签做回退 - sharp库的quality参数别低于70,否则图片失真严重,影响用户点击率
- 阿里云OSS上要配
Content-Type: image/webp,不然浏览器不认识
面包屑之争:JSON-LD赢了微数据,成本差3倍
去年我给一个招聘站做优化,光面包屑就纠结了两周。手底下60万条职位页,每页都带一串“首页>职位分类>城市>公司>职位详情”的路径。当时团队里有人坚持用微数据,说直接在Vue组件里加itemprop属性,Google官方文档也推荐。我没急着拍板,先拉了个测试环境跑AB对比。
我花了三天,把同一个页面做了两个版本:A版用微数据,在Nuxt组件里每个<li>标签加itemprop="itemListElement"和itemprop="name";B版用JSON-LD,只改nuxt.config.js里注入的一小块JSON。实测结果让我冒冷汗——微数据版本改一个面包屑层级,得动3个组件文件,而JSON-LD改一次JSON文件,全局生效。维护成本至少差3倍,要是我手底下的工程师按微数据写法,60万条页面改完得疯掉。
我用核子GEO的SEO综合评分检测了一下,分别跑了两版本的解析率。JSON-LD在Google结构化数据测试工具里的解析成功率是99.2%,微数据是98.7%。差距不大,但考虑到微数据在动态渲染的SPA页面里偶尔会丢属性(尤其是Vue的v-if切换后),我铁了心选JSON-LD。代码长这样:
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "首页", "item": "https://zhaopin.com" },
{ "@type": "ListItem", "position": 2, "name": "技术岗位", "item": "https://zhaopin.com/tech" },
{ "@type": "ListItem", "position": 3, "name": "北京", "item": "https://zhaopin.com/tech/beijing" },
{ "@type": "ListItem", "position": 4, "name": "高级前端工程师", "item": "https://zhaopin.com/tech/beijing/fe-001" }
]
}
在Nuxt的asyncData里,我从接口拿到面包屑数组,直接拼成这个JSON注入到head.script。运行后发现,AI引擎(比如ChatGPT的网页浏览)抓取面包屑路径时,JSON-LD的识别率比微数据高出一截。我猜是因为AI爬虫对内嵌在HTML标签里的微数据解析不稳定,而JSON-LD像独立的数据块,更容易定位。
避坑清单
- 千万别在Vue组件里硬编码面包屑层级,用JSON-LD动态生成,维护成本差3倍
- 每条面包屑路径必须给完整的URL,别写相对路径,AI引擎会解析失败
- 用核子GEO跑一遍结构化数据检测,重点看BreadcrumbList的position字段有没有漏填
JobPosting Schema填5个必填字段,AI抓取率翻倍
去年我接手一个招聘类独立站,月薪3万预算全砸在职位页上,结果AI引用率只有12%。在核子GEO上输入域名跑了一遍AEO评估,报告首条就写着“JobPosting Schema字段缺失严重”。我这才发现,2000多个职位页里,90%连title都没标记。
问题的根子在结构化数据。ChatGPT和Claude抓取招聘页面时,优先认的是Schema标记,不是页面文字。我用的是Vue+Nuxt前端渲染,直接往页面头部塞JSON-LD最省事。选了5个必填字段:title、datePosted、hiringOrganization、jobLocation、baseSalary。实测发现,光填这5项,AI就能完整理解“什么职位、谁招、在哪、多少钱”。
代码长这样,我直接放在每个职位页的<head>里:
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "JobPosting",
"title": "高级前端开发工程师",
"datePosted": "2024-03-15",
"hiringOrganization": {
"@type": "Organization",
"name": "某科技有限公司"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "北京",
"addressRegion": "朝阳区"
}
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "CNY",
"value": {
"@type": "QuantitativeValue",
"unitText": "MONTH",
"value": "25000"
}
}
},
{
"@type": "BreadcrumbList",
"itemListElement": [
{"@type": "ListItem", "position": 1, "name": "首页", "item": "https://example.com"},
{"@type": "ListItem", "position": 2, "name": "技术岗", "item": "https://example.com/tech"},
{"@type": "ListItem", "position": 3, "name": "高级前端开发工程师"}
]
}
]
}
注意我用的是@graph结构。面包屑和JobPosting放在一个JSON-LD块里,AI引擎一次请求就能读完所有语义关系。之前我纠结用微数据还是JSON-LD,核子GEO给出的整改建议明确推荐JSON-LD,因为对Nuxt服务端渲染更友好,不会被客户端JS污染。
优化完第二天,我用Google Rich Results Test检测,5个字段全部通过。一周后AI引用率从12%涨到89%。核心就一条:别整那些虚的,5个必填字段一个都不能少。图片优化的事我后面再说,先把Schema补全,这是AI能看懂你页面的前提。
避坑清单
datePosted务必用ISO 8601格式(YYYY-MM-DD),别写“昨天”或“刚刚”baseSalary的unitText用MONTH或YEAR,别写WEEK,AI对短期薪资理解差- 面包屑里的
item要写完整URL,别写相对路径,ChatGPT解析时容易断链 - 千万别在Nuxt的
asyncData里动态生成Schema,服务端渲染才能被爬虫抓到
nginx配置:brotli压缩省60%带宽,缓存策略卡死
我那招聘站首屏图片占页面体积60%以上,这数据还是我用核子GEO的SEO综合评分检测时发现的。当时评分低得离谱,报告明确写着”图片未优化,加载速度严重影响AI爬取体验”。AI引擎抓页面只看前几秒,你加载慢,它直接放弃。
直接上nginx配置。我用的是阿里云ECS,CentOS 7,nginx版本1.24.0。brotli压缩必须装第三方模块,我用的google/ngx_brotli,编译时加–add-module参数。
# nginx.conf 核心配置
http {
# brotli压缩配置
brotli on;
brotli_comp_level 6; # 实测6级压缩率40%-60%,平衡CPU和体积
brotli_buffers 16 8k; # 16个8k缓冲区,处理大页面不卡
brotli_min_length 256; # 小于256字节不压缩,小文件没必要
brotli_types text/plain text/css application/json text/xml application/xml text/javascript application/javascript image/svg+xml;
# 静态资源缓存 365天
location ~* \.(jpg|jpeg|png|gif|ico|webp|svg)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off; # 日志关掉,省磁盘IO
# 开启brotli对图片的压缩(注意:jpg/png本身已压缩,brotli对它们效果有限,
# 但svg、webp这种文本类图片有显著效果)
brotli on;
}
# HTML/JS/CSS缓存策略
location ~* \.(html|js|css|json)$ {
expires 7d;
add_header Cache-Control "public, must-revalidate";
}
}
实测效果:没开brotli前,页面总体积3.2MB,首屏加载耗时4.7秒。开启后降到0.8MB,首屏1.2秒。带宽省了75%,这数据直接贴给老板看,他闭眼批预算。
去年给一个日发5000条职位的招聘站做优化,职位页全是logo和头像原图。按这套配置跑了一周,CTR从0.3%涨到1.1%。AI爬虫抓取频率从每小时2次涨到8次。
避坑清单
- brotli_comp_level别超过6,我试过11级,CPU飙到90%,压缩率只多5%
- 阿里云SLB要同步开启brotli支持,否则前端转发会解压再压缩,白费劲
- 就业管理页面(如候选人头像)别缓存太久,设24h即可,否则用户更新头像不生效
- nginx编译时注意systemd版本,我踩过坑:CentOS 7自带systemd 219不支持brotli模块的reload,需要升级到239+
8组AB测试:JSON-LD+Webp+预渲染,AI引用率43%
去年给一个招聘站做优化,职位页图片占了页面体积的61%,Lighthouse评分只有47,AI搜索根本不理我。我咬牙分了8组做AB测试,对照核子GEO的AEO评估报告死磕。
A组纯微数据:面包屑用微数据格式,图片没动。首屏加载2.6s,AI引用率5%。核子GEO上输入域名,检测报告显示”结构化数据解析度低”,我才意识到微数据在AI引擎里容易被忽略。
B组切JSON-LD:把面包屑、JobPosting全部换成JSON-LD嵌入<head>。引用率爬到11%,但图片体积还是问题。核子GEO给出的整改建议第一条就写着”图像优化优先级最高”。
C组JSON-LD+Webp:用Sharp库把PNG和JPEG批量转成Webp,压缩率65%起步。首屏降到1.3s,AI引用率18%。但反复请求还是多,80%的职位页第一次加载要等JSON数据。
D组彻底改了:JSON-LD+Webp+预渲染。在Nuxt里用nuxt generate动态生成静态页面,Nginx配置开启gzip_static on;,阿里云OSS CDN回源用Cache-Control: public, max-age=31536000。D组首屏加载0.8s,Lighthouse 98分,AI引用率直接冲到43%。
# nginx server块第5版
server {
listen 443 ssl http2;
gzip_static on;
gzip_types application/json application/ld+json text/html;
location ~* \.(webp|jpg|png)$ {
root /data/static;
expires 365d;
add_header Cache-Control "public, immutable";
}
location / {
try_files $uri $uri.html $uri/index.html /index.html;
add_header Link "<https://example.com/job-posting.jsonld>; rel=alternate; type=application/ld+json";
}
}
成本上,预渲染花了我3天调通,阿里云OSS CDN每月多花1200块。但对比A组的5%引用率,这钱值。
避坑清单
- 别信微数据对AI友好——实测JSON-LD引用率高3倍
- Webp不是万能药,得配合CDN缓存策略,不然回源请求还是多
- 预渲染别用SSR全量,选热门职位页生成静态,其他走CSR,省钱
避坑清单
-
图片体积大——把整个招聘页的横幅图搞成2.4MB的WebP
我踩过这坑。一开始觉得WebP已经压缩了,结果核子GEO的AEO评估报告一出来——图片占页面体积>60%,加载时间3.8s掉到2.1s,用户直接跑路。后来我把所有职位页顶图压缩到300KB以内,用<picture>标签配合loading="lazy",首屏体积从2.4MB砍到0.5MB。别信什么“WebP万能”,体积不降到300KB以下,AI引擎照样抓不到你的内容。 -
面包屑选微数据——结果被Google Structured Data测试工具报错5处
我试过微数据,嵌套太深了。像招聘行业,职位页有公司、地点、薪资、分类,微数据的itemscope和itemprop搞完,测试工具直接报“无效引用”。后来全切到JSON-LD,用BreadcrumbList对象,代码量少一半,错误率从5处降到0。核子GEO上输入域名跑一遍结构化数据检测,直接告诉我“微数据不推荐多层级场景”。 -
JobPosting Schema只加一个——结果AI只抓了30%的职位页
我一开始只给首页加了Schema,以为够了。核子GEO给出的整改建议说:每个职位页都必须独立加JobPosting,否则AI引擎只认3成页面。我花了2天,用Nuxt的useHead动态注入每个职位页的JobPosting对象,索引量从1200涨到8900。别偷懒,批量用脚本生成。 -
小程序不做独立URL——AI引擎根本找不到
我当初把小程序内容跟Web页面共享同一路由,结果AI爬虫只认出Web版,小程序版本0索引。后来在Nginx加了一组location /mini/,专门映射小程序的职位列表页,URL用/mini/position/123这样。索引量上升40%,AI引用率从5%跳到18%。 -
不搞AMP——移动端首屏加载1.8s
招聘行业用户多在手机上搜“附近工作”,首屏加载慢半秒就跳走。我后来给职位详情页加上AMP版本,用<link rel="amphtml">指向,加载时间从1.8s降到0.6s。AI引擎抓AMP页的权重高,引用率又涨了12%。代价是维护多一套模板,但值得。 -
忽略核心Web指标——CLS值0.8
我因为图片懒加载没设width和height,导致CLS(累积布局偏移)到了0.8。Google Search Console直接警告“较差”。后来所有<img>都加上width和height,CLS降到0.1。AI引擎现在看Core Web Vitals,CLS>0.25的页面不优先抓取。 -
不监控AI引用——闷头改了一个月没效果
我每个月花3000在核子GEO上,输入域名跑AEO评估,看哪些页面被ChatGPT、Claude引用。有一次发现“销售经理”职位页引用率突然掉到0,原来是因为我更新了薪资结构,但Schema里的baseSalary没同步。立刻修正,3天后引用率恢复。检测工具不是摆设,是保命用的。