Node.js中使用Axios+Cheerio爬取谷歌搜索时CSS选择器失效求助
谷歌搜索爬虫CSS选择器无效、日志无输出的解决方法
你的爬虫核心问题出在反爬拦截和代码配置错误上,导致返回的不是真实搜索结果页面,进而引发选择器失效、日志无输出的情况,以下是具体解决步骤:
1. 添加浏览器请求头,绕过基础反爬
谷歌会通过User-Agent识别非浏览器请求,直接返回人机验证页面,必须添加真实的浏览器请求头:
const 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-Language': 'es-MX,es;q=0.9', 'Referer': 'https://www.google.com.mx/' };
2. 修正搜索结果参数
你代码里的start=${numResults}是错误逻辑:
num才是每页结果数量,比如num=10表示每页10条start是结果偏移量,start=0从第一条开始,start=10从第11条开始
正确的请求URL格式:
`https://www.google.com.mx/search?q=${encodedQuery}&num=${numResults}&start=${startOffset}`
3. 检查返回内容是否为验证页
如果console.log(html)输出包含"人机验证"或"reCAPTCHA"的内容,说明被反爬拦截,此时可以尝试:
- 添加更多请求头(如
Cookie,但需从真实浏览器复制) - 使用代理IP分散请求来源
4. 更新CSS选择器(谷歌页面结构常变更)
你用的.tF2Cxc、.IsZvec等类名可能已失效,需打开谷歌搜索页面F12查看最新结构:
- 结果容器:
.MjjYud - 标题:
h3.LC20lb - 链接:
.yuRUbf a - 描述文本:
.VwiC3b
5. 完善日志排查逻辑
在关键节点添加日志,确认问题出在哪一步:
console.log('响应状态码:', response.status); console.log('HTML内容长度:', html.length); // 验证页长度通常远小于真实结果页 console.log('匹配到的结果数量:', results.length);
修改后的完整代码
const axios = require("axios"); const cheerio = require("cheerio"); async function scrape(req, res) { try { const query = req.params.query; const encodedQuery = encodeURIComponent(query); const numResults = 10; // 每页结果数量 const startOffset = 0; // 从第1条结果开始 // 模拟浏览器请求头 const 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-Language': 'es-MX,es;q=0.9', 'Referer': 'https://www.google.com.mx/' }; const response = await axios.get( `https://www.google.com.mx/search?q=${encodedQuery}&num=${numResults}&start=${startOffset}`, { headers } ); const html = response.data; console.log('响应状态码:', response.status); console.log('HTML内容长度:', html.length); // 最新谷歌搜索结果选择器 const css_identifier_result = ".MjjYud"; const css_identifier_title = "h3.LC20lb"; const css_identifier_link = ".yuRUbf a"; const css_identifier_text = ".VwiC3b"; const $ = cheerio.load(html); const results = $(css_identifier_result); console.log('匹配到的结果数量:', results.length); const output = []; results.each((index, element) => { console.log(`处理第${index + 1}条结果`); const item = { title: $(element).find(css_identifier_title).text().trim(), link: $(element).find(css_identifier_link).attr('href'), text: $(element).find(css_identifier_text).text().trim(), }; output.push(item); }); res.status(200).json({ message: "Scraping successful", output: output, // 返回整理后的结果数组,而非原HTML }); } catch (error) { console.error('错误详情:', error); // 打印完整错误信息,包括响应内容 res.status(500).json({ message: "Error while scraping website. Contact support.", error: error.message, }); } } module.exports = { scrape, };
内容的提问来源于stack exchange,提问作者La Bola Al Riel
相关产品推荐
相关产品推荐

