nightmare 模拟点击更多按钮,,怎么做??
发布于 7 年前 作者 Jackzhangpan 7392 次浏览 来自 问答

比如我要获取网易新闻的内容,因为是动态的,用nightmare,,但不知道怎么模拟获取更多??

var Nightmare = require('nightmare');
var nightmare = Nightmare({show:false})

nightmare
  .goto('http://news.163.com/')
  .inject('js', 'jquery.min.js')
  .type(这里应该怎么写)  -------???
  .click(怎么写?)          --------????
  .evaluate(function () {
   	 var newsList=[];
     $('.data_row').each(function () {
        var $me=$(this);
        var title=$me.find('.news_title').find('h3').find('a').text();
        var url=$me.find('.news_title').find('h3').find('a').attr('href');
        var item={
          title:title,
          url:url
        }
        newsList.push(item);

     })
     return newsList 	
  })
  .end()
  .then(function (result) {
  	console.log(result);
  })
  .catch(function (err) {
  	console.log(err);
  }) 
21 回复

自己分析对应页面的源码,要不就找到对应的函数直接在 evaluate 调用,要不就对这个按钮模拟 click 事件。

@atian25 ,我写了click(’.load_more_btn’),但是还没有加载更多信息。网上搜了很久没找到例子,我想知道怎么去写这个click事件,,原谅我只是一个小白。

const path = require('path');
var Nightmare = require('nightmare');
var nightmare = Nightmare({
    show: true,
    pollInterval: 50
});

nightmare
    .goto('http://news.163.com/domestic/')
    .inject('js', 'jquery-2.1.1.min.js')
    .wait(function() {
        if (document.querySelector('.post_addmore').style["visibility"] == "visible") {
            document.querySelector('.load_more_btn').click();
            return false;
		}
        if (document.querySelector(".post_adding").style["display"] == "block") return false;
        if (document.querySelector(".load_more_tip").style["display"] == "block") return true;
    })
    .evaluate(function() {
        var newsList = [];
        $('.data_row').each(function() {
            var $me = $(this);
            var title = $me.find('.news_title').find('h3').find('a').text();
            var url = $me.find('.news_title').find('h3').find('a').attr('href');
            var item = {
                title: title,
                url: url
            }
            newsList.push(item);
        })
        return newsList
    })
    .end()
    .then(function(result) {
        console.log(result);
        console.log(result.length);
    }).catch(function(err) {
        console.log(err);
    })

@godghdai 感谢感谢。

@godghdai 请问一下 我这种情况 .wait(function() {}里面该怎么写 ,我写的报错

这个是爬取链接https://www.youtube.com/playlist?list=PLHPTxTxtC0iaN9kA37m6MRrxFkgby2CDR image.png https://www.youtube.com/playlist?list=PLHPTxTxtC0iaN9kA37m6MRrxFkgby2CDRimage.png

@zhoujinhai

var Nightmare = require('nightmare');
var nightmare = Nightmare({
    show: false,
    pollInterval: 50
});

nightmare
    .goto('https://www.youtube.com/playlist?list=PLHPTxTxtC0iaN9kA37m6MRrxFkgby2CDR')
    //.inject('js', 'jquery-2.1.1.min.js')
    .wait(function() {
        var loadMoreText = document.querySelector('.load-more-text');
        if (loadMoreText == null) return true;
        if (/hid/.test(loadMoreText.classList.value)) return false;
        document.querySelector('.browse-items-load-more-button').click();
        return false;
    })
    .evaluate(function() {
        return Array.from(document.querySelectorAll('.pl-video-title')).map(function(item) {
            return item.childNodes[1].innerText;
        })
    })
    .end()
    .then(function(result) {
        console.log(result);
        console.log(result.length);
    }).catch(function(err) {
        console.log(err);
    })

@godghdai 非常感谢,问题解决啦!刚接触nightmare,请问下有没有好一点儿的教程适合我这种小白的,嘿嘿

@godghdai ,我也想请问下,根据不同需求,不同的点击等事件,要怎么去分析,nightmare官网的APi ??还是有其他博客或者js教程??谢谢

@zhoujinhai @Jackzhangpan

看官网api

pollInterval (default: 250ms)
How long to wait between checks for the .wait() condition to be successful.

.wait(fn[, arg1, arg2,...])
Wait until the fn evaluated on the page with arg1, arg2,... returns true. All the args are optional. See .evaluate() for usage.

每间隔段时间都会调用wait方法,直到wait返回true,在wait方法里面根据dom检查,一般三个状态,加载中(return false),可以加载更多(click,return false),加载完毕(return true)

@godghdai ,你好大神,又来请求你的帮助,像这个模拟点击下一页的问题?怎么分析去写?谢谢。

const path = require('path');
var Nightmare = require('nightmare');
var nightmare = Nightmare({
    show: false,
    pollInterval: 150
});
nightmare
    .goto('http://roll.news.qq.com/')
    .inject('js', 'jquery.min.js')
    .wait(function() {
     /////
    })
    .evaluate(function() {
        var newsList = [];
        $('#artContainer li').each(function() {
            var $me = $(this);
            var title = $me.find('a').text();
            var url = $me.find('a').attr('href');
            var item = {
                title: title,
                url: url
            }
            newsList.push(item);
        })
        return newsList
    })
    .end()
    .then(function(result) {
        console.log(result,result.length)
    }).catch(function(error) {
        console.log('错误是:'+error);
    })


 [腾讯滚动新闻](http://roll.news.qq.com/#) [腾讯滚动新闻](http://roll.news.qq.com/#)

@Jackzhangpan


var Nightmare = require('nightmare');
var nightmare = Nightmare({
    show: true,
    pollInterval: 1000
});


nightmare
    .goto('http://roll.news.qq.com/')
    .wait(function() {
        return document.querySelectorAll("#artContainer li").length>0;
    })
    .wait(function() {

        if (window._$qqNews == undefined) {

            window._$qqNews = {
                total: 0,
                page: 0,
                items: []
            }

            //停止自动刷新
            AutoRefresh();
            _$qqNews.total = qq.$("totalPage").value;

            G.showArtList = function(responseText) {
                try {
                    eval("var json = " + responseText);
                    if (json.response.code == "0") {
                        qq.$("artContainer").innerHTML = json.data.article_info;

                        //
                        var newslist = document.querySelectorAll("#artContainer li a");
                        for (var i = 0; i < newslist.length; i++) {

                            _$qqNews.items.push({
                                title: newslist[i].childNodes[0].data,
                                href: newslist[i].href
                            });
                        }

                        qq.$("totalPage").value = json.data.count;

                        if (_$qqNews.total > 1) {
                            _$qqNews.total -= 1;
                            nextPage();
                        }


                    } else if (json.response.code == "2") {
                        qq.$("totalPage").value = 1;
                        G.gotoPage(1);
                        qq.$("artContainer").innerHTML = '<div class="article-tips">该日期没有文章!</div>';
                    } else {
                        qq.$("totalPage").value = 1;
                        G.gotoPage(1);
                        qq.$("artContainer").innerHTML = '<div class="article-tips">文章加载失败!</div>';
                    }
                } catch (e) {}
            }

            //加载第1页
            Refresh();

            return false;
        }

        if (_$qqNews.total == 1)
            return true;

        return false;

    }).evaluate(function() {

        return _$qqNews.items;
    })
    .end()
    .then(function(result) {
        console.log(result, result.length)
    }).catch(function(error) {
        console.log('错误是:' + error);
    })



@godghdai 谢谢谢谢。受教了,有时候分析不同页面还是一头雾水。

这个问题有意思

@godghdai 你好,不好意思又来问啦!对于其他网页模拟下一页的时候,像您15楼那样,要是找不到相应的JS文件的话,我想通过每点击一次下一页,然后获取一次页面信息,直到点到最后一页,我试了下 http://roll.news.qq.com/,但一直显示wait等待超时?请问一下,这样是我这思路不行还是代码问题!

var Nightmare = require('nightmare');       
var nightmare = Nightmare({ 
	show: true//显示electron窗口
	// waitTimeout : 5000
});

nightmare
	//加载页面
	.goto('http://roll.news.qq.com/')
	.wait(function() {
        return document.querySelectorAll("#artContainer li").length>0;
    })
	.inject('js','jquery.min.js')
	.wait(function(){
		if(window.qqNews === undefined){
			window.qqNews={
				page : 26,
				arr : []
			};
			if(qqNews.page!==1){
	  			$('#artContainer li').each(function(){
			  		var title = $(this).find('a').text();
			  		qqNews.arr.push(title);
	  			});
	  			$('#pageArea .f12:contains("下一页")').click();
	  			qqNews.page -= 1;
	  			return false;
	  		}
	  		if(qqNews.page===1){
	  			$('#artContainer li').each(function(){
			  		var title = $(this).find('a').text();
			  		qqNews.arr.push(title);
	  			});
	  			return true;
	  		}	
		}
		return false;
	})
	.evaluate(function(){
		return qqNews.arr;
	})
	.end()
	.then(function(res){
	  console.log(res,res.length);
	})
	.catch(function (error) {
	  console.error('failed:', error);
	});

@zhoujinhai 模拟点击下一页也是可以的,只是没有上一种方法快,


var Nightmare = require('nightmare');
var nightmare = Nightmare({
    show: true //显示electron窗口
        // waitTimeout : 5000
});
nightmare
    .goto('http://roll.news.qq.com/')
    .wait(function() {
        return !document.querySelector(".loading");
    })
    .wait(function() {
        window._$qqNews = [];
        return true;
    })
    .wait(function() {

        //如果显示正在加载中……
        if (document.querySelector(".loading")) return false;

        var newslist = document.querySelectorAll("#artContainer li a");
        for (var i = 0; i < newslist.length; i++) {
            _$qqNews.push({
                title: newslist[i].childNodes[0].data,
                href: newslist[i].href
            });
        }
		//下一页button
        var next_page_button = document.querySelector("#pageArea .f12:last-child");
        if (next_page_button) {
            next_page_button.click();
            return false;
        }
        return true;

    })
    .evaluate(function() {
        return _$qqNews;
    })
    .end()
    .then(function(res) {
        console.log(res[res.length-1], res.length);
    })
    .catch(function(error) {
        console.error('failed:', error);
    });


@godghdai 嗯嗯 是的,非常感谢!!!

回到顶部