如何在NodeJs中刮取一个动态生成的网页?[英] How do you scrape a dynamically generated webpage in NodeJs?

问题描述

有些网站的 DOM 和内容是在页面加载时动态生成的.(基于 Angularjs 的网站因此而臭名昭著)

您使用什么方法?我尝试了 phantomjs 和 jsdom,但似乎在我抓取之前我无法让页面执行其 javascript.

这是一个简单的 jsdom 示例(不是基于 angularjs,但仍然是动态生成的)

var env = require('jsdom').env;

exports.scrape = function(link, callback) {
  var config = {
    url: link,
    headers: { 
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36'
      },
    done: jsdomDone
  };

  env(config);
}

function jsdomDone(err, window) {
  var info = null;
  if(err) {
    console.error(err);
  } else {
    var $ = require('jquery')(window);

    console.log($('.profilePic').attr('src'));
  }
}

exports.scrape('https://www.facebook.com/elcompanies');

我尝试了 phantomjs 并取得了一定的成功.

var page = new WebPage()
var fs = require('fs');

page.onLoadFinished = function() {
  console.log("page load finished");
  window.setTimeout(function() {
    page.render('export.png');
    fs.write('1.html', page.content, 'w');
    phantom.exit();
  }, 10000);
};

page.open("https://www.facebook.com/elcompanies", function() {
  page.evaluate(function() {
  });
});

在这里我等待 onLoadFinished 事件,甚至设置了一个 10 秒的计时器.有趣的是,虽然我的页面的 export.png 图像捕获显示了一个完全呈现的页面,但我的 1.html 没有在其应有的位置显示 .profilePic 类元素.它似乎坐在一些 javascript 代码中,被某种 "require("TimeSlice").guard(function() {bigPipe.onPageletArrive({..." 块

如果你能提供一个从这个页面上刮掉图像的工作示例,那将会很有帮助.

推荐答案

我在 Facebook 中使用 nightmarejs 做了一些抓取.
这是我从 Facebook 页面的某些帖子中获取一些内容的代码.

module.exports = function checkFacebook(callback) {
var nightmare = Nightmare();
Promise.resolve(nightmare
  .viewport(1000, 1000)
  .goto('https://www.facebook.com/login/')
  .wait(2000)
  .evaluate(function(){
    document.querySelector('input[id="email"]').value = facebookEmail
    document.querySelector('input[id="pass"]').value = facebookPwd
    return true
  })
  .click('#loginbutton input')
  .wait(1000)
  .goto('https://www.facebook.com/groups/bierconomia')
  .evaluate(function(){
    var posts = document.getElementsByClassName('_1dwg')
    var length = posts.length
    var postsContent = []
    for(var i = 0; i < length; i++){
      var pTag = posts[i].getElementsByTagName('p')
      postsContent.push({
        content: pTag[0] ? pTag[0].innerText : '',
        productLink: posts[i].querySelector('a[rel = "nofollow"]') ? posts[i].querySelector('a[rel = "nofollow"]').href : '',
        photo: posts[i].getElementsByClassName('_46-i img')[0] ? posts[i].getElementsByClassName('_46-i img')[0].src : ''
      })
    }
    return postsContent
  }))
  .then(function(results){
    log(results)
    return new Promise(function(resolve, reject) {
      var leanLinks = results.map(function(result){
        return {
          post: {
            content: result.content,
            productLink: extractLinkFromFb(result.productLink),
            photo: result.photo
          }
        }
      })
      resolve(leanLinks)
    })
  })


我发现对 nightmare 有用的一点是,您可以使用 wait 函数等待 X 毫秒或等待特定的类进行渲染.

本文地址:https://www.itbaoku.cn/post/1739946.html