2015-04-25 31 views
10

Próbuję pobrać zdjęcia opublikowane z konkretnym tagiem w czasie rzeczywistym. Znalazłem api w czasie rzeczywistym całkiem bezużyteczne, więc używam strategii długiego sondowania. Poniżej jest pseudokod z uwagami błędów sublte w nimChwytanie oznaczonych zdjęć Instagram w czasie rzeczywistym

newMediaCount = getMediaCount(); 
delta = newMediaCount - mediaCount; 
if (delta > 0) { 
    // if mediaCount changed by now, realDelta > delta, so realDelta - delta photos won't be grabbed and on next poll if mediaCount didn't change again realDelta - delta would be duplicated else ... 
    // if photo posted from private account last photo will be duplicated as counter changes but nothing is added to recent 
    recentMedia = getRecentMedia(delta); 
    // persist recentMedia 
    mediaCount = newMediaCount; 
} 

Druga sprawa może być skierowana z zestawem jakiegoś ja gueess. Ale najpierw naprawdę przeszkadza mi to. Przeniosłem dwa wywołania na instagram api tak blisko, jak to możliwe, ale czy to wystarczy?

Edit

Jak Amir zasugerował mam przepisany kod z wykorzystaniem min/max_tag_id s. Ale wciąż pomija zdjęcia. Nie mogłem znaleźć lepszego sposobu na przetestowanie tego, niż zapisywanie obrazów na dysku przez jakiś czas i porównywanie wyników z instagram.com/explore/tags/.

public class LousyInstagramApiTest { 

    @Test 
    public void testFeedContinuity() throws Exception { 
     Instagram instagram = new Instagram(Settings.getClientId()); 
     final String TAG_NAME = "portrait"; 
     String id = instagram.getRecentMediaTags(TAG_NAME).getPagination().getMinTagId(); 
     HashtagEndpoint endpoint = new HashtagEndpoint(instagram, TAG_NAME, id); 

     for (int i = 0; i < 10; i++) { 
      Thread.sleep(3000); 
      endpoint.recentFeed().forEach(d -> { 
       try { 
        URL url = new URL(d.getImages().getLowResolution().getImageUrl()); 
        BufferedImage img = ImageIO.read(url); 
        ImageIO.write(img, "png", new File("D:\\tmp\\" + d.getId() + ".png")); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      }); 
     } 
    } 
} 

class HashtagEndpoint { 
    private final Instagram instagram; 
    private final String hashtag; 
    private String minTagId; 

    public HashtagEndpoint(Instagram instagram, String hashtag, String minTagId) { 
     this.instagram = instagram; 
     this.hashtag = hashtag; 
     this.minTagId = minTagId; 
    } 

    public List<MediaFeedData> recentFeed() throws InstagramException { 
     TagMediaFeed feed = instagram.getRecentMediaTags(hashtag, minTagId, null); 
     List<MediaFeedData> dataList = feed.getData(); 
     if (dataList.size() == 0) return Collections.emptyList(); 

     String maxTagId = feed.getPagination().getNextMaxTagId(); 
     if (maxTagId != null && maxTagId.compareTo(minTagId) > 0) dataList.addAll(paginateFeed(maxTagId)); 
     Collections.reverse(dataList); 
//  dataList.removeIf(d -> d.getId().compareTo(minTagId) < 0); 

     minTagId = feed.getPagination().getMinTagId(); 
     return dataList; 
    } 

    private Collection<? extends MediaFeedData> paginateFeed(String maxTagId) throws InstagramException { 
     System.out.println("pagination required"); 

     List<MediaFeedData> dataList = new ArrayList<>(); 
     do { 
      TagMediaFeed feed = instagram.getRecentMediaTags(hashtag, null, maxTagId); 
      maxTagId = feed.getPagination().getNextMaxTagId(); 
      dataList.addAll(feed.getData()); 
     } while (maxTagId.compareTo(minTagId) > 0); 
     return dataList; 
    } 

} 
+0

Dlaczego znaleźć API Realtime bezużyteczne? Używam go teraz i działa dobrze. – Gonzalingui

+0

@Gonzalingui, ponieważ nie wysyła do Ciebie samych danych. Aby uzyskać dane, musisz użyć jednej z powyższych strategii, która nie działa. I nie możesz go użyć poza serwerem, na którym jestem. – user2418306

Odpowiedz

4

Używanie Tag endpoints aby uzyskać najnowsze nośniki z żądanym tagiem, zwraca min_tag_id w swojej informacji stronicowania, który jest przywiązany do ostatnio oznaczone mediów w czasie rozmowy. Ponieważ interfejs API akceptuje również parametr min_tag_id, można go przekazać z ostatniego zapytania, aby odbierać tylko te nośniki, które zostały oznaczone po ostatnim zapytaniu.

Opierając się na posiadanym mechanizmie odpytywania, wystarczy wywołać interfejs API, aby pobrać nowe ostatnie nośniki, jeśli takie są na podstawie ostatnio otrzymanego min_tag_id.

Należy również podać duży parametr count i postępować zgodnie z paginacją odpowiedzi, aby otrzymać wszystkie dane, nie tracąc niczego, gdy szybkość oznaczania jest szybsza niż w przypadku odpytywania.

Aktualizacja:
podstawie zaktualizowanego kodu:

public List<MediaFeedData> recentFeed() throws InstagramException { 
    TagMediaFeed feed = instagram.getRecentMediaTags(hashtag, minTagId, null, 100000); 
    List<MediaFeedData> dataList = feed.getData(); 
    if (dataList.size() == 0) return Collections.emptyList(); 

    // follow the pagination 
    MediaFeed recentMediaNextPage = instagram.getRecentMediaNextPage(feed.getPagination()); 
    while (recentMediaNextPage.getPagination() != null) { 
     dataList.addAll(recentMediaNextPage.getData()); 
     recentMediaNextPage = instagram.getRecentMediaNextPage(recentMediaNextPage.getPagination()); 
    } 

    Collections.reverse(dataList); 

    minTagId = feed.getPagination().getMinTagId(); 
    return dataList; 
} 
+0

Dziękuję za odpowiedź, przepraszam za spóźnioną odpowiedź. Testowałem to podejście i wpadałem na dziwne wyniki, które okazały się nie być specyficzne dla "min_tag_id", jak myślałem na początku. Na przykład. to połączenie https://api.instagram.com/v1/tags/partytools/media/recent?min_id=964461544535307126_444055843 nie zwraca mediów z określonym identyfikatorem, w rzeczywistości zwraca tylko 6 ostatnich postów. A jeśli pominąć 'min_id' i podać counter lub zapewnić oba daje tylko 6 ostatnich wpisów. Oto moje testy za pomocą jInstagram: http://pastebin.com/EnPRwMLw. Użyty tam shortcode pochodzi z dziewiątego zdjęcia. – user2418306

+0

To podejście spowodowało pominięcie niektórych zdjęć. – user2418306

+0

Robisz rzeczy nieco skomplikowane, samemu implementując podział na strony. Wystarczy wykonać jedno połączenie za pomocą 'min_tag_id' i postępować zgodnie z wbudowaną paginacją. Zobacz moją zaktualizowaną odpowiedź. –