国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

node crawler如何添加promise支持

2024-05-06 15:43:57
字體:
來源:轉載
供稿:網友

背景

最近在組內做一些爬蟲相關的工作,本來想自己簡單造個輪子的,但是經網友推薦后,采用了node-crawler,用了一段時間過后,確實滿足了我的絕大部分需求,但是其 api 卻不支持 promise,而且我還需要一些同步爬取、同步處理的能力,如果不用 promise 的話,寫法很不優雅,所以我就簡單地給其封裝了一層 promise api

現狀

目前 node-crawler 的使用方式不支持 promise ,這里直接給出 npm 上的使用例子

const Crawler = require("crawler")// 實例化const c = new Crawler({  // ... 可以傳入一些配置  callback : function (error, res, done) {    // 請求回調,實例化的時候傳入的 callback 是作為默認 callback 的,后續每次抓取如果沒有傳入 callback,那么都會調用默認 callback    done();  }})// 爬取c.queue([{  uri: 'http://parishackers.org/',  jQuery: false,   // The global callback won't be called  callback: function (error, res, done) {    if(error){      console.log(error);    }else{      console.log('Grabbed', res.body.length, 'bytes');    }    done();  }}])

這樣的回調方式對于多爬蟲同步爬取很不友好

改造

理想使用方式:

const Crawler = require('crawler')const c = new Crawler({  // 一些默認配置})c.queue({  uri: 'xxx'}).then(res => {  // 抓取成功}).catch(err => {  // 抓取失敗})

改造方案:

// utils/crawler.jsconst Crawler = require('crawler')const defaultOptions = { jQuery: false, rateLimit: fetchRateLimit, retries: 0, timeout: fetchTimeout,}module.exports = class PromiseifyCrawler extends Crawler {  // namespace 是為了后續抓取結果統一上報時候進行區分  constructor(namespace = 'unknow', options = {}) {   if (typeof namespace === 'object') {    options = namespace    namespace = 'unknow'   }      options = merge({}, defaultOptions, options)   const cb = options.callback   options.callback = (err, res, done) => {    typeof cb === 'function' && cb(err, res, noop)    process.nextTick(done)    // 在這里可以自定義抓取成功還是失敗    // 我這里直接設置的是如果 http code 不是 200 就視為錯誤    // 而且在這里也可以做一些抓取成功失敗的統計    if (err || res.statusCode !== 200) {     if (!err) err = new Error(`${res.statusCode}-${res.statusMessage}`)     err.options = res.options     err.options.npolisReject(err)    } else {     res.options.npolisResolve(res)    }   }   options.headers = Object.assign({}, options.headers, {    'X-Requested-With': 'XMLHttpRequest',   })   super(options)  }   queue(options = {}) {   // 每次抓取都是一個新的 promise   return new Promise((resolve, reject) => {    // 然后在 options 里掛載上 resolve 和 reject    // 這樣在全局 callback 上就可以用到了    options.npolisResolve = resolve    options.npolisReject = reject    const pr = options.preRequest    options.preRequest = (options, done) => {     typeof pr === 'function' && pr(options, noop)     // 在這里也可以做一些通用的抓取前的處理          done()    }    super.queue(options)   })  }    // direct api 同理 }// 使用const Crawler = require('./utils/crawler')const crawler = new Crawler('示例爬蟲 namespace')crawler.queue({ uri: 'xxx', preRequest: options => log('開始抓取'),}).then(res => { log('爬取成功') return res}).catch(err => { log('爬取失敗') throw err})promise 化后,多個爬取任務同步爬取寫法就友好多了:// 抓取任務1const fetchTask1 = () => crawler.queue({/* 配置 */}).then(res => handle(res))// 抓取任務2const fetchTask2 = () => crawler.queue({/* 配置 */}).then(res => handle(res))const fetch = () => {  return Promise.all([    fetchTask1(),    fetchTask2(),  ])}fetch()            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 宁乡县| 莱芜市| 博爱县| 屏东县| 全州县| 鄱阳县| 礼泉县| 平利县| 冀州市| 长葛市| 水城县| 万宁市| 稻城县| 乳源| 达拉特旗| 清苑县| 兴海县| 岳西县| 富蕴县| 界首市| 达州市| 林口县| 姚安县| 商丘市| 衡东县| 抚松县| 古丈县| 丰都县| 河源市| 拜城县| 静宁县| 福海县| 渝北区| 靖西县| 烟台市| 曲周县| 布拖县| 丘北县| 九龙县| 九龙县| 驻马店市|