使用 Node.js 開發(fā)資訊爬蟲流程
最近項(xiàng)目需要一些資訊,因?yàn)轫?xiàng)目是用 Node.js 來寫的,所以就自然地用 Node.js 來寫爬蟲了
項(xiàng)目地址:github.com/mrtanweijie… ,項(xiàng)目里面爬取了 Readhub 、 開源中國 、 開發(fā)者頭條 、 36Kr 這幾個(gè)網(wǎng)站的資訊內(nèi)容,暫時(shí)沒有對多頁面進(jìn)行處理,因?yàn)槊刻炫老x都會(huì)跑一次,現(xiàn)在每次獲取到最新的就可以滿足需求了,后期再進(jìn)行完善
爬蟲流程概括下來就是把目標(biāo)網(wǎng)站的HTML下載到本地再進(jìn)行數(shù)據(jù)提取。
一、下載頁面
Node.js 有很多http請求庫,這里使用 request ,主要代碼如下:
requestDownloadHTML () { const options = { url: this.url, headers: { 'User-Agent': this.randomUserAgent() } } return new Promise((resolve, reject) => { request(options, (err, response, body) => { if (!err && response.statusCode === 200) { return resolve(body) } else { return reject(err) } }) }) }
使用 Promise 來進(jìn)行包裝,便于后面使用的時(shí)候用上 async/await 。因?yàn)橛泻芏嗑W(wǎng)站是在客戶端渲染的,所以下載到的頁面不一定包含想要的HTML內(nèi)容,我們可以使用 Google 的 puppeteer 來下載客戶端渲染的網(wǎng)站頁面。眾所周知的原因,在 npm i 的時(shí)候 puppeteer 可能因?yàn)樾枰螺dChrome內(nèi)核導(dǎo)致安裝會(huì)失敗,多試幾次就好了:)
puppeteerDownloadHTML () { return new Promise(async (resolve, reject) => { try { const browser = await puppeteer.launch({ headless: true }) const page = await browser.newPage() await page.goto(this.url) const bodyHandle = await page.$('body') const bodyHTML = await page.evaluate(body => body.innerHTML, bodyHandle) return resolve(bodyHTML) } catch (err) { console.log(err) return reject(err) } }) }
當(dāng)然客戶端渲染的頁面最好是直接使用接口請求的方式,這樣后面的HTML解析都不需要了,進(jìn)行一下簡單的封裝,然后就可以像這樣使用了: #滑稽 :)
await new Downloader('http://36kr.com/newsflashes', DOWNLOADER.puppeteer).downloadHTML()
二、HTML內(nèi)容提取
HTML內(nèi)容提取當(dāng)然是使用神器 cheerio 了, cheerio 暴露了和 jQuery 一樣的接口,用起來非常簡單。瀏覽器打開頁面 F12 查看提取的頁面元素節(jié)點(diǎn),然后根據(jù)需求來提取內(nèi)容即可
readHubExtract () { let nodeList = this.$('#itemList').find('.enableVisited') nodeList.each((i, e) => { let a = this.$(e).find('a') this.extractData.push( this.extractDataFactory( a.attr('href'), a.text(), '', SOURCECODE.Readhub ) ) }) return this.extractData }
三、定時(shí)任務(wù)
cron 每天跑一跑 function job () { let cronJob = new cron.CronJob({ cronTime: cronConfig.cronTime, onTick: () => { spider() }, start: false }) cronJob.start() }
四、數(shù)據(jù)持久化
數(shù)據(jù)持久化理論上應(yīng)該不屬于爬蟲關(guān)心的范圍,用 mongoose ,創(chuàng)建Model
import mongoose from 'mongoose' const Schema = mongoose.Schema const NewsSchema = new Schema( { title: { type: 'String', required: true }, url: { type: 'String', required: true }, summary: String, recommend: { type: Boolean, default: false }, source: { type: Number, required: true, default: 0 }, status: { type: Number, required: true, default: 0 }, createdTime: { type: Date, default: Date.now } }, { collection: 'news' } ) export default mongoose.model('news', NewsSchema)
基本操作
import { OBJ_STATUS } from '../../Constants' class BaseService { constructor (ObjModel) { this.ObjModel = ObjModel } saveObject (objData) { return new Promise((resolve, reject) => { this.ObjModel(objData).save((err, result) => { if (err) { return reject(err) } return resolve(result) }) }) } } export default BaseService
資訊
import BaseService from './BaseService' import News from '../models/News' class NewsService extends BaseService {} export default new NewsService(News)
愉快地保存數(shù)據(jù)
await newsService.batchSave(newsListTem)
更多內(nèi)容到Github把項(xiàng)目clone下來看就好了。
總結(jié)
相關(guān)文章
Nodejs 發(fā)送Post請求功能(發(fā)短信驗(yàn)證碼例子)
這篇文章主要介紹了Nodejs 發(fā)送Post請求功能(發(fā)短信驗(yàn)證碼例子),需要的朋友可以參考下2017-02-02Nodejs多站點(diǎn)切換Htpps協(xié)議詳解及簡單實(shí)例
這篇文章主要介紹了Nodejs多站點(diǎn)切換Htpps協(xié)議詳解及簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02Nodejs實(shí)現(xiàn)內(nèi)網(wǎng)穿透服務(wù)
很多人都不知道什么是內(nèi)網(wǎng)穿透,就是公網(wǎng)客戶端,可以訪問局域網(wǎng)內(nèi)的服務(wù),本文詳細(xì)的介紹了原理以及實(shí)現(xiàn),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05node版本太高導(dǎo)致項(xiàng)目跑不起來的解決辦法(windows)
換了臺電腦后,安裝node,一切完美,發(fā)現(xiàn)其中有一個(gè)uniapp的小程序項(xiàng)目跑不起來,感覺是node版本太高導(dǎo)致的,所以只能重新安裝低版本的node,本文給大家介紹了node版本太高的解決辦法,需要的朋友可以參考下2023-10-10使用pify實(shí)現(xiàn)Node.js回調(diào)函數(shù)的Promise化
使用pify庫,你可以非常便利地將任何遵循Node.js回調(diào)風(fēng)格的函數(shù)轉(zhuǎn)換為返回Promise對象的函數(shù),從而使得你的異步代碼更加清晰和易于維護(hù),本文通過豐富的代碼示例引導(dǎo)你如何有效地利用pify,需要的朋友可以參考下2024-06-06Node.js+Express+Mysql 實(shí)現(xiàn)增刪改查
這篇文章主要介紹了Node.js+Express+Mysql 實(shí)現(xiàn)增刪改查,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04node.js WEB開發(fā)中圖片驗(yàn)證碼的實(shí)現(xiàn)方法
這篇文章主要介紹了node.js WEB開發(fā)中圖片驗(yàn)證碼的實(shí)現(xiàn)方法,使用ccap模塊實(shí)現(xiàn),需要的朋友可以參考下2014-06-06nodejs實(shí)現(xiàn)日志讀取、日志查找及日志刷新的方法分析
這篇文章主要介紹了nodejs實(shí)現(xiàn)日志讀取、日志查找及日志刷新的方法,涉及nodejs日期時(shí)間運(yùn)算、轉(zhuǎn)換及日志讀寫等相關(guān)操作技巧,需要的朋友可以參考下2019-05-05