如何使用节点获取给定URL的所有元素的CSS?

时间:2018-05-02 13:18:47

标签: javascript node.js cheerio

我正在尝试编写一个脚本,在提供网站网址时查看所有链接并检查是否在每个网址中是否该网页上使用的字体是helvetica,所以我想出了下面的脚本(从网上复制的部分。)

var request = require('request');
var cheerio = require('cheerio');
var URL = require('url-parse');

var START_URL = "http://example.com/";
var SEARCH_FONT = "helvetica";
var MAX_PAGES_TO_VISIT = 100000;

var pagesVisited = {};
var numPagesVisited = 0;
var pagesToVisit = [];
var url = new URL(START_URL);
var baseUrl = url.protocol + "//" + url.hostname;

pagesToVisit.push(START_URL);
crawl();

function crawl() {
  if(numPagesVisited >= MAX_PAGES_TO_VISIT) {
    console.log("Reached max limit of number of pages to visit.");
    return;
  }
  var nextPage = pagesToVisit.pop();
  if (nextPage in pagesVisited) {
    // We've already visited this page, so repeat the crawl
    crawl();
  } else {
    // New page we haven't visited
    visitPage(nextPage, crawl);
  }
}

function visitPage(url, callback) {
  // Add page to our set
  pagesVisited[url] = true;
  numPagesVisited++;

  // Make the request
  console.log("Visiting page " + url);
  request(url, function(error, response, body) {
     // Check status code (200 is HTTP OK)
     console.log("Status code: " + response.statusCode);
     if(response.statusCode !== 200) {
       callback();
       return;
     }
     // Parse the document body
     var $ = cheerio.load(body);
     var helveticaFound = searchForHelvetica($, SEARCH_FONT);
     if(helveticaFound) {
       console.log('Word ' + SEARCH_FONT + ' found at page ' + url);
     } else {
       collectInternalLinks($);
       // In this short program, our callback is just calling crawl()
       callback();
     }
  });
}

function searchForHelvetica($, word) {
    var bodyText = $('*').each( function(i , e) { console.log($(e).css('fontFamily')) } );
}

function collectInternalLinks($) {
    var relativeLinks = $("a[href^='/']");
    console.log("Found " + relativeLinks.length + " relative links on page");
    relativeLinks.each(function() {
        pagesToVisit.push(baseUrl + $(this).attr('href'));
    });
}

我面临的问题是以下功能:

function searchForHelvetica($, word) {
        var bodyText = $('*').each( function(i , e) { console.log($(e).css('fontFamily')) } );
    }

console.log($(e).css('fontFamily'))将始终返回undefined。我相信cheerio无法访问元素的CSS。我该如何解决这个问题?如何获取页面上每个元素的css,遍历每个元素,然后检查页面上的任何位置是否使用helvetica字体,并根据此测试返回true或false?

1 个答案:

答案 0 :(得分:1)

您必须使用getComputedStyle

请参阅https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

像这样的东西: window.getComputedStyle(node, null).getPropertyValue('font-family');

它将返回一个字符串(如"Arial, "Helvetica Neue", Helvetica, sans-serif"),您可以在其中搜索字体

鉴于你的例子,我认为你可以这样做:

    function searchForHelvetica($, word) {
            var bodyText = $('*').each( function(i , e) { console.log(window.getComputedStyle($(e)[0], null).getPropertyValue('font-family')) } );
    }

注意:

正如cheerio README中明确指出的那样:

  

Cheerio解析标记并提供用于遍历/操纵结果数据结构的API。它不会像Web浏览器那样解释结果。具体来说,它不会生成可视化渲染,应用CSS,加载外部资源或执行JavaScript。如果您的用例需要任何此功能,则应考虑PhantomJS或JSDom等项目。

cheerio不会渲染/应用CSS。

所以你应该使用jsdom(https://github.com/jsdom/jsdom),因为它支持getComputedStyle