node.js爬蟲實踐
小貓的畢設系統需要一些疾病資料資訊,于是決定從某醫藥網站上爬取相關資料,
小貓以前學爬蟲的時候,用的是python,這次決定用node.js試試,
首先說說用node做一個簡單的爬蟲需要的庫
- request:用于http請求
- iconv-lite:用于轉換字符編碼
- cheerio:用于決議html,
- node-xlsx:將資料生成excel檔案
一個簡單的爬蟲其實就是爬取網頁,決議資料,存盤資料,
小貓使用request獲取網頁,當然也可以選擇其他方式,比如node自帶的http模塊,因為小貓爬取的網頁字符編碼為‘gb2312’,因此使用iconv-lite轉換為utf8,并且需要注意的是使用request不傳encoding欄位時有一個默認編碼,因此需要傳入{encoding: null}的引數去除默認格式iconv-lite才會生效,
const request = require('request');
const iconv = require('iconv-lite');
// 獲得html
const requestPromise = (url)=>{
return new Promise((resolve,reject)=>{
request(url,{encoding: null}, (error, response, body)=>{
if(response.statusCode === 200) {
// 編碼格式轉換 ,{encoding: null}解除默認格式
const bufs = iconv.decode(body, 'gb2312')
const html = bufs.toString('utf8')
resolve(html)
}else {
reject()
}
})
})
}
獲取到html后使用cheerio.load決議html,cheerio.load可以讓使用者通過jquery的方式獲取想要的元素,比如$('.class').text()獲取文字,
將獲取到的資料整理好后,使用node-xlsx的xlsx.build創建一個buffer,最后用node的fs檔案系統寫入檔案,
const cheerio = require('cheerio');
var fs = require('fs');
var xlsx = require('node-xlsx');
// 決議資料
const getData = async(url) =>{
const html = await requestPromise(url)
const $ = cheerio.load(html) // 決議html
// 疾病名稱
var disease = $('body > div.wrap.mt10.clearfix.graydeep > div.main-sub.fl > div.jib-janj.bor.clearfix > div.jib-articl.fr.f14 > div.jib-articl-con.jib-lh-articl > strong').text()
// 存進excel
var buffer = xlsx.build([
{
name:'sheet1',
data:[[disease]]
}
]);
fs.writeFileSync('diseaseData.xlsx',buffer);
}
下面是完整的demo代碼,其中省去了部分資料處理,僅保留一個disease欄位,并且隱去了具體網址,
const request = require('request');
const iconv = require('iconv-lite');
const cheerio = require('cheerio');
var fs = require('fs');
var xlsx = require('node-xlsx');
// 獲得html
const requestPromise = (url)=>{
return new Promise((resolve,reject)=>{
request(url,{encoding: null}, (error, response, body)=>{
if(response.statusCode === 200) {
// 編碼格式轉換 ,{encoding: null}解除默認格式
const bufs = iconv.decode(body, 'gb2312')
const html = bufs.toString('utf8')
resolve(html)
}else {
reject()
}
})
})
}
// 決議資料
const getData = async(url) =>{
const html = await requestPromise(url)
const $ = cheerio.load(html) // 決議html
// 疾病名稱
var disease = $('body > div.wrap.mt10.clearfix.graydeep > div.main-sub.fl > div.jib-janj.bor.clearfix > div.jib-articl.fr.f14 > div.jib-articl-con.jib-lh-articl > strong').text()
// 存進excel
var buffer = xlsx.build([
{
name:'sheet1',
data:[[disease]]
}
]);
// fs.appendFileSync('diseaseData.xlsx',buffer);
fs.writeFileSync('diseaseData.xlsx',buffer);
}
// 回圈存入url,并進行資料請求
var urls = []
for (let i = 50; i<53;i++) {
const url = `http://xxx/${i}.htm`
urls.push(url)
}
// 等待一個請求處理結束后再進行第二次請求
urls.reduce((rs,url)=>{
return rs.then(res => {
return new Promise(async (resolve)=>{
await getData(url)
resolve()
})
})
},Promise.resolve())
兩個note:
-
為什么使用reduce和Promise,而不直接在for回圈中
getData(url)?reduce方法作為累加器可以將陣列的上一次計算結果傳給下一項,第二個引數接受
Promise.resolve()的初始值,在回呼函式中只有當一次資料請求和處理完成并且resolve()后才會進行下一項的處理,這樣就可以逐次請求陣列中的url,避免給服務器造成較大壓力, -
使用
fs.writeFileSync會覆寫已有檔案,追加檔案本來應該使用appendFileSync,但在本例中遇到問題一開始是想使用
appendFileSync向excel中追加資料的,但是生成的檔案一直顯示損壞,似乎是寫入錯誤,一直沒有找到問題的原因,因為這不是小貓此次畢設的主要任務,決定先留一個坑,后來迫于時間壓力,選擇了先將適量資料存入一個陣列,然后使用writeFileSync生成多個excel,最后在excel軟體中一次性合并多張表,本次共收集10000余條資料,最后曬張圖,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/267096.html
標籤:區塊鏈
上一篇:Win10下安裝CUDA11.0+CUDNN8.0+tensorflow-gpu2.4.1+pytorch1.7.0
