求助:Axios+Cheerio爬取ISO-8859-1编码网页乱码问题
解决ISO-8859-1编码网页爬取后的字符乱码问题
我是法国人,英语表达可能不够地道,还请见谅。我是一名角色扮演玩家,需要爬取采用ISO-8859-1编码的网页http://www.gemmaline.com/sorts/liste-classe-pretre.htm,提取每个列表文本,后续还要从列表名称对应的链接抓取各类信息。
原本用Google Sheet的IMPORTXML公式爬取,但它最多支持50次请求,速度还极慢,所以改用JavaScript+Node.js,用Axios和Cheerio实现。代码能正常运行,但爬取结果里带重音的字符和单引号都显示异常。
我的代码:
const PORT = 8000 const axios = require('axios') const cheerio = require('cheerio') const express = require('express') const fs = require('fs') const app = express() const url = 'http://www.gemmaline.com/sorts/liste-classe-pretre.htm' axios(url) .then(response => { const html = response.data const $ = cheerio.load(html) const data = [] $('body:nth-child(2) ul li').each(function() { //const encoder = new TextEncoder() //const name = new TextDecoder().decode(new Uint8Array(encoder.encode($(this).text()))) const name = $(this).text() const url = $(this).find('a').attr('href') data.push({ name, url}) }) fs.writeFileSync('test.json', JSON.stringify(data, null, 1)) }).catch(err => console.log(err)) app.listen(PORT, ()=>console.log(`server running on port ${PORT}`))
异常结果:

可以看到出现了奇怪的符号,求解决方法。
解决方案:
问题出在Axios默认会把响应按UTF-8解析,但目标网页是ISO-8859-1编码,导致字符解码错误。需要让Axios返回原始二进制数据,再手动用ISO-8859-1解码:
修改Axios请求配置,添加responseType: 'arraybuffer',然后用TextDecoder解码成正确的字符串:
const PORT = 8000 const axios = require('axios') const cheerio = require('cheerio') const express = require('express') const fs = require('fs') const app = express() const url = 'http://www.gemmaline.com/sorts/liste-classe-pretre.htm' axios(url, { responseType: 'arraybuffer' }) // 关键配置:返回二进制数据 .then(response => { // 用ISO-8859-1解码二进制数据 const html = new TextDecoder('ISO-8859-1').decode(response.data) const $ = cheerio.load(html) const data = [] $('body:nth-child(2) ul li').each(function() { const name = $(this).text() const url = $(this).find('a').attr('href') data.push({ name, url}) }) fs.writeFileSync('test.json', JSON.stringify(data, null, 1)) }).catch(err => console.log(err)) app.listen(PORT, ()=>console.log(`server running on port ${PORT}`))
原理说明:
responseType: 'arraybuffer'让Axios不自动解析响应,保留原始的二进制字节流TextDecoder('ISO-8859-1')用目标网页的编码来解码字节,这样带重音的字符就能正确显示了
内容的提问来源于stack exchange,提问作者LaCerise
相关产品推荐
相关产品推荐

