2015-11-24 12 views
11

Sto cercando di interrogare i post di Instagram fornendo l'hashtag e l'intervallo di tempo (da e fino alle date). Io uso il recent tags endpoint.Invia messaggi di Instagram per hashtag e intervallo di tempo

https://api.instagram.com/v1/tags/{tag-name}/media/recent?access_token=ACCESS-TOKEN

Il mio codice è scritto in Node.js utilizzando la libreria instagram-node (vedi i commenti inline):

// Require the config file 
var config = require('../config.js'); 

// Require and intialize the instagram instance 
var ig = require('instagram-node').instagram(); 

// Set the access token 
ig.use({ access_token: config.instagram.access_token }); 

// We export this function for public use 
// hashtag: the hashtag to search for 
// minDate: the since date 
// maxDate: the until date 
// callback: the callback function (err, posts) 
module.exports = function (hashtag, minDate, maxDate, callback) { 

    // Create the posts array (will be concated with new posts from pagination responses) 
    var posts = []; 

    // Convert the date objects into timestamps (seconds) 
    var sinceTime = Math.floor(minDate.getTime()/1000); 
    var untilTime = Math.floor(maxDate.getTime()/1000); 

    // Fetch the IG posts page by page 
    ig.tag_media_recent(hashtag, { count: 50 }, function fetchPosts(err, medias, pagination, remaining, limit) { 

    // Handle error 
    if (err) { 
     return callback(err); 
    } 

    // Manually filter by time 
    var filteredByTime = medias.filter(function (currentPost) { 
     // Convert the created_time string into number (seconds timestamp) 
     var createdTime = +currentPost.created_time; 

     // Check if it's after since date and before until date 
     return createdTime >= sinceTime && createdTime <= untilTime; 
    }); 

    // Get the last post on this page 
    var lastPost = medias[medias.length - 1] || {}; 

    // ...and its timestamp 
    var lastPostTimeStamp = +(lastPost.created_time || -1); 

    // ...and its timestamp date object 
    var lastPostDate = new Date(lastPostTimeStamp * 1000); 

    // Concat the new [filtered] posts to the big array 
    posts = posts.concat(filteredByTime); 

    // Show some output 
    console.log('found ' + filteredByTime.length + ' new items total: ' + posts.length, lastPostDate); 


    // Check if the last post is BEFORE until date and there are no new posts in the provided range 
    if (filteredByTime.length === 0 && lastPostTimeStamp <= untilTime) { 
     // ...if so, we can callback! 
     return callback(null, posts); 
    } 

    // Navigate to the next page 
    pagination.next(fetchPosts); 
    }); 
}; 

Questo farà partire il recupero dei messaggi con il più recente al meno recenti, e filtrare manualmente il created_time. Funziona, ma è molto molto inefficiente perché se vogliamo, ad esempio, ottenere i post di un anno fa, dobbiamo iterare le pagine fino a quel momento, e questo userà molte richieste (probabilmente più di 5k/ora che è il limite di velocità).

C'è un modo migliore per fare questa richiesta? Come ottenere i post di Instagram fornendo l'hashtag e l'intervallo di tempo?

+0

Potresti aumentare il 'CONTO' per afferrare una significativamente più alta quantità di foto alla volta per ridurre * l'importo * dei post fetch? Naturalmente sarebbero molto più grandi ma sarebbe qualcosa di simile essere utile? –

+0

@NickZ Abbiamo provato a farlo (stavo eseguendo il debug di questo è l'OP) e il massimo che abbiamo ottenuto è stato di 33 articoli/richiesta. Quindi, il 'count' non aiuta davvero ... :-(Qualche altra idea? Sono felice di assegnare 50 punti a qualcuno che dia una buona risposta.: D –

+1

Hai cercato di utilizzare MIN_TAG_ID e MAX_TAG_ID per iterare rapidamente verso una data di destinazione? Posso immaginare un metodo che richiede un solo post alla volta per trovare un MAX_TAG_ID che è appena prima della data richiesta. – sbozzie

risposta

6

Penso che questa sia l'idea di base che stai cercando. Non ho molta familiarità con Node.js, quindi questo è tutto in chiaro javascript. Dovrai modificarlo in base alle tue esigenze e probabilmente farne una funzione.

L'idea è di convertire un id di Instagram (1116307519311125603 in questo esempio) in una data e viceversa per consentire di catturare rapidamente un punto specifico nel tempo piuttosto che tornare indietro attraverso tutti i risultati fino a trovare il timestamp desiderato. La porzione dell'ID dopo il carattere di sottolineatura '_' deve essere ritagliata poiché si riferisce, in qualche modo, all'utente IIRC. Ci sono 4 funzioni nell'esempio che spero ti aiuteranno.

Happy hacking!

//static 
var epoch_hour = 3600, 
    epoch_day = 86400, 
    epoch_month = 2592000, 
    epoch_year = 31557600; 

//you'll need to set this part up/integrate it with your code 
var dataId = 1116307519311125603, 
    range = 2 * epoch_hour, 
    count = 1, 
    tagName = 'cars', 
    access = prompt('Enter access token:'), 
    baseUrl = 'https://api.instagram.com/v1/tags/' + 
       tagName + '/media/recent?access_token=' + access; 

//date && id utilities 
function idToEpoch(n){ 
    return Math.round((n/1000000000000 + 11024476.5839159095)/0.008388608); 
} 

function epochToId(n){ 
    return Math.round((n * 0.008388608 - 11024476.5839159095) * 1000000000000); 
} 

function newDateFromEpoch(n){ 
    var d = new Date(0); 
    d.setUTCSeconds(n); 
    return d; 
} 

function dateToEpoch(d){ 
    return (d.getTime()-d.getMilliseconds())/1000; 
} 

//start with your id and range; do the figuring 
var epoch_time = idToEpoch(dataId), 
    minumumId = epochToId(epoch_time), 
    maximumId = epochToId(epoch_time + range), 
    minDate = newDateFromEpoch(epoch_time), 
    maxDate = newDateFromEpoch(epoch_time + range); 

var newUrl = baseUrl + 
      '&count=' + count + 
      '&min_tag_id=' + minumumId + 
      '&max_tag_id=' + maximumId; 


//used for testing 
/*alert('Start: ' + minDate + ' (' + epoch_time + 
     ')\nEnd: ' + maxDate + ' (' + (epoch_time + 
     range) + ')'); 
window.location = newUrl;*/ 
+0

Sembra fantastico! Lo sto testando proprio ora - puoi spiegare questi numeri magici: 'return Math.round ((n * 0.008388608 - 11024476.5839159095) * 1000000000000);'? –

+0

Testato, wow, funziona come necessario !!! Sei forte! :) –

+0

Un riferimento a dove hai trovato il modo in cui Instagram codifica gli ID sarebbe utile. Questo odora di funzionalità non documentata. – FuriousFolder

2

Per supportare this risposta eccellente, un ID instagram viene generato tramite la funzione plpgsql:

CREATE OR REPLACE FUNCTION insta5.next_id(OUT result bigint) AS $$ 
DECLARE 
    our_epoch bigint := 1314220021721; 
    seq_id bigint; 
    now_millis bigint; 
    shard_id int := 5; 
BEGIN 
    SELECT nextval('insta5.table_id_seq') %% 1024 INTO seq_id; 

    SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis; 
    result := (now_millis - our_epoch) << 23; 
    result := result | (shard_id << 10); 
    result := result | (seq_id); 
END; 
$$ LANGUAGE PLPGSQL; 

da Instagram's blog

Problemi correlati