ノード爬虫類の経験を忘れないでくださいあなたの爬虫類を教え

今日、ビジネスは急に残業の時間が行われ、作業が開始1時間前の形式のExcelデータエクスポートのうち登る、爬虫類のビジネスを作りました。あまりにも長い間、私は爬虫類をしませんでしたので!需要がこれを行うことは非常に興奮しています!

要求の説明

  1. ウェブサイトへ
  2. (サイクリング)は、ページ指定されたデータソースを取得します
  3. 別のページのデータソースによると、(ループ)データアクセスの詳細
  4. Excel形式でエクスポートしたデータの記録内容、。

必要なモジュール

結果のモジュールは、5つを必要とします

// 请求模块(1.访问网站)
const request = require('request');

// 可以看做成node版的jQuery(2.获取页面指定数据源)
const cheerio = require("cheerio");

// node异步流程控制 异步循环(3.根据页面数据源再访问详情数据)
const async = require("async");

// Excel表格导出+node自带文件系统(4.以Excel形式导出)
const excelPort = require('excel-export');
const fs         = require("fs");

モジュールをインストールします。

npm install request cheerio async excel-export --save-dev

リクエストの送信を開始します

私は中に何も間違っているサイトを直接尋ねるが、直接404に戻ったが、私は、ブラウザで話して要求を開始しました。私は、ヘッダの要求に応じて変化しました。ヒッヒッヒ

request({
    url: 'http://www.foo.cn?page=1',
    method: 'get',
    headers: {
      'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
      // 这里巨坑!这里开启了gzip的话http返回来的是Buffer。
      // 'Accept-Encoding': 'gzip, deflate',
      'Accept-Language': 'zh-CN,zh;q=0.9',
      'Cache-Control': 'no-cache',
    },
    // 想请求回来的html不是乱码的话必须开启encoding为null
    encoding: null
  }, (err, res, body) => {
      // 这样就可以直接获取请求回来html了
      console.log('打印HTML', body.toString()); // <html>xxxx</html>
    }
  );

指定されたデータソースを取得します。

request({
    url: 'http://www.foo.cn?page=1',
    method: 'get',
    headers: {
      'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
      // 'Accept-Encoding': 'gzip, deflate',
      'Accept-Language': 'zh-CN,zh;q=0.9',
      'Cache-Control': 'no-cache',
    },
    encoding: null
  }, (err, res, body) => {
      console.log('打印HTML', body.toString()); // <html>xxxx</html>
      const list = [];
      const $ = cheerio.load(body.toString());
      // 获取指定元素
      let item = $('.className tbody tr');
      // 循环得到元素的跳转地址和名称
      item.map((i, index) => {
        let obj = {};
        obj.link = $(index).children('a').attr('href');
        obj.name = $(index).children('a').text();
        list.push(obj);
      });
      console.log('list', list); // [{ link: 'http://xxxx.com', name: 'abc' }]
    }
  );

非同期フロー制御

まず、多層パッケージ要求、およびコールバックasync.seriesの流入ページの値

async function requestPage(page = 1, callback) {
  request({
    url: 'http://www.masuma.cn/product.php?lm=21&page=' + page,
    method: 'get',
    headers: {
      'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
      // 'Accept-Encoding': 'gzip, deflate',
      'Accept-Language': 'zh-CN,zh;q=0.9',
      'Cache-Control': 'no-cache',
    },
    encoding: null
  }, async (err, res, body) => {
     console.log('打印HTML', body.toString()); // <html>xxxx</html>
      const list = [];
      const $ = cheerio.load(body.toString());
      // 获取指定元素
      let item = $('.className tbody tr');
      // 循环得到元素的跳转地址和名称
      item.map((i, index) => {
        let obj = {};
        obj.link = $(index).children('a').attr('href');
        obj.name = $(index).children('a').text();
        list.push(obj);
      });
      console.log('list', list); // [{ link: 'http://xxxx.com', name: 'abc' }]
      callback(null, list);
    }
  );
}

データをプリントアウトするためのエクスポートエクセル+

async function main() {
  const requestList = [];
  // 在这里为什么要用到async.series?
  // 是因为这个爬虫需要具有顺序性,必须得异步请求完一个地址并获取数据然后再存到一个变量里才能执行下一个
  // 在此期间我想过其他方法。例如:
  // for循环 + await 直接否定了
  // Promise.all这个并不能保证数据具有顺序
  // 最终敲定用async.series 用完之后!真香啊!
  // 很好奇async.series找个时间也做个源码解析
  for (let i = 1; i < 36; i++) {
    requestList.push(callback => {
      requestPage(i, callback);
    });
  }
  console.log('requestList', requestList); // [Function, Function] 全是function的数组
  async.series(requestList, (err, result) => {
    // 因为async.series返回来的结果是[[], [], []]这种二维数组形式,每个function返回来的值都放在一个数组里,我们需要将它弄成一维数组好做导出列表
    const arry = [].concat.apply([], result);
    console.log('最终结果!!!!', arry); // [{ link: 'http://xxxx.com', name: 'abc' }, ...]
    writeExcel(arry);
  });
}

const writeExcel = (datas) => {
  // 定义一个对象,存放内容
  let conf = {};
  // 定义表头
  conf.cols = [
     {caption:'玛速玛编码', type:'string', width:40},
     {caption:'原厂编码', type:'string', width:60},
  ];
  // 创建一个数组用来多次遍历行数据
  let array = [];
  // 循环导入从传参中获取的表内容
  for (let i=0;i<datas.length;i++){
      //依次写入
    array[i] = [
      datas[i].name,
      datas[i].code,
    ];
  }
  // 写入道conf对象中
  conf.rows = array;
  // 生成表格
  const result = excelPort.execute(conf);
  // 定义表格存放路径
  fs.writeFile('./表格.xlsx', result, 'binary',function(err){
      if(err){
          console.log(err);
      }
  });
}

main();

概要

実際には、爬虫類は次のとおりです。

  1. GET HTMLへのアナログブラウザ要求、
  2. HTMLの解析を行うには、データを抽出する必要があります。
  3. データをさらに処理、輸出エクセル、データベースの保存など

遂に

実際には、これは究極の爬虫類であります

  1. ページネーションと反復表
  2. 撤退は、リンクを形成すると詳細ページに移動するためのリンクにアクセス
  3. 私は、詳細ページのデータを取得する必要があります
  4. 最終的な出力エクセル

しかし、私はここで私は単純なシェアをしたいので、各ページのリンクアドレスを取得するためのフォームを作成するためにここにいます。

これらは、類推を共有するための十分なはずです。

おすすめ

転載: www.cnblogs.com/scottjeremy/p/11961190.html