首頁  >  文章  >  web前端  >  如何使用nodeJs爬蟲

如何使用nodeJs爬蟲

php中世界最好的语言
php中世界最好的语言原創
2018-05-30 09:56:161761瀏覽

這次帶給大家如何使用nodeJs爬蟲,使用nodeJs爬蟲的注意事項有哪些,下面就是實戰案例,一起來看一下。

背景

最近打算把之前看過的nodeJs相關的內容在複習下,順便寫幾個爬蟲來打發無聊,在爬的過程中發現一些問題,記錄下以便備忘。

依賴

用到的是網路爛大街的cheerio函式庫來處理爬取的內容,使用superagent處理請求,log4js來記錄日誌。

日誌配置

話不多說,直接上程式碼:

const log4js = require('log4js');
log4js.configure({
 appenders: {
  cheese: {
   type: 'dateFile',
   filename: 'cheese.log',
   pattern: '-yyyy-MM-dd.log',
   // 包含模型
   alwaysIncludePattern: true,
   maxLogSize: 1024,
   backups: 3 }
 },
 categories: { default: { appenders: ['cheese'], level: 'info' } }
});
const logger = log4js.getLogger('cheese');
logger.level = 'INFO';
module.exports = logger;

以上直接匯出一個logger對象,在業務文件裡直接呼叫logger .info()等函數加入日誌資訊就可以,會按天產生日誌。相關資訊網路上一堆。

爬取內容並處理

 superagent.get(cityItemUrl).end((err, res) => {
  if (err) {
   return console.error(err);
  }
  const $ = cheerio.load(res.text);
  // 解析当前页面,获取当前页面的城市链接地址
  const cityInfoEle = $('.newslist1 li a');
  cityInfoEle.each((idx, element) => {
   const $element = $(element);
   const sceneURL = $element.attr('href'); // 页面地址
   const sceneName = $element.attr('title'); // 城市名称
   if (!sceneName) {
    return;
   }
   logger.info(`当前解析到的目的地是: ${sceneName}, 对应的地址为: ${sceneURL}`);
   getDesInfos(sceneURL, sceneName); // 获取城市详细信息
   ep.after('getDirInfoComplete', cityInfoEle.length, (dirInfos) => {
    const content = JSON.parse(fs.readFileSync(path.join(dirname, './imgs.json')));
    dirInfos.forEach((element) => {
     logger.info(`本条数据为:${JSON.stringify(element)}`);
     Object.assign(content, element);
    });
    fs.writeFileSync(path.join(dirname, './imgs.json'), JSON.stringify(content));
   });
  });
 });

使用superagent請求頁面,請求成功後使用cheerio 來載入頁面內容,然後使用類似Jquery的匹配規則來尋找目的資源。

多個資源載入完成,使用eventproxy來代理事件,處理一次資源處罰一次事件,所有事件觸發完成後處理資料。

以上就是最基本的爬蟲了,接下來就是一些可能會出問題或需要特別注意的地方了。 。 。

讀寫本機檔案

建立資料夾

function mkdirSync(dirname) {
 if (fs.existsSync(dirname)) {
  return true;
 }
 if (mkdirSync(path.dirname(dirname))) {
  fs.mkdirSync(dirname);
  return true;
 }
 return false;
}

讀寫檔案

   const content = JSON.parse(fs.readFileSync(path.join(dirname, './dir.json')));
   dirInfos.forEach((element) => {
    logger.info(`本条数据为:${JSON.stringify(element)}`);
    Object.assign(content, element);
   });
   fs.writeFileSync(path.join(dirname, './dir.json'), JSON.stringify(content));

大量下載資源

下載資源可能包括圖片、音訊等等。

使用Bagpipe處理非同步並發 參考

const Bagpipe = require('bagpipe');
const bagpipe = new Bagpipe(10);
  bagpipe.push(downloadImage, url, dstpath, (err, data) => {
   if (err) {
    console.log(err);
    return;
   }
   console.log(`[${dstpath}]: ${data}`);
  });

下載資源,使用stream來完成檔案寫入。

function downloadImage(src, dest, callback) {
 request.head(src, (err, res, body) => {
  if (src && src.indexOf('http') > -1 || src.indexOf('https') > -1) {
   request(src).pipe(fs.createWriteStream(dest)).on('close', () => {
    callback(null, dest);
   });
  }
 });
}

編碼

有時候直接使用cheerio.load處理的網頁內容,寫入檔案後發現是編碼後的文字,可以透過

const $ = cheerio.load(buf, { decodeEntities: false });

來禁止編碼,

ps: encoding庫和iconv-lite未能實現將utf-8編碼的字元轉換為中文,可能是還對API不熟悉,稍後可以關注。

最後,附上一個符合所有dom標籤的正則

const reg = /<.*?>/g;

相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

如何使用js封裝ajax功能函數與用法

JS裡常見內建函數使用詳解

以上是如何使用nodeJs爬蟲的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn