Node.js网页抓取:配置Axios响应为UTF-8解决西班牙语乱码
解决Node.js抓取墨西哥谷歌搜索结果的ISO-8859-1乱码问题
问题核心
你遇到的乱码是因为谷歌墨西哥站强制返回ISO-8859-1编码的内容,而你设置的Content-Type请求头完全无效——这个头是告诉服务器你发送的请求内容类型,和服务器返回的响应编码无关,所以服务器根本不会理会这个设置。
解决方案
核心思路是手动将ISO-8859-1编码的二进制响应转换为UTF-8字符串,再交给Cheerio处理。可以用Node原生Buffer或iconv-lite库实现,后者兼容性更好。
步骤1:安装依赖(可选,用原生Buffer可跳过)
如果选择iconv-lite,先安装:
npm install iconv-lite
步骤2:修改代码
以下是修复后的完整代码,优化了异步写法并解决编码问题:
const axios = require("axios"); const cheerio = require("cheerio"); const fs = require("fs"); const iconv = require("iconv-lite"); // 若用原生Buffer可移除这行 async function scrape(req, res) { try { const query = req.params.query; const encodedQuery = encodeURIComponent(query); const numResults = 10; const url = `https://www.google.com.mx/search?q=${encodedQuery}&start=${numResults}`; // 请求时指定返回二进制数据,避免Axios自动转码出错 const response = await axios.get(url, { responseType: "arraybuffer", headers: { "Accept-Charset": "utf-8" // 尝试请求UTF-8,谷歌可能忽略但符合规范 } }); console.log(response.headers['content-type']); // 仍会显示ISO-8859-1,属于正常现象 // 方法1:用iconv-lite转码(推荐) const html = iconv.decode(Buffer.from(response.data), "ISO-8859-1"); // 方法2:用Node原生Buffer转码(无需额外依赖) // const html = Buffer.from(response.data).toString('latin1'); const $ = cheerio.load(html, { decodeEntities: false }); const data = [...$(".egMi0")].map(e => ({ title: $(e).find("h3").text().trim(), href: $(e).find("a").attr("href"), })); console.log(data); // 保存文件时指定UTF-8编码,避免本地文件乱码 fs.writeFileSync("test.html", html, "utf8"); res.status(200).json({ message: "Scraping successful", output: data.length, results: data }); } catch (error) { console.error('Error while scraping website:', error.message); res.status(500).json({ message: "Error while scraping website. Contact support.", error: error.message }); } } module.exports = { scrape };
关键修复点
- 移除无效的
Content-Type请求头,替换为Accept-Charset尝试请求UTF-8 - 将二进制响应数据手动从ISO-8859-1转码为UTF-8字符串
- 保存文件时指定UTF-8编码,避免本地存储乱码
- 优化异步逻辑,使用纯
async/await替代混合写法
内容的提问来源于stack exchange,提问作者La Bola Al Riel
相关产品推荐
相关产品推荐

