【问题标题】:Scraping algorithm for open graph in nodejsnodejs中开放图的抓取算法
【发布时间】:2012-10-24 13:30:27
【问题描述】:

我正在尝试使用 nodejs(使用cheerio)从 URL 获取打开的图形元数据, 使用下面的代码。

我有这个东西要填:var result={};

  for (var ogCounter = 0; ogCounter < metalist.length; ogCounter++) {
    if (!utils.isEmpty(metalist[ogCounter].attribs.property) && !utils.isEmpty(metalist[ogCounter].attribs.content)) {
        if (metalist[ogCounter].attribs.property.indexOf('og') == 0) {
            var ogname = metalist[ogCounter].attribs.property.split(':');
            var property = ogname[1];
            var content = metalist[ogCounter].attribs.content;

            if (utils.isEmpty(result[property])) {
                result[property] = content;
            } else {
                if (result[property].push) {
                    result[property].push(content);
                } else {
                   result[property] = [result[property], content];
                }
            }

        }
    }
}

填充结果后,我在 JSon 中转换并使用此代码,我得到如下内容:

type: "video",
image: "http://i3.ytimg.com/vi/fWNaR-rxAic/mqdefault.jpg",
video: [
"http://www.youtube.com/v/fWNaR-rxAic?version=3&amp;autohide=1",
"application/x-shockwave-flash",
"1920",
"1080"
]

但我想要的是这样的:

type: "video",
image: "http://i3.ytimg.com/vi/fWNaR-rxAic/mqdefault.jpg",
video: {
"http://www.youtube.com/v/fWNaR-rxAic?version=3&amp;autohide=1",
{ 
type:"application/x-shockwave-flash",
width:"1920",
height:"1080"
}
}

我正在尝试这个“如果”,但它不起作用:

 if (utils.isEmpty(result[property])) {
                    result[property] = content;
                } else {
                    if (result[property].push) {
                        result[property].push(content);
                    } else {
                        var subresult={};
                        subresult[name[2]]=content;
                        subresult[property]=result[property] ;

                        result[property] = subresult;
                    }
                }

我不想循环所有的元 2 次,而且我不擅长 javascript 和 nodejs 功能......有什么建议吗?谢谢

【问题讨论】:

  • 很高兴为您提供帮助,但如果您发布可以实际运行的代码,您将获得更快的响应。任何想要提供帮助的人都必须重新构建程序的其余部分。

标签: algorithm node.js logic metadata facebook-opengraph


【解决方案1】:

这很棘手,因为您希望如何显示 og:video。我不认为你可以那样做。最简单的做法是为其分配一个标识符,例如 name 并将其与 og:video:width 处于同一级别

示例结果

{
  "type": "video.other",
  "url": "http://philippeharewood.com/facebook/video.html",
  "title": "Simple Plan",
  "video": {
    "name": "http://www.youtube.com/v/Y4MnpzG5Sqc?version=3&amp;autohide=1",
    "type": "application/x-shockwave-flash",
    "width": "398",
    "height": "224",
    "release_date": "2012-05-29T21:30"
  }
}

如何做到,

var cheerio = require('cheerio')
var request = require('request')

var url = 'http://philippeharewood.com/facebook/video.html';
var result = {};

request(url, function(error, response, body) {
  var $ = cheerio.load(body);

  var meta = $('meta')
  var keys = Object.keys(meta)

  keys.forEach(function(key){
    if ( meta[key].attribs 
         && meta[key].attribs.property 
         && meta[key].attribs.property.indexOf('og') == 0
       ) 
    {
      var og = meta[key].attribs.property.split(':');

      if(og.length > 2) {
        if(result[og[1]]) {
          if (typeof result[og[1]] == 'string' 
             || result[og[1]] instanceof String
             ) 
          {
            var set = {};
            set['name'] = result[og[1]];
            set[og[2]] = meta[key].attribs.content;
            result[og[1]] = set;
          }
          else {
            ex_set = result[og[1]];
            ex_set[og[2]] = meta[key].attribs.content;
            result[og[1]] = ex_set;
          }
        }
        else {
          var set = {};
          set[og[2]] = meta[key].attribs.content;
          result[og[1]] = set;
        }
      }
      else {
        result[og[1]] = meta[key].attribs.content;
      }
    }
  });

  console.log(JSON.stringify(result, undefined, 2));

});

【讨论】:

  • 正确,不可能有 JS 中要求的数据结构,因为在 object 中,每个属性都需要有一个名称。什么是可能的,是用花括号替换外部方括号 - 从而将视频创建为具有两个条目的 array,第一个是包含 URL 的字符串值,第二个是一个对象“元数据”。但我认为这并没有任何实际好处——必须从访问该数据结构中的所有其他内容作为对象属性切换,并且只有在这一点上基于索引才会相当混乱。
【解决方案2】:

这是我的答案。 @phwd 完全回答了这个问题,但我认为最好制定一个更通用的解决方案,将所有 meta 标签解析为 n 级别。

var cheerio = require('cheerio'),
  request = require('request'),
  url = 'http://philippeharewood.com/facebook/video.html',
  result = {},
  attr = function( tag, prop ){ return tag.attribs && tag.attribs[prop] || ""; }

request( url, function( err, res, body ) {

  var metas = cheerio.load(body)('meta')
  var keys = Object.keys(metas)

  keys.forEach(function(i){
    var meta = metas[i],
      property = attr(meta,'property'),
      parts = property.split(":");

    if ( property ) {
      var og = property.split(':'),
        parent = result;

      for ( var j = 0; j < og.length; j++ ){
        var token = og[j],
          current = parent[token],
          name;

        if ( j+1 == og.length ) { // leaf node

          // expected leaf is already a branch so append a name attr
          if ( current instanceof Object ) name = token;
          // leaf should take the value given
          else parent[token] = attr(meta,'content');

        } else { // branch node

          // if no such branch exists, make one
          if ( !(current instanceof Object) ) {
            // if the branch is already a leaf, move value to name attr
            if ( typeof current == "string" ) name = current;
            current = {};
            parent[token] = current;  
          }
        }
        if ( name ) current["name"] = name;
        name = undefined
        parent = current;
      }
    }
  });

  console.log(JSON.stringify( result.og, undefined, 2));

});

【讨论】:

    猜你喜欢
    • 2012-05-19
    • 2017-06-21
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-02
    • 2017-05-09
    • 1970-01-01
    相关资源
    最近更新 更多