使用unirest与cheerio爬取谷歌图片解析失败如何解决
谷歌图片爬取解析为空问题修复
问题根因
- 你代码里写的CSS选择器对应的
.vbC6V、.iKjWAf、.mVDMnf、.rg_l、.rg_ic都是谷歌前端构建时生成的随机混淆类名,会随页面版本、访问地区/语言变化,硬编码这类选择器大概率匹配不到任何元素。 - 你请求的是谷歌图片的异步加载接口,返回内容开头会带防XSS的冗余前缀
)]}',直接把原始返回值丢给cheerio加载,会导致DOM解析异常。 - 谷歌图片的原图链接、标题等核心数据,大部分不是直接写在DOM元素的属性里,而是存储在页面内嵌的
AF_initDataCallback脚本块的JSON结构中,单纯靠DOM遍历拿不到完整数据。 - 部分图片的src属性是懒加载的,初始HTML里不会直接写入真实地址,存在
data-src等自定义属性里,直接找src会拿空值。
修复代码
首先处理返回内容的冗余前缀,再优先从内嵌JSON提取稳定数据,备选方案用无混淆的属性选择器匹配DOM:
const unirest = require("unirest"); const cheerio = require("cheerio"); const getData = async() => { const url = "https://www.google.com/search?q=india&oq=india&tbm=isch&asearch=ichunk&async=_id:rg_s,_pms:s,_fmt:pc&sourceid=chrome&ie=UTF-8"; const response = await unirest .get(url) .headers({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", }) .proxy("proxy"); // 第一步:清理异步接口返回的冗余前缀 let htmlContent = response.body; if (htmlContent.startsWith(")]}'")) { htmlContent = htmlContent.replace(/^\)\]\}'\n/, ''); } const $ = cheerio.load(htmlContent); // 方案1:优先从内嵌JSON提取,稳定性最高 const imageList = []; $('script').each((_, el) => { const scriptText = $(el).html(); if (!scriptText || !scriptText.includes('AF_initDataCallback')) return; const matchRes = scriptText.match(/AF_initDataCallback\(([\s\S]*?)\);/); if (!matchRes) return; try { const dataBlock = JSON.parse(matchRes[1]); // 定位图片数据所在的数组节点 const imgItems = dataBlock?.data?.[31]?.[0]?.[12]?.[2]?.data || []; imgItems.forEach(item => { if (item?.[1]?.[3]) { imageList.push({ title: item[1][9]?.[2003]?.[3] || item[1]?.[3]?.[12] || '', thumbnail: item[1][2]?.[0] || '', originalUrl: item[1][3]?.[0] || '' }) } }) } catch (err) { // 跳过解析失败的非目标脚本块 } }) console.log('JSON提取结果:', imageList); // 方案2:DOM提取备选,不用随机混淆类名 let title = [] , link = []; $("img").each((_, el) => { const $img = $(el); const src = $img.attr("src") || $img.attr("data-src"); // 过滤页面logo、图标等非结果图片 if (src && (src.startsWith('data:image') || src.includes('encrypted-tbn0.gstatic.com/images'))) { link.push(src); title.push($img.attr("alt") || ''); } }) console.log('DOM提取结果:', title, link); } getData();
注意事项
谷歌搜索有严格的反爬校验,请求频率过高、代理质量差时会直接返回人机验证页面而非正常搜索结果,这种情况下无论怎么写选择器都拿不到目标数据,需要先确认返回的HTML内容确实是图片搜索结果页,而非验证页。
内容的提问来源于stack exchange,提问作者Jimmy
相关产品推荐
相关产品推荐

