Jak mogę pobrać multimedia użytkownika z Instagrama bez uwierzytelniania jako użytkownik?

175

Próbuję umieścić najnowsze media z Instagrama użytkownika na pasku bocznym. Próbuję użyć interfejsu API Instagrama, aby pobrać multimedia.

http://instagram.com/developer/endpoints/users/

Dokumentacja mówi o GET https://api.instagram.com/v1/users/<user-id>/media/recent/, ale mówi o przekazaniu tokenu dostępu OAuth. Token dostępu reprezentuje upoważnienie do działania w imieniu użytkownika. Nie chcę, aby użytkownicy logowali się na Instagramie, aby zobaczyć to na pasku bocznym. Nie powinni nawet mieć konta na Instagramie.

Na przykład mogę wejść na http://instagram.com/thebrainscoop bez logowania się na Instagramie i oglądać zdjęcia. Chcę to zrobić przez API.

W interfejsie API Instagrama żądania nieuwierzytelnione przez użytkownika przechodzą client_idzamiast pliku access_token. Jeśli jednak spróbuję, otrzymam:

{
  "meta":{
    "error_type":"OAuthParameterException",
    "code":400,
    "error_message":"\"access_token\" URL parameter missing. This OAuth request requires an \"access_token\" URL parameter."
  }
}

Więc czy to niemożliwe? Czy nie ma sposobu, aby pobrać najnowsze (publiczne) media użytkownika bez uprzedniego zalogowania się na konto Instagram za pośrednictwem protokołu OAuth?

Peeja
źródło
Jest to możliwe dzięki tej wtyczce, po prostu sprawdź kod źródłowy, w jaki sposób pobrali najnowsze publiczne media użytkownika, bez pytania użytkownika o zalogowanie się na swoje konto na Instagramie. : D smashballoon.com/instagram-feed/demo Potrzebujesz tylko identyfikatora klienta, bez tokena dostępu. : D
jehzlau
Musisz uwierzytelnić, aby mogli Cię śledzić i ograniczać pobieranie (stawki ...), jak każdy duży interfejs API. Jest publiczny dla prawdziwych użytkowników i publiczny dla scrapperów / botów, co zwykle nie jest tym samym, co prawdziwi użytkownicy zobaczą reklamy i bezpośrednio skorzystają z usługi.
Christophe Roussy
1
Żadna z tych metod już nie działa. Zobacz stackoverflow.com/questions/49852080/…
Moradnejad

Odpowiedzi:

123

To już późno, ale warto, jeśli komuś to pomoże, bo nie widziałem tego w dokumentacji Instagrama.

Aby wykonać GET https://api.instagram.com/v1/users/<user-id>/media/recent/(w chwili obecnej) nie potrzebujesz tokena dostępu OAuth.

Możesz występować https://api.instagram.com/v1/users/[USER ID]/media/recent/?client_id=[CLIENT ID]

[ID KLIENTA] byłby prawidłowym identyfikatorem klienta zarejestrowanym w aplikacji za pośrednictwem klientów zarządzających (niezwiązanych z żadnym użytkownikiem). Możesz uzyskać [USER ID] od nazwy użytkownika, wykonując żądanie wyszukiwania użytkowników GET: https://api.instagram.com/v1/users/search?q=[USERNAME]&client_id=[CLIENT ID]

Ersan J Sano
źródło
9
Myślę, że znowu zmienili zdanie. Otrzymuję tę samą odpowiedź o błędzie, jak pokazano w OP
James
35
Dotyczy to tylko aplikacji utworzonych przed 17 listopada 2015 r. I nie będzie w ogóle obsługiwane po czerwcu 2016 r. Następnie będziesz potrzebować oauth access_token. instagram.com/developer/changelog
Dax Fohl
211
To jest takie głupie i irytujące. Dlaczego mieliby zmuszać token dostępu tylko do wyświetlania obrazów, które są już publiczne ? Prawie nie próbuję ich spłukiwać dla każdego użytkownika na świecie, po prostu chcę wyświetlić najnowsze insta klienta bez konieczności spędzania godzin na majstrowaniu przy nim. Gah!
Matt Fletcher,
8
@ Limity stawek kabusa, kolego.
Walf
20
@MattFletcher jest teraz jeszcze głupszy, trzeba przejść przez przegląd uprawnień aplikacji i nie być pewien, czy jest to w ogóle wykonalne, ponieważ ten przypadek użycia „pokazanie własnego kanału klienta na jego własnej stronie internetowej” nie jest jednym z przypadków użycia. Aha, te ograniczenia są do niczego.
Ciantic
334

var name = "smena8m";
$.get("https://images"+~~(Math.random()*3333)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=https://www.instagram.com/" + name + "/", function(html) {
if (html) {
    var regex = /_sharedData = ({.*);<\/script>/m,
        json = JSON.parse(regex.exec(html)[1]),
        edges = json.entry_data.ProfilePage[0].graphql.user.edge_owner_to_timeline_media.edges;

      $.each(edges, function(n, edge) {
          var node = edge.node;
          $('body').append(
              $('<a/>', {
              href: 'https://instagr.am/p/'+node.shortcode,
              target: '_blank'
          }).css({
              backgroundImage: 'url(' + node.thumbnail_src + ')'
          }));
      });
    }
});
html, body {
  font-size: 0;
  line-height: 0;
}

a {
  display: inline-block;
  width: 25%;
  height: 0;
  padding-bottom: 25%;
  background: #eee 50% 50% no-repeat;
  background-size: cover;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Możesz pobrać dowolny kanał ze zdjęciami użytkownika Instagram w formacie JSON, używając ?__a=1obok adresu strony docelowej, takiego jak ten . Nie ma potrzeby uzyskiwania identyfikatora użytkownika ani rejestrowania aplikacji, żadnych tokenów ani protokołu OAuth.

min_ida max_idzmienne mogą być używane do paginacji, oto przykład

YQLmoże nie działać w wyciętej ramce iframe, więc zawsze możesz to sprawdzić ręcznie w Konsoli YQL

AKTUALIZACJA KWIECIEŃ 2018: Po najnowszych aktualizacjach na Instagramie nie można tego zrobić po stronie klienta (javascript), ponieważ niestandardowych nagłówków dla podpisanego żądania nie można ustawić za pomocą javascript ze względu na CORS Access-Control-Allow-Headersograniczenia. Jest jeszcze możliwość, aby to zrobić za pośrednictwem phplub jakiejkolwiek innej metody po stronie serwera z odpowiednim podpisem na bazie rhx_gis, csrf_tokenoraz parametrów żądania. Więcej na ten temat przeczytasz tutaj .

AKTUALIZACJA STYCZNIA 2019: YQL przeszedł na emeryturę, więc sprawdź moją najnowszą aktualizację z Google Image Proxy jako CORSproxy dla strony Instagram! Wtedy tylko moment negatywny - paginacja nie jest dostępna przy tej metodzie.

PHP rozwiązanie:

    $html = file_get_contents('https://instagram.com/apple/');
    preg_match('/_sharedData = ({.*);<\/script>/', $html, $matches);
    $profile_data = json_decode($matches[1])->entry_data->ProfilePage[0]->graphql->user;
350D
źródło
14
@ 350D Jak to znalazłeś? Nie mogę znaleźć tego nigdzie w ich dokumentacji. Chcę tylko przeczytać więcej o tym, co jest możliwe z tym punktem końcowym (obrazy kwadratowe EG vs inne niż kwadratowe, czy ma to zakończyć się w czerwcu itp.) - Dzięki!
Phil Johnston,
8
@Phil Johnston Tylko badanie 😀 Zrób jeszcze jedno - możesz dodać / media /? Size = L obok adresu URL strony docelowej zdjęcia i uzyskać zdjęcie w PEŁNEJ rozdzielczości.
350D
9
@ user2659694 W końcu znalazłem rozwiązanie, aby uzyskać kolejne strony za pomocą tej metody, której możesz użyć / media /? max_id = [MAX_ID]
Reza
3
FYI wydaje się, że działa to tylko wtedy, gdy jesteś sam zalogowany na konto Instagram. Spróbuj zrobić to w trybie incognito w Chrome lub podobnym, a zobaczysz, że odpowiedź JSON nie zawiera żadnych elementów. Próbowałem włączyć to do skryptu, aby uzyskać listę adresów URL na serwerze internetowym i musiałem wrócić do starych metod autoryzacji.
Ryan Zink
9
@RyanZink próbowałeś konta prywatnego? działa dobrze dla mnie wylogowanego lub incognito na kontach publicznych.
ryan
41

11.11.2017
Odkąd Instagram zmienił sposób dostarczania tych danych, żadna z powyższych metod nie działa obecnie. Oto nowy sposób uzyskiwania multimediów użytkownika:
GET https://instagram.com/graphql/query/?query_id=17888483320059182&variables={"id":"1951415043","first":20,"after":null}
Gdzie:
query_id- stała wartość: 17888483320059182 (uwaga może ulec zmianie w przyszłości).
id- identyfikator użytkownika. Może zawierać listę użytkowników. Aby uzyskać listę użytkowników, możesz skorzystać z następującego zapytania: GET https://www.instagram.com/web/search/topsearch/?context=blended&query=YOUR_QUERY
first- ilość przedmiotów do zdobycia.
after- id ostatniej pozycji, jeśli chcesz otrzymać przedmioty z tego id.

Footniko
źródło
Czy mógłbyś dać mi znać, skąd mam uzyskać identyfikator zapytania i identyfikator użytkownika?
Vijaysinh Parmar
2
@VijaysinhParmar, jak wspomniałem, query_idma stałą wartość. Oznacza to, że zawsze jest to 17888483320059182 (przynajmniej jeśli Instagram tego nie zmieni). id użytkownika - to identyfikator użytkownika (trochę zredagowałem moją odpowiedź)
Footniko
1
Nie pamiętam dokładnie, gdzieś w internecie. Ale nie mam żadnych relacji z Instagramem, więc gdyby to się zmieniło, nie będę w stanie powiedzieć ci nowego :(
Footniko
1
Zastanawiasz się, jaka jest polityka ograniczania tempa tego podejścia?
kkzxak47
1
Jeśli ktoś ma problemy z zażądaniem tego adresu URL przez żądanie CURL, musisz pobrać nagłówek żądania pliku cookie (otwórz kartę Sieci, po uruchomieniu adresu URL skopiuj nagłówek pliku cookie i wklej go do nagłówka żądania curl. Jeśli tego nie zrobisz, pojawi się błąd odmowy dostępu 403).
Anders,
40

Udało mi się uzyskać najnowsze media użytkownika za pomocą następującego interfejsu API bez uwierzytelniania (w tym opis, polubienia, liczba komentarzy).

https://www.instagram.com/apple/?__a=1

Na przykład

https://www.instagram.com/{username}/?__a=1
Michael
źródło
1
to też zadziałało w przypadku mnie, ale gdy „is_video = true”, brak adresu URL wideo w danych.
didikee
4
Racja, możesz pobrać tylko miniatury (nie sam film) - niestety nie znalazłem żadnej oficjalnej dokumentacji na ten temat i nie mam pojęcia, czy ten interfejs API jest przestarzały ani jak długo będzie obsługiwany.
Michael
8
Od 2018-04-13 wydaje się, że to już nie działa. Może z powodu ostatniego skandalu dotyczącego danych z Cambridge Analytica na Facebooku, zaostrzają sprawy o tonę. Jakieś inne sugestie dotyczące uzyskiwania podstawowych danych użytkownika bez uwierzytelniania?
BakerStreetSystems
2
Tak, był czas, kiedy to API nie działało - ale teraz jest znowu z powrotem
Michael
4
U mnie zadziałało, ale tylko wtedy, gdy jestem zalogowany na Instagramie.
zundi
16

W zeszłym tygodniu Instagram wyłączył /media/adresy URL, zaimplementowałem obejście, które na razie działa całkiem nieźle.

Aby rozwiązać problemy wszystkich w tym wątku, napisałem to: https://github.com/whizzzkid/instagram-reverse-proxy

Zapewnia wszystkie publiczne dane Instagrama przy użyciu następujących punktów końcowych:

Pobierz media użytkownika:

https://igapi.ga/<username>/media
e.g.: https://igapi.ga/whizzzkid/media 

Uzyskaj media użytkownika z limitem liczby:

https://igapi.ga/<username>/media?count=N // 1 < N < 20
e.g.: https://igapi.ga/whizzzkid/media?count=5

Użyj JSONP:

https://igapi.ga/<username>/media?callback=foo
e.g.: https://igapi.ga/whizzzkid/media?callback=bar

Interfejs API proxy dołącza również adresy URL następnej strony i poprzedniej strony do odpowiedzi, więc nie musisz tego obliczać na końcu.

Mam nadzieję, że wam się spodoba!

Dzięki @ 350D za dostrzeżenie tego :)

whizzzkid
źródło
1
@rex dopóki nie zmienią sposobu, w jaki wszystko działa po ich zakończeniu, jesteśmy dobrzy! Nie zawracali sobie głowy przez ostatnie 3 lata, prawdopodobnie nie zrobią tego przez następne 3
whizzzkid
3
@whizzzkid Pech, zmieniają to. Widziałem, że myślisz, że punkt końcowy użytkownika załatwi sprawę, ale istnieją limity żądań dla niezalogowanych użytkowników. Jakieś pomysły?
nobilik
1
@nobilik obejście jest na miejscu, igpi.ga/whizzzkid/media?count=3 i igpi.ga/graphql/query/?user_id=1606740656&count=3 powinny zwrócić Twoje dane. Pamiętaj, że niezdefiniowane strony odsyłające są wyłączone dla tych adresów URL.
whizzzkid
1
@whizzzkid - Got to działa! Wielkie dzięki - jesteś uczonym i dżentelmenem!
James Trickey
1
Otrzymuję błąd „Odmowa dostępu do strony odsyłającej”. Może to już nie działa?
khalid13
14

Interfejs API Instagrama wymaga uwierzytelnienia użytkownika przez OAuth, aby uzyskać dostęp do ostatniego punktu końcowego mediów dla użytkownika. Wydaje się, że obecnie nie ma innego sposobu na pobranie wszystkich multimediów dla użytkownika.

Bill Rollins
źródło
4
To nie ma sensu, jeśli chcę wyświetlać własne multimedia na własnej stronie internetowej, dlaczego potrzebuję, aby każdy, kto chce to zobaczyć, miał konto na Instagramie?
ninjasense
5
ninjasense - nie sądzę, że tak to działa. Myślę, że Twoja witryna musiałaby zawierać trochę kodu, który wysyłałby zapytania do interfejsu API Instagrama z danymi uwierzytelniającymi oauth podanymi w celu pobrania multimediów. Następnie możesz pokazać swoje multimedia wszystkim użytkownikom witryny. Twoja witryna byłaby jedyną rzeczą, która wymagałaby uwierzytelnienia na Instagramie.
Bill Rawlinson,
9

Jeśli szukasz sposobu na wygenerowanie tokena dostępu do użytku na jednym koncie, możesz spróbować tego -> https://coderwall.com/p/cfgneq .

Potrzebowałem sposobu, aby użyć interfejsu API Instagrama, aby pobrać wszystkie najnowsze multimedia dla określonego konta.

Craig Heneveld
źródło
5
To mniej więcej to, co ostatecznie zrobiłem: utworzyłem nowe konto, zrobiłem dla niego token dostępu i zapisałem ten token w mojej konfiguracji serwera obok klucza API. Jest to jednak kiepskie rozwiązanie dla aplikacji JS, ponieważ wymaga wysłania tokenu dostępu do użytkownika (co widziałem w wielu przykładowych kodach). Na szczęście mogę to zrobić po stronie serwera.
Peeja,
4
@CraigHeneveld W jaki sposób zapewniasz aktualność hat access_token? Czy to nie wygasło?
Ryan Ore
Czy token wygasa po jakimś czasie?
Monitus
Jeśli moja pamięć mi służy, klucz wygasa tylko wtedy, gdy zmienisz hasło. Oto kolejny wątek w tej sprawie -> stackoverflow.com/questions/22753170/…
Craig Heneveld
Jak możemy uzyskać wiele zdjęć użytkowników? Na przykład, czy możemy przekazać identyfikatory wielu użytkowników oddzielone znakiem „,”?
Aadil Keshwani,
9

Oto rozwiązania dla szyn. To coś w rodzaju tylnych drzwi, które w rzeczywistości są drzwiami frontowymi.

# create a headless browser
b = Watir::Browser.new :phantomjs
uri = 'https://www.instagram.com/explore/tags/' + query
uri = 'https://www.instagram.com/' + query if type == 'user'

b.goto uri

# all data are stored on this page-level object.
o = b.execute_script( 'return window._sharedData;')

b.close

Obiekt, który otrzymujesz, różni się w zależności od tego, czy jest to wyszukiwanie użytkownika, czy wyszukiwanie tagów. Otrzymuję takie dane:

if type == 'user'
  data = o[ 'entry_data' ][ 'ProfilePage' ][ 0 ][ 'user' ][ 'media' ][ 'nodes' ]
  page_info = o[ 'entry_data' ][ 'ProfilePage' ][ 0 ][ 'user' ][ 'media' ][ 'page_info' ]
  max_id = page_info[ 'end_cursor' ]
  has_next_page = page_info[ 'has_next_page' ]
else
  data = o[ 'entry_data' ][ 'TagPage' ][ 0 ][ 'tag' ][ 'media' ][ 'nodes' ]
  page_info = o[ 'entry_data' ][ 'TagPage' ][ 0 ][ 'tag' ][ 'media' ][ 'page_info' ]
  max_id = page_info[ 'end_cursor' ]
  has_next_page = page_info[ 'has_next_page' ]
end

Następnie otrzymuję kolejną stronę wyników, konstruując adres URL w następujący sposób:

  uri = 'https://www.instagram.com/explore/tags/' + query_string.to_s\
    + '?&max_id=' + max_id.to_s
  uri = 'https://www.instagram.com/' + query_string.to_s + '?&max_id='\
    + max_id.to_s if type === 'user'
Benjamin Talisman
źródło
to rozwiązanie działa dla mnie, ale mam z nim pewien problem. Po załadowaniu danych mój serwer railsowy (korzystający z Rails 5.0.0, serwer Puma 3.6.0) uruchamia się ponownie w niewytłumaczalny sposób ... Jakieś możliwe rozwiązanie?
Luis Eduardo Rojas Cabrera
8

Dzięki ciągle zmieniającemu się (i przerażająco zaprojektowanemu) schematowi API Instagrama, większość z powyższych nie będzie działać od kwietnia 2018 roku.

Oto najnowsza ścieżka dostępu do danych poszczególnych postów, jeśli odpytujesz ich API bezpośrednio przy użyciu tej https://www.instagram.com/username/?__a=1metody.

Zakładając, że zwrócone JSONdane $datamożesz przejrzeć każdy wynik, korzystając z następujących przykładów ścieżek:

foreach ($data->graphql->user->edge_owner_to_timeline_media->edges as $item) {

    $content_id = $item->node->id; 
    $date_posted = $item-node->taken_at_timestamp;
    $comments = $item->node->edge_media_to_comment->count;
    $likes = $item->node->edge_liked_by->count;
    $image = $item->node->display_url;
    $content = $item->node->edge_media_to_caption->edges[0]->node->text;
    // etc etc ....
}

Najważniejsze w tej ostatniej zmianie były graphqliedge_owner_to_timeline_media .

Wygląda na to, że w grudniu 2018 r. Zabiją dostęp do interfejsu API dla klientów niebędących klientami biznesowymi więc wykorzystaj go, póki możesz.

Mam nadzieję, że to komuś pomoże;)

przyprawa
źródło
To mi pomogło, chcę tylko pokazać najnowsze posty na Instagramie dla klienta. Dzięki!
weston deboer
1
instagram.com/username/?__a=1 wyświetla teraz błąd: Odmowa dostępu do www.instagram.com Nie masz uprawnień do przeglądania tej strony. BŁĄD HTTP 403 jakieś inne pomysły?
Hese
1
Tak, Instagram teraz to zabił. „Aby stale poprawiać prywatność i bezpieczeństwo użytkowników Instagrama, przyspieszamy wycofywanie platformy API Instagrama, wprowadzając w życie następujące zmiany natychmiast. Rozumiemy, że może to wpłynąć na Twoją działalność lub usługi i doceniamy Twoje wsparcie w utrzymaniu naszej platformy w bezpiecznym miejscu. Te funkcje zostaną natychmiast wyłączone (poprzednio ustawione na 31 lipca 2018 lub 11 grudnia 2018, wycofanie). ”
spice
Jeśli to, co czytam, jest poprawne, nie będzie już można odzyskać obrazów ani danych z dowolnego konta „niebiznesowego”. Całkowicie zabijają interfejs API platformy. Myślę, że to wtedy ... instagram.com/developer/changelog
spice
1
@james_tookey nie będzie możliwy kolego. Ze względu na nowe ograniczenia prywatności nie będzie już w stanie wysyłać zapytań ani pobierać danych użytkowników / danych z kont osobistych, tylko tych biznesowych. Po prostu zabili całe użycie API dla kont osobistych.
spice
7

JSFiddle

JavaScript:

$(document).ready(function(){

    var username = "leomessi";
    var max_num_items = 5;

    var jqxhr = $.ajax( "https://www.instagram.com/"+username+"/?__a=1" ).done(function() {
        //alert( "success" );
    }).fail(function() {
        //alert( "error" );
    }).always(function(data) {
        //alert( "complete" )
        items = data.graphql.user.edge_owner_to_timeline_media.edges;
        $.each(items, function(n, item) {
            if( (n+1) <= max_num_items )
            {
                var data_li = "<li><a target='_blank' href='https://www.instagram.com/p/"+item.node.shortcode+"'><img src='" + item.node.thumbnail_src + "'/></a></li>";
                $("ul.instagram").append(data_li);
            }
        });

    });

});

HTML:

<ul class="instagram">
</ul>

CSS:

ul.instagram {
    list-style: none;
}

ul.instagram li {
  float: left;
}

ul.instagram li img {
    height: 100px;
}
Lew
źródło
5

Chcę tylko dodać do odpowiedzi @ 350D, ponieważ było mi trudno to zrozumieć.

Moja logika w kodzie jest następna:

Podczas pierwszego wywoływania API dzwonię tylko https://www.instagram.com/_vull_ /media/. Kiedy otrzymuję odpowiedź, sprawdzam wartość logiczną more_available. Jeśli to prawda, pobieram ostatnie zdjęcie z tablicy, pobieram jego id, a następnie ponownie wywołuję API Instagrama, ale tym razem https://www.instagram.com/_vull_/media/?max_id=1400286183132701451_1642962433.

Ważna rzecz, o której należy wiedzieć, ten identyfikator jest identyfikatorem ostatniego obrazu w tablicy. Więc pytając o maxId z ostatnim identyfikatorem obrazu w tablicy, otrzymasz następne 20 obrazów i tak dalej.

Mam nadzieję, że to wyjaśnia sprawy.

Vulovic Vukasin
źródło
4

Jeśli pominiesz Oauth, prawdopodobnie nie wiesz, który z nich jest użytkownikiem Instagrama. Mając to na uwadze, istnieje kilka sposobów na uzyskanie obrazów z Instagrama bez uwierzytelniania.

  1. Interfejs API Instagrama umożliwia przeglądanie najpopularniejszych obrazów użytkownika bez uwierzytelniania. Korzystanie z następującego punktu końcowego: Oto link

  2. Instagram zapewnia kanały RSS dla tagów w tym miejscu .

  3. Strony użytkowników Instagrama są publiczne, więc możesz użyć PHP z CURL, aby uzyskać ich stronę i parser DOM, aby przeszukać kod HTML pod kątem żądanych tagów graficznych.

Dorian Damon
źródło
9
Wydaje się nieaktualne.
Burak Tokak
czy można ominąć uwierzytelnianie dla instagramu
JAck
3

Jeszcze jedna sztuczka, szukaj zdjęć według hashtagów:

GET https://www.instagram.com/graphql/query/?query_hash=3e7706b09c6184d5eafd8b032dbcf487&variables={"tag_name":"nature","first":25,"after":""}

Gdzie:

query_hash - stała wartość (wierzę, że jej hash to 17888483320059182, może zostać zmieniony w przyszłości)

tag_name - tytuł mówi sam za siebie

first - ilość przedmiotów do zdobycia (nie wiem dlaczego, ale ta wartość nie działa zgodnie z oczekiwaniami. Rzeczywista liczba zwróconych zdjęć jest nieco większa niż wartość pomnożona przez 4,5 (około 110 dla wartości 25 i około 460 dla wartości wartość 100))

after- id ostatniej pozycji, jeśli chcesz otrzymać przedmioty z tego id. W tym miejscu end_cursormożna użyć wartości z odpowiedzi JSON.

kara4k
źródło
Jak to znalazłeś?
ekntrtmz
3

Jeśli chcesz wyszukiwać użytkowników bez identyfikatora klienta i tokena dostępu:

1: Jeśli chcesz wyszukać wszystkich użytkowników, których nazwy są podobne do wyszukiwanego słowa:

zamień SeachName na tekst, który chcesz przeszukać:

https://www.instagram.com/web/search/topsearch/?query=SearchName

2: jeśli chcesz wyszukać dokładnie tę samą nazwę użytkownika:

zamień nazwę użytkownika na żądaną nazwę wyszukiwania:

https://www.instagram.com/UserName/?__a=1

Rahul Gusain
źródło
2

Można użyć tego API pobierać publicznej informacji użytkownika Instagram:
https://api.lityapp.com/instagrams/thebrainscoop?limit=2

Jeśli nie ustawić parametr limit, słupki są ograniczone na 12 domyślnie

This api zostało stworzone w SpringBoot z HtmlUnit, jak widać w kodzie:

public JSONObject getPublicInstagramByUserName(String userName, Integer limit) {
    String html;
    WebClient webClient = new WebClient();

    try {
        webClient.getOptions().setCssEnabled(false);
        webClient.getOptions().setJavaScriptEnabled(false);
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        webClient.getCookieManager().setCookiesEnabled(true);

        Page page = webClient.getPage("https://www.instagram.com/" + userName);
        WebResponse response = page.getWebResponse();

        html = response.getContentAsString();
    } catch (Exception ex) {
        ex.printStackTrace();

        throw new RuntimeException("Ocorreu um erro no Instagram");
    }

    String prefix = "static/bundles/es6/ProfilePageContainer.js";
    String sufix = "\"";
    String script = html.substring(html.indexOf(prefix));

    script = script.substring(0, script.indexOf(sufix));

    try {
        Page page = webClient.getPage("https://www.instagram.com/" + script);
        WebResponse response = page.getWebResponse();

        script = response.getContentAsString();
    } catch (Exception ex) {
        ex.printStackTrace();

        throw new RuntimeException("Ocorreu um erro no Instagram");
    }

    prefix = "l.pagination},queryId:\"";

    String queryHash = script.substring(script.indexOf(prefix) + prefix.length());

    queryHash = queryHash.substring(0, queryHash.indexOf(sufix));
    prefix = "<script type=\"text/javascript\">window._sharedData = ";
    sufix = ";</script>";
    html = html.substring(html.indexOf(prefix) + prefix.length());
    html = html.substring(0, html.indexOf(sufix));

    JSONObject json = new JSONObject(html);
    JSONObject entryData = json.getJSONObject("entry_data");
    JSONObject profilePage = (JSONObject) entryData.getJSONArray("ProfilePage").get(0);
    JSONObject graphql = profilePage.getJSONObject("graphql");
    JSONObject user = graphql.getJSONObject("user");
    JSONObject response = new JSONObject();

    response.put("id", user.getString("id"));
    response.put("username", user.getString("username"));
    response.put("fullName", user.getString("full_name"));
    response.put("followedBy", user.getJSONObject("edge_followed_by").getLong("count"));
    response.put("following", user.getJSONObject("edge_follow").getLong("count"));
    response.put("isBusinessAccount", user.getBoolean("is_business_account"));
    response.put("photoUrl", user.getString("profile_pic_url"));
    response.put("photoUrlHD", user.getString("profile_pic_url_hd"));

    JSONObject edgeOwnerToTimelineMedia = user.getJSONObject("edge_owner_to_timeline_media");
    JSONArray posts = new JSONArray();

    try {
        loadPublicInstagramPosts(webClient, queryHash, user.getString("id"), posts, edgeOwnerToTimelineMedia, limit == null ? 12 : limit);
    } catch (Exception ex) {
        ex.printStackTrace();

        throw new RuntimeException("Você fez muitas chamadas, tente mais tarde");
    }

    response.put("posts", posts);

    return response;
}

private void loadPublicInstagramPosts(WebClient webClient, String queryHash, String userId, JSONArray posts, JSONObject edgeOwnerToTimelineMedia, Integer limit) throws IOException {
    JSONArray edges = edgeOwnerToTimelineMedia.getJSONArray("edges");

    for (Object elem : edges) {
        if (limit != null && posts.length() == limit) {
            return;
        }

        JSONObject node = ((JSONObject) elem).getJSONObject("node");

        if (node.getBoolean("is_video")) {
            continue;
        }

        JSONObject post = new JSONObject();

        post.put("id", node.getString("id"));
        post.put("shortcode", node.getString("shortcode"));

        JSONArray captionEdges = node.getJSONObject("edge_media_to_caption").getJSONArray("edges");

        if (captionEdges.length() > 0) {
            JSONObject captionNode = ((JSONObject) captionEdges.get(0)).getJSONObject("node");

            post.put("caption", captionNode.getString("text"));
        } else {
            post.put("caption", (Object) null);
        }

        post.put("photoUrl", node.getString("display_url"));

        JSONObject dimensions = node.getJSONObject("dimensions");

        post.put("photoWidth", dimensions.getLong("width"));
        post.put("photoHeight", dimensions.getLong("height"));

        JSONArray thumbnailResources = node.getJSONArray("thumbnail_resources");
        JSONArray thumbnails = new JSONArray();

        for (Object elem2 : thumbnailResources) {
            JSONObject obj = (JSONObject) elem2;
            JSONObject thumbnail = new JSONObject();

            thumbnail.put("photoUrl", obj.getString("src"));
            thumbnail.put("photoWidth", obj.getLong("config_width"));
            thumbnail.put("photoHeight", obj.getLong("config_height"));
            thumbnails.put(thumbnail);
        }

        post.put("thumbnails", thumbnails);
        posts.put(post);
    }

    JSONObject pageInfo = edgeOwnerToTimelineMedia.getJSONObject("page_info");

    if (!pageInfo.getBoolean("has_next_page")) {
        return;
    }

    String endCursor = pageInfo.getString("end_cursor");
    String variables = "{\"id\":\"" + userId + "\",\"first\":12,\"after\":\"" + endCursor + "\"}";

    String url = "https://www.instagram.com/graphql/query/?query_hash=" + queryHash + "&variables=" + URLEncoder.encode(variables, "UTF-8");
    Page page = webClient.getPage(url);
    WebResponse response = page.getWebResponse();
    String content = response.getContentAsString();
    JSONObject json = new JSONObject(content);

    loadPublicInstagramPosts(webClient, queryHash, userId, posts, json.getJSONObject("data").getJSONObject("user").getJSONObject("edge_owner_to_timeline_media"), limit);
}


Oto przykład odpowiedzi:

{
  "id": "290482318",
  "username": "thebrainscoop",
  "fullName": "Official Fan Page",
  "followedBy": 1023,
  "following": 6,
  "isBusinessAccount": false,
  "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/447ffd0262082f373acf3d467435f130/5C709C77/t51.2885-19/11351770_612904665516559_678168252_a.jpg",
  "photoUrlHD": "https://scontent-gru2-1.cdninstagram.com/vp/447ffd0262082f373acf3d467435f130/5C709C77/t51.2885-19/11351770_612904665516559_678168252_a.jpg",
  "posts": [
    {
      "id": "1430331382090378714",
      "shortcode": "BPZjtBUly3a",
      "caption": "If I have any active followers anymore; hello! I'm Brianna, and I created this account when I was just 12 years old to show my love for The Brain Scoop. I'm now nearly finished high school, and just rediscovered it. I just wanted to see if anyone is still active on here, and also correct some of my past mistakes - being a child at the time, I didn't realise I had to credit artists for their work, so I'm going to try to correct that post haste. Also; the font in my bio is horrendous. Why'd I think that was a good idea? Anyway, this is a beautiful artwork of the long-tailed pangolin by @chelsealinaeve . Check her out!",
      "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/ab823331376ca46136457f4654bf2880/5CAD48E4/t51.2885-15/e35/16110915_400942200241213_3503127351280009216_n.jpg",
      "photoWidth": 640,
      "photoHeight": 457,
      "thumbnails": [
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/43b195566d0ef2ad5f4663ff76d62d23/5C76D756/t51.2885-15/e35/c91.0.457.457/s150x150/16110915_400942200241213_3503127351280009216_n.jpg",
          "photoWidth": 150,
          "photoHeight": 150
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/ae39043a7ac050c56d741d8b4355c185/5C93971C/t51.2885-15/e35/c91.0.457.457/s240x240/16110915_400942200241213_3503127351280009216_n.jpg",
          "photoWidth": 240,
          "photoHeight": 240
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/ae7a22d09e3ef98d0a6bbf31d621a3b7/5CACBBA6/t51.2885-15/e35/c91.0.457.457/s320x320/16110915_400942200241213_3503127351280009216_n.jpg",
          "photoWidth": 320,
          "photoHeight": 320
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/1439dc72b70e7c0c0a3afcc30970bb13/5C8E2923/t51.2885-15/e35/c91.0.457.457/16110915_400942200241213_3503127351280009216_n.jpg",
          "photoWidth": 480,
          "photoHeight": 480
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/1439dc72b70e7c0c0a3afcc30970bb13/5C8E2923/t51.2885-15/e35/c91.0.457.457/16110915_400942200241213_3503127351280009216_n.jpg",
          "photoWidth": 640,
          "photoHeight": 640
        }
      ]
    },
    {
      "id": "442527661838057235",
      "shortcode": "YkLJBXJD8T",
      "caption": null,
      "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/dc94b38da679826b9ac94ccd2bcc4928/5C7CDF93/t51.2885-15/e15/11327349_860747310663863_2105199307_n.jpg",
      "photoWidth": 612,
      "photoHeight": 612,
      "thumbnails": [
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/c1153c6513c44a6463d897e14b2d8f06/5CB13ADD/t51.2885-15/e15/s150x150/11327349_860747310663863_2105199307_n.jpg",
          "photoWidth": 150,
          "photoHeight": 150
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/47e60ec8bca5a1382cd9ac562439d48c/5CAE6A82/t51.2885-15/e15/s240x240/11327349_860747310663863_2105199307_n.jpg",
          "photoWidth": 240,
          "photoHeight": 240
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/da0ee5b666ab40e4adc1119e2edca014/5CADCB59/t51.2885-15/e15/s320x320/11327349_860747310663863_2105199307_n.jpg",
          "photoWidth": 320,
          "photoHeight": 320
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/02ee23571322ea8d0992e81e72f80ef2/5C741048/t51.2885-15/e15/s480x480/11327349_860747310663863_2105199307_n.jpg",
          "photoWidth": 480,
          "photoHeight": 480
        },
        {
          "photoUrl": "https://scontent-gru2-1.cdninstagram.com/vp/dc94b38da679826b9ac94ccd2bcc4928/5C7CDF93/t51.2885-15/e15/11327349_860747310663863_2105199307_n.jpg",
          "photoWidth": 640,
          "photoHeight": 640
        }
      ]
    }
  ]
}
Ruan Barroso
źródło
czy mogę uzyskać dane według identyfikatora użytkownika (pk)
SAURABH RATHOD,
Przepraszam @SAURABHRATHOD Próbowałem, ale nie znalazłem sposobu, aby to zrobić. Byłbym bardzo zadowolony, gdyby ktoś to rozwiązał. Dziękuję za komentarz.
Ruan Barroso
2

Naprawdę potrzebowałem tej funkcji, ale dla Wordpress. Pasowałem i działało idealnie

<script>
    jQuery(function($){
        var name = "caririceara.comcariri";
        $.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=https://www.instagram.com/" + name + "/", function(html) {
            if (html) {
                var regex = /_sharedData = ({.*);<\/script>/m,
                  json = JSON.parse(regex.exec(html)[1]),
                  edges = json.entry_data.ProfilePage[0].graphql.user.edge_owner_to_timeline_media.edges;
              $.each(edges, function(n, edge) {
                   if (n <= 7){
                     var node = edge.node;
                    $('.img_ins').append('<a href="https://instagr.am/p/'+node.shortcode+'" target="_blank"><img src="'+node.thumbnail_src+'" width="150"></a>');
                   }
              });
            }
        });
    }); 
    </script>
Karra Max
źródło
1

Poniższy kod nodejs usuwa popularne obrazy ze strony na Instagramie. Funkcja „ScrapeInstagramPage” dba o efekt post starzenia.

var request = require('parse5');
var request = require('request');
var rp      = require('request-promise');
var $       = require('cheerio'); // Basically jQuery for node.js 
const jsdom = require("jsdom");    
const { JSDOM } = jsdom;


function ScrapeInstagramPage (args) {
    dout("ScrapeInstagramPage for username -> " + args.username);
    var query_url = 'https://www.instagram.com/' + args.username + '/';

    var cookieString = '';

    var options = {
        url: query_url,
        method: 'GET',
        headers: {
            'x-requested-with' : 'XMLHttpRequest',
            'accept-language'  : 'en-US,en;q=0.8,pt;q=0.6,hi;q=0.4', 
            'User-Agent'       : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
            'referer'          : 'https://www.instagram.com/dress_blouse_designer/',
            'Cookie'           : cookieString,
            'Accept'           : '*/*',
            'Connection'       : 'keep-alive',
            'authority'        : 'www.instagram.com' 
        }
    };


    function dout (msg) {
        if (args.debug) {
            console.log(msg);
        }
    }

    function autoParse(body, response, resolveWithFullResponse) {
        // FIXME: The content type string could contain additional values like the charset. 
        // Consider using the `content-type` library for a robust comparison. 
        if (response.headers['content-type'] === 'application/json') {
            return JSON.parse(body);
        } else if (response.headers['content-type'] === 'text/html') {
            return $.load(body);
        } else {
            return body;
        }
    }

    options.transform = autoParse;


    rp(options)
        .then(function (autoParsedBody) {
            if (args.debug) {
                console.log("Responce of 'Get first user page': ");
                console.log(autoParsedBody);
                console.log("Creating JSDOM from above Responce...");
            }

            const dom = new JSDOM(autoParsedBody.html(), { runScripts: "dangerously" });
            if (args.debug) console.log(dom.window._sharedData); // full data doc form instagram for a page

            var user = dom.window._sharedData.entry_data.ProfilePage[0].user;
            if (args.debug) {
                console.log(user); // page user
                console.log(user.id); // user ID
                console.log(user.full_name); // user full_name
                console.log(user.username); // user username
                console.log(user.followed_by.count); // user followed_by
                console.log(user.profile_pic_url_hd); // user profile pic
                console.log(autoParsedBody.html());
            }

            if (user.is_private) {
                dout ("User account is PRIVATE");
            } else {
                dout ("User account is public");
                GetPostsFromUser(user.id, 5000, undefined);
            }
        })
        .catch(function (err) {
            console.log( "ERROR: " + err );
        });  

    var pop_posts = [];
    function GetPostsFromUser (user_id, first, end_cursor) {
        var end_cursor_str = "";
        if (end_cursor != undefined) {
            end_cursor_str = '&after=' + end_cursor;
        }

        options.url = 'https://www.instagram.com/graphql/query/?query_id=17880160963012870&id=' 
                        + user_id + '&first=' + first + end_cursor_str;

        rp(options)
            .then(function (autoParsedBody) {
                if (autoParsedBody.status === "ok") {
                    if (args.debug) console.log(autoParsedBody.data);
                    var posts = autoParsedBody.data.user.edge_owner_to_timeline_media;

                    // POSTS processing
                    if (posts.edges.length > 0) {
                        //console.log(posts.edges);
                        pop_posts = pop_posts.concat
                        (posts.edges.map(function(e) {
                            var d = new Date();
                            var now_seconds = d.getTime() / 1000;

                            var seconds_since_post = now_seconds - e.node.taken_at_timestamp;
                            //console.log("seconds_since_post: " + seconds_since_post);

                            var ageing = 10; // valuses (1-10]; big value means no ageing
                            var days_since_post = Math.floor(seconds_since_post/(24*60*60));
                            var df = (Math.log(ageing+days_since_post) / (Math.log(ageing)));
                            var likes_per_day = (e.node.edge_liked_by.count / df);
                            // console.log("likes: " + e.node.edge_liked_by.count);
                            //console.log("df: " + df);
                            //console.log("likes_per_day: " + likes_per_day);
                            //return (likes_per_day > 10 * 1000);
                            var obj = {};
                            obj.url = e.node.display_url;
                            obj.likes_per_day = likes_per_day;
                            obj.days_since_post = days_since_post;
                            obj.total_likes = e.node.edge_liked_by.count;
                            return obj;
                        }
                        ));

                        pop_posts.sort(function (b,a) {
                          if (a.likes_per_day < b.likes_per_day)
                            return -1;
                          if (a.likes_per_day > b.likes_per_day)
                            return 1;
                          return 0;
                        });

                        //console.log(pop_posts);

                        pop_posts.forEach(function (obj) {
                            console.log(obj.url);
                        });
                    }

                    if (posts.page_info.has_next_page) {
                        GetPostsFromUser(user_id, first, posts.page_info.end_cursor);
                    }
                } else {
                    console.log( "ERROR: Posts AJAX call not returned good..." );
                }
            })
            .catch(function (err) {
                console.log( "ERROR: " + err );
            }); 
    }
}


ScrapeInstagramPage ({username : "dress_blouse_designer", debug : false});

Spróbuj tutaj

Przykład: dla danego adresu URL „ https://www.instagram.com/dress_blouse_designer/ ” można wywołać funkcję

ScrapeInstagramPage ({username : "dress_blouse_designer", debug : false});
Vishnu Kanwar
źródło
Widzę tylko pierwsze 12 postów, jak mogę je wszystkie zdobyć?
rahul gawale
0

Działa to przy użyciu prostego wywołania ajax i iteracji ścieżek obrazu.

        var name = "nasa";
        $.get("https://www.instagram.com/" + name + "/?__a=1", function (data, status) {
            console.log('IG_NODES', data.user.media.nodes);
            $.each(data.user.media.nodes, function (n, item) {
                console.log('ITEMS', item.display_src);
                $('body').append(
                    "<div class='col-md-4'><img class='img-fluid d-block' src='" + item.display_src + "'></div>"
                );
            });
        })
Evin Weissenberg
źródło
U mnie zadziałało, ale tylko wtedy, gdy jestem zalogowany na Instagramie.
zundi
-1

Oto skrypt php, który pobiera obrazy i tworzy plik html z linkami do obrazów. Kredyt 350D dla wersji php, to jest właśnie rozwinięte. Sugerowałbym umieszczenie tego zadania w cronie i odpalanie, jak często potrzebujesz. Zweryfikowano działanie na maj 2019 .

<?
$user = 'smena8m';
$igdata = file_get_contents('https://instagram.com/'.$user.'/');
preg_match('/_sharedData = ({.*);<\/script>/',$igdata,$matches);
$profile_data = json_decode($matches[1])->entry_data->ProfilePage[0]->graphql->user;
$html = '<div class="instagramBox" style="display:inline-grid;grid-template-columns:auto auto auto;">';
$i = 0;
$max = 9;
while($i<$max){
    $imglink = $profile_data->edge_owner_to_timeline_media->edges[$i]->node->shortcode;
    $img = $profile_data->edge_owner_to_timeline_media->edges[$i]->node->thumbnail_resources[0]->src;
    file_put_contents('ig'.$i.'.jpg',file_get_contents($img));
    $html .= '<a href="https://www.instagram.com/p/'.$imglink.'/" target="_blank"><img src="ig'.$i.'.jpg" /></a>';
    $i++;
}
$html .= '</div>';
$instagram = fopen('instagram.html','w');
fwrite($instagram,$html);
fclose($instagram);
?>
drooh
źródło