recherche

Maison  >  Questions et réponses  >  le corps du texte

node.js - Utilisez Node comme robot d'exploration pour simuler l'interface afin d'obtenir des données en boucle. Comment async/await peut-il réaliser des opérations synchrones et contrôler le processus ?

L'idée actuelle est la suivante : 1. Obtenez toutes les URL des pages de balises sous la catégorie, 2. Parcourez la page d'exploration pour récupérer la page de balises actuelle afin d'obtenir l'adresse API json, 3. Récupérez la liste de produits de la balise actuelle. , 4. Récupérez les produits en cours de chargement dans les pages à onglets.

Mais ce qui est fait maintenant, c'est qu'au début de la deuxième étape, il n'attend pas que 2-4 soit terminé avant de passer à la suivante. J'ai essayé d'utiliser async/await, mais le contrôle de processus n'a pas été implémenté. Demander conseil ici.

var http = require('http');
var fs = require("fs");
var superagent = require('superagent');
var urls = [];
var pageIndex = 1;
var xlsxData = '';

getGoodsUrl(urls);

function getGoodsUrl(urls){
    superagent
        .post('http://bravetime.davdian.com/index.php?c=Index&a=getCatNavList')
        .type('text/html; charset=utf-8')
        .set('Accept','application/json, text/javascript, */*; q=0.01')
        .end(function(err, res) {
            if (err) {
                console.log('分类数据请求失败');
            } else {
                console.log('分类数据请求成功');
                var resData = res.text;
                var resData = JSON.parse(resData); 
                if(resData.data.length > 0){
                    resData.data.forEach(function(item){
                        var rowObj = [];
                        var title = item.title;
                        var category = item.content.category;
                         category.forEach(function(item){
                             var text = [];
                             text.push(title+ '--' + item.text);
                             text.push(item.link);
                            rowObj.push(text);
                         });
                         urls.push(rowObj);
                     });
                     loopUrls(urls);
                } else {
                    console.log('分类数据为空');
                }

                // saveInfo(xlsxData);
            }
        })
}

function loopUrls(urls){
    urls.forEach(function(item){
        var row = item;
        row.forEach(function(item){
            var tagTitie = item[0];
            var tegUrl = item[1];
            getApiUrl(tagTitie,tegUrl);
        });
    });
}

function getApiUrl(title,url){
    var realUrl = 'http://bravetime.davdian.com' + url;
    http.get(realUrl,function(res){
         var html = '';
         res.on('data',function(data){
             html += data;
         });
         res.on('end',function(){
             console.log('正在获取' + title + '页面数据');
             var reg = /goodsUrl = "(.+)"/;
             var apiUrl = reg.exec(html);
             getGoodsJson(apiUrl[1],pageIndex);
         });
     }).on('error',function(){
         console.log('获取html出错!!');
     });
}

function getGoodsJson(url,pageIndex){
    superagent
        .post('http://bravetime.davdian.com/' + url + 'page_size=10&rp=catergory_search&rl=list')
        .send({page:pageIndex})
        .type('application/x-www-form-urlencoded; charset=UTF-8')
        .set('Accept','application/json, text/javascript, */*; q=0.01')
        .end(function(err, res) {
            if (err) {
                console.log('第' + pageIndex + '页请求失败');
            } else {
                console.log('第' + pageIndex + '页请求成功');
                var resData = res.text;
                var resData = JSON.parse(resData); 
                if(resData.data.length > 0){
                    resData.data.forEach(function(item){
                         xlsxData = xlsxData + item.goods_name + '  ' + item.shop_price + '  ' + item.goods_number + '\r\n';
                     });
                     pageIndex = parseInt(pageIndex) + 1;
                     setTimeout(function(){
                         getGoodsJson(url,pageIndex);
                     },200);
                } else {
                    console.log('数据已加载完毕');
                    saveTxt(xlsxData);
                    pageIndex = 1;
                    return false;
                }

                // saveInfo(xlsxData);
            }
        })

}

function saveTxt(data){
    fs.writeFile("create.txt",data,function (err) {
        if (err) throw err ;
         console.log("File Saved !"); //文件被保存
    }) ;
}
function saveInfo(data){
     var buffer = xlsx.build([{name: "mySheetName", data: data}]);
     fs.writeFileSync("myFile.xlsx", buffer, 'binary');
     console.log('excel保存成功');
}

Voici le diagramme de résultats et la séquence d'exécution du code :

给我你的怀抱给我你的怀抱2783 Il y a quelques jours1713

répondre à tous(4)je répondrai

  • 天蓬老师

    天蓬老师2017-07-06 10:38:31

    générateur
    async
    promesse

    répondre
    0
  • 仅有的幸福

    仅有的幸福2017-07-06 10:38:31

    L'ensemble de votre processus est asynchrone et vous ne voyez aucune signification à la synchronisation. Je pense que vous ne comprenez peut-être pas ce qu'est l'asynchrone.

    Async/await est basé sur Promise et Superagent lui-même prend en charge Promise. Vous pouvez utiliser async/await directement.

    async function() {
      try {
        const result = await superagent.get(url);
        console.log(result.headers);
        console.log(result.body);
      } catch (error) {
        console.error(error);
      }
    }

    http://visionmedia.github.io/...

    http://www.ruanyifeng.com/blo...

    Ensuite, il ne vous reste plus qu'à mettre http.get() 换成 superagent.get().

    répondre
    0
  • 習慣沉默

    習慣沉默2017-07-06 10:38:31

    En général, les gens n’ont pas la patience de lire la logique métier des autres.

    Comme mentionné ci-dessus, Async/await est basé sur Promise. Si l'interface API de la bibliothèque tierce que vous appelez ne renvoie pas d'objet de promesse, si vous souhaitez utiliser Async/await, vous ne pouvez créer un nouvel objet de promesse que sur à chaque étape. C'est en fait très difficile à écrire. Bien sûr, ce serait très pratique s'il pouvait renvoyer un objet promis.

    Ce qui suit est écrit en utilisant l'événement du module core du nœud sans promesses, pour votre référence :

    const EventEmitter = require('events');
    class MyEmitter extends EventEmitter {}
    const myEmitter = new MyEmitter();
    
    myEmitter.on('step1', (m) => {
        //第一步
        //业务逻辑处理得到结果result1
            
        //判断是否触发下一步,如有需要将这步的结果传给下一步
        myEmitter.emit('step2', result1);
       
    });
    myEmitter.on('step2', (result1) => {
        //第二步
        //业务逻辑处理得到结果result2
            
        //判断是否触发下一步,如有需要将这步的结果传给下一步
        myEmitter.emit('step3', result2);
    });
    myEmitter.on('step3', (result2) => {
        //以此类推
    });
    myEmitter.emit('step1', urls);
    

    répondre
    0
  • 怪我咯

    怪我咯2017-07-06 10:38:31

    Peut utiliser Node8 util.promisify , ou Bluebird, etc. changez la fonction de style de rappel Node en une fonction de style Promise, puis vous pouvez utiliser async/await pour écrire du code.

    Le code lui-même est toujours un appel asynchrone, mais la méthode d'écriture semble synchrone. Par conséquent, vous devez toujours faire attention à la structure du processus lors de l’écriture, en particulier lors de l’écriture de boucles. Le code est trop long, j'ai donc écrit un petit exemple pour illustrer

    async function remoteCall() {
        // do something
    }
    
    list = [];  // 假设是很多数据
    
    
    async function process() {
        // 这种写法必须要一个 remoteCall 完成之后才进行另一个
        for (let i = 0; i < list.length; i++) {
            await remoteCall();
        }
    
        doAfter();
    }
    
    async function process2() {
        // 这种写法没法 await
        list.forEach(function(t) {
            remoteCall();
        });
    }
    
    async function process3() {
        // 这种写法 doAfter 一早就会执行
        list.forEach(async function(t) {
            await remoteCall();
        });
    
        // 它可能会在 remoteCall() 之前
        doAfter();
    }
    
    async function process4() {
        // 这种写法必须要全部 remoteCall 成功才能进行到 doAfter
        // remoteCall返回的 promise 如果 reject 会抛异常
        var promises = list.map(t => remoteCall());
        await Promise.all(promises);
        doAfter();
    }

    répondre
    0
  • Annulerrépondre