I'm trying to get open graph metadata from an URL using nodejs (with cheerio), using the code bellow.

I have this thing to fill: 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];
                }
            }

        }
    }
}

After I populate the result I converted in a JSon and with this code I get something like:

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"
]

But the thing I want is something like:

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"
}
}

I'm trying this "if" but it doesn't work:

 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;
                    }
                }

I don't want to cycle all the meta 2 times and I'm not good with javascript and nodejs function... Any suggestion? Thanks

share|improve this question
Happy to help but you'll get quicker responses if you post code that can actually run. Right would anyone wanting to help would have to reconstruct the rest of your program. – Richard Marr 18 hours ago
feedback

1 Answer

This is tricky because of how you want to display og:video. I don't think you can do it that way. The easiest thing to do would be to assign it an identifier for example name and have it at the same level as og:video:width

Example result

{
  "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"
  }
}

How it could be done,

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));

});
share|improve this answer
Correct, it is not possible to have the data structure as requested in JS, because in an object every property needs to have a name. What would be possible, is to replace the outer square brackets with curly ones – thus creating video as an array with two entries, the first one a string value containing the URL, and the second one an object with the “meta data”. But I don’t see any actual benefit to that – having to switch from accessing everything else in that data structure as object properties, and only at this point index-based would be rather confusing. – CBroe 10 hours ago
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.