時間:2021年4月1號,文中各版本號以該時間為背景
問題一、網頁採用gb2312編碼,爬取後中文全部亂碼
環境:node@8.12.0,cheerio@0.22.0
網站使用的gb2312編碼,開始用http直接訪問網頁,cheerio加載後console出來中文全部亂碼:
const http = require('http')
const cheerio = require('cheerio')
const baseUrl = '******'
http.get(baseUrl, res => {
let html = ''
res.on('data', data => {
html += data
})
res.on('end', () => {
downloadHandler(html)
})
}).on('error', () => {
console.log('出錯了')
})
function downloadHandler(html) {
const $ = cheerio.load(html) // 默認解析
console.log($.html());
}
cheerio解析:
不解析:
function downloadHandler(html) {
const $ = cheerio.load(html,{ decodeEntities: false }) // 不解析
console.log($.html());
}
原因:Node不支持gb2312
解決:使用superagent取代http,同時使用superagent-charset解決編碼問題
const request = require('superagent')
require('superagent-charset')(request)
const cheerio = require('cheerio')
const baseUrl = '******'
request.get(baseUrl)
.buffer(true)
.charset('gbk')
.end((err, html) => {
downloadHandler(html)
})
function downloadHandler(html) {
const htmlText = html.text
const $ = cheerio.load(htmlText,{ decodeEntities: false })
}
問題二、一個循環內部,每次循環都會有一個異步請求;循環外部需要等內部所有請求返回結果後再執行
解決:
const idList = [1,2,3,4]
getData(idList).then(data => {
// get data
})
function getData(idList) {
let asyncPool = idList.map(id => {
return new Promise((resolve,reject) => {
request.get(`http://detail/${id}`)
.then(html => {
return resolve(html)
})
})
})
return Promise.all(asyncPool).then(data => {
return data
})
}
問題三、運行puppeteer報錯:unexpected token {
環境:node@8.12.0,npm@6
原因:node版本過低
解決:升級node版本至最新穩定版14.16.0,重新安裝puppeteer
問題四、運行puppeteer報錯:could not find expected browser
環境:node@14.16.0,npm@6
升級好node,重新安裝puppeteer。我親眼看見他下載了版本號好像是865什麼的chromium,然後運行代碼puppeteer又報錯説在本地找不到865版本的瀏覽器(明明剛才下載了,且版本號一致)。
最終在官方issues裏找到了可能的答案:
https://github.com/puppeteer/puppeteer/issues/6586
原因:npm版本問題。貌似是npm6下載puppeteer時,實際下載的瀏覽器版本和puppeteer需要的並不一致
解決:升級npm至7,重新安裝puppeteer,正常運行
問題五、升級node後,cheerio無法正常運行,報錯:content.forEach() is not a function
環境:node@14.16.0,npm@7,cheerio@v1.0.0-rc5
升級了node和npm至最新穩定版後,把之前的包也全部重新安裝了一遍
cheerio突然一直報錯無法運行,之前是正常的。
還是在官方issues裏找到了答案:
https://github.com/cheeriojs/cheerio/issues/1591
原因:cheerio版本問題
Cheerio.load expects there to be array. Older versions was there condition for checking, if it is not array. Seems like it is lost due to optimizations.
older version wraps it into array