Przejdź do treści

Instagram – zbieranie danych i bot

Konto na Instagramie mam od kwietnia 2012 roku, ale nie zajmuje on mojego czasu (nie zaglądam tam wcale). Kiedyś chciałem sprawdzić czy zdjęcia z tagu #warszawa są zrobione w Warszawie, ale nie sprawdziłem… Do dzisiaj.

Tekst How I Eat For Free in NYC Using Python, Automation, Artificial Intelligence, and Instagram który robi furorę w ostatnich dniach sprawił, że wreszcie ruszyłem tyłek i zająłem się tematem. Kilka miesięcy temu widziałem tutorial How to Get Instagram Followers/Likes Using Python, dzisiaj spróbujemy w R.

Celem będzie sprawdzenie tej Warszawy i na tym się skupimy, ale narzędzie powinno być uniwersalne, zatem uniwersalnie do niego podejdziemy.

Z niniejszego wpisu dowiesz się:

  • jak pobrać informacje o zdjęciu z Instagrama
  • jak pobrać listę najnowszych zdjęć użytkownika
  • oraz najnowszych i najpopularniejszych zdjęć z tagu
  • jak automatycznie dać like i napisać komentarz do zdjęcia
  • jak podglądać co automat klika w przeglądarce (odpalonej przez Dockera) z użyciem klienta VNC
  • a także zobaczysz kilka podstawowych danych o zdjęciach zebranych z tagów #warszawa i #warsaw

Pobieranie danych z Instagrama

Zaczniemy od przygotowania funkcji zbierającej informacje o zdjęciu. Wchodzimy na Instagrama przez przeglądarkę WWW, wybieramy dowolne zdjęcie (nie kolekcję i nie wideo!) i zaglądamy w kod strony. Nie musimy mieć konta, nie musimy być na nim zalogowani. Ta część wpisu opiera się o zwykły scrapping strony.

Właściwie pełne informacje znajdziemy w kodzie w postaci JSONa – znakomicie ułatwia to pracę, nie trzeba szukać odpowiednich tagów HTML, wszystko podane jest na tacy. Część elementów jest też jest w nagłówku strony. Z pomocą selektorów XPath wydobywamy poszczególne fragmenty strony (w tym wspomnianego JSONa), a następnie nieco je przekształcamy jeśli trzeba. Pełna funkcja poniżej (komentarze tłumaczą co i jak), potrzebne pakiety to: tidyverse, rvest, jsonlite oraz lubridate.

Przykładowy wynik dla mojego testowego zdjęcia o ID BvUAaQkFb9_ (zobacz je na Insta, zerknij w kod źródłowy strony) będzie następujący:

post_id post_author post_title post_created post_location image_url hashtags like_count comment_count comments
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 1553258410 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com c(“warszawa”, “datascience”, “analiza”, “analizadanych”) 8 2 list(comment_author = c(“bobiko”, “lemur_78”), text = c(“w pythonie czy w go?”, “@bobiko w R”))

Elementy w kolumnach hashtags oraz comments są zagnieżdżone (po to, aby finalnie mieć jeden wiersz dla każdego postu), można je rozwinąć:

post_id post_author post_title post_created post_location image_url like_count comment_count hashtags comment_author text
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 analizadanych bobiko w pythonie czy w go?
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 analizadanych lemur_78 @bobiko w R
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 analiza bobiko w pythonie czy w go?
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 analiza lemur_78 @bobiko w R
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 warszawa bobiko w pythonie czy w go?
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 warszawa lemur_78 @bobiko w R
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 datascience bobiko w pythonie czy w go?
BvUAaQkFb9_ lemur_78 Się inwestyguje instagrama na tagu #warszawa #analiza #analizadanych #datascience 2019-03-22 13:40:10 Warsaw, Poland https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2 datascience lemur_78 @bobiko w R

Widzimy, że liczba wierszy po rozwinięciu zagnieżdżeń rośnie, a wiele kolumn zawiera zduplikowane informacje. Stąd właśnie zagnieżdżenie w kolumnach.

No i ważna sprawa – informacja o liczbie komentarzy, lajków czy treść samych komentarzy pobierana jest na dany moment – to oczywiście się zmienia i jeśli chcemy mieć najświeższe dane to trzeba dany post pobrać jeszcze raz.

Dobrze, umiemy dobrać się do jednego zdjęcia, a co z pojedynczym użytkownikiem? Kolejna funkcja:

która w efekcie daje nam:

post_id post_created image_url like_count comment_count
BvWcr05FZI3 2019-03-23 13:25:43 https://scontent-waw1-1.cdninstagram.com/vp/f9524d417193ec3b41a006c2e8449f2d/5D2F87F7/t51.2885-15/e35/53823369_2057664951019247_4473442439456346066_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 13 0
BvUAaQkFb9_ 2019-03-22 14:40:10 https://scontent-waw1-1.cdninstagram.com/vp/4d59875de95353bf067c10a3300267bb/5D17FF07/t51.2885-15/e35/53226574_2260585120695438_4429725531160779195_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 2
Bs0rDwMF9ct 2019-01-19 17:34:21 https://scontent-waw1-1.cdninstagram.com/vp/f1361dd74870568525675d551e89b437/5D4C100B/t51.2885-15/fr/e15/s1080x1080/46758889_1319731371503046_6087482114854365775_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 0
Bjz4uz1hkFF 2018-06-09 18:32:02 https://scontent-waw1-1.cdninstagram.com/vp/1e1403a9fb6e746c381a355eeea252c8/5D150892/t51.2885-15/e35/33841721_1021196438049522_2703779893920923648_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 1 0
Bire6zehmDX 2018-05-12 15:41:10 https://scontent-waw1-1.cdninstagram.com/vp/5fd3562b402d3aae80bd507adf83a548/5D465538/t51.2885-15/e35/32157535_238218890091075_6016316108640878592_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 3 0
BiXH02TBznR 2018-05-04 17:54:34 https://scontent-waw1-1.cdninstagram.com/vp/6fe44395bc63a4ed76fb16e055c8b13b/5D45979A/t51.2885-15/e35/30953971_1879380748750489_3668880425679323136_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 7 2
BXYcuXBHD8- 2017-08-04 20:31:05 https://scontent-waw1-1.cdninstagram.com/vp/83532c3d2a04cb4e93fef34e473e1d49/5D4A3082/t51.2885-15/e35/20633305_1510834248980095_3378422129732091904_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 4 0
BVmxlESnRBf 2017-06-21 16:59:53 https://scontent-waw1-1.cdninstagram.com/vp/ea184da1d22a288f558a75c2aa1426c6/5D49E9DC/t51.2885-15/e35/19366963_1350842421666361_1421712412100263936_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 7 0
BVXa-Fsn4rB 2017-06-15 17:53:43 https://scontent-waw1-1.cdninstagram.com/vp/9c011f11c41cf5101bd3903dcd8f53db/5D506B69/t51.2885-15/e35/19227511_349490455467156_7531117435756216320_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 1 0
BU4x5uphkpz 2017-06-03 20:17:39 https://scontent-waw1-1.cdninstagram.com/vp/6d458c747e6dcc25386b8c30b8a19c66/5D41FCA4/t51.2885-15/e35/18879426_1855326008125510_4893078652025044992_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 4 0
BSVofbMhstl 2017-04-01 11:39:12 https://scontent-waw1-1.cdninstagram.com/vp/e1f331a8d0d0656d3f54575273273ec7/5D33AD83/t51.2885-15/e35/17662481_254903208306221_8865474958994702336_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 0
BOpsLjmgRIO 2016-12-30 19:30:41 https://scontent-waw1-1.cdninstagram.com/vp/d0836ada39cab7018158b22e0e12b246/5D31BA42/t51.2885-15/e35/15624737_170607886750773_1653574671091630080_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 1 0

czyli podstawowe informacje o najnowszych 12 zdjęciach z profilu, w tym:

  • id zdjęcia
  • datę jego utworzenia
  • link do zdjęcia
  • liczbę komentarzy
  • liczbę like’ów

Dlaczego tylko 12 sztuk? Ano dlatego, że strony Instagrama są dynamiczne (i to w dość pokręcony sposób) – kolejne elementy dociągają się przy skrolowaniu strony w dół. Pakiet rvest tego nie obsłuży, trzeba by inaczej do tego podejść jeśli chcielibyśmy ściągnąć całą zawartość profilu.

Pytanie tylko czy jest to potrzebne? W maszynie, którą sobie przygotowałem na potrzeby zebrania danych do niniejszego wpisu założyłem, że to wystarczy. Można odwiedzić profil co jakiś czas (co ile to zależy od profilu – niektóre wrzucają zdjęcia tonami, inne raz na jakiś czas) i gromadzić tylko nowe zdjęcia. Kwestia potrzeby biznesowej.

Mając ID kolejnych zdjęć możemy oczywiście wywołać funkcję get_post_details() dla kolejnych ID i zebrać nieco więcej informacji (np. tagi). Na stronie profilu niestety informacji o tagach poszczególnych zdjęć nie mamy.

Zwrócicie też uwagę, że nie zbieramy informacji opisujących sam profil (liczba wszystkich postów, obrazek profilowy, jakieś dodatkowe opisy). Znowu: w tym zadaniu to nie są potrzebne informacje.

Celem jest sprawdzenie czy zdjęcia z tagu #warszawa są zrobione w Warszawie. Zatem potrzebujemy jeszcze pobrać dane ze strony samego tagu (bo skąd wiedzieć jakie profile publikują na tagu?). Kolejna funkcja, dość podobna do tej pobierającej dane z profilu:

Dlaczego sprawdzamy dwa elementy strony? Na stronie tagu mamy dwie sekcje top zdjęcia i najnowsze zdjęcia, przy czym tej drugiej może w ogóle nie być (sprawdźcie tag #sexy). W helpie napisano, że może nie być też części top posty (przed czym powyższa funkcja nie zabezpiecza).

Wynik działania jest podobny do get_account_index():

post_id post_created image_url like_count comment_count
Bvgqkk9Jmir 2019-03-27 12:39:28 https://scontent-waw1-1.cdninstagram.com/vp/a0be4c154cda92b1d751f4d2b90cbc72/5D14F02E/t51.2885-15/e35/54800454_352785385334119_3740211091469849925_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 537 22
BvgkRdHnKA3 2019-03-27 11:44:25 https://scontent-waw1-1.cdninstagram.com/vp/65c0f0f9923479e841f5eb15c2eed9fe/5D2A17EE/t51.2885-15/e35/53349100_576239206189031_3549679433512070757_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 265 4
Bvgjz6_pzMY 2019-03-27 11:40:23 https://scontent-waw1-1.cdninstagram.com/vp/819d1cf88d9770e0407184f1a23ca726/5D380A39/t51.2885-15/e35/53500328_320700825470759_7207453812240986862_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 237 17
BvfB61FHAJf 2019-03-26 21:25:00 https://scontent-waw1-1.cdninstagram.com/vp/75ea0c7d6e59b81a402ff9149042b442/5D2F9387/t51.2885-15/e35/53759583_1306896016115157_4333933136393783967_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 5201 60
BvgckxyHTTc 2019-03-27 10:37:09 https://scontent-waw1-1.cdninstagram.com/vp/85d54d8eb1eede8e22e72400fa19217d/5D338295/t51.2885-15/e35/53659145_150822732616904_5468385185039052597_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 286 7
BvgvrGsgGBa 2019-03-27 13:24:03 https://scontent-waw1-1.cdninstagram.com/vp/bdf9439f7988c35097e096eb16665603/5D2D14A3/t51.2885-15/e35/54277722_123454515482034_3840644262469580321_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 416 38
BvgG59wFBmq 2019-03-27 07:27:49 https://scontent-waw1-1.cdninstagram.com/vp/eb598f3deb753805834e4995e64869d1/5D41C2CC/t51.2885-15/e35/54511306_173702843620957_4053853746451190050_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 1279 8
BvgnhxaATAv 2019-03-27 12:12:52 https://scontent-waw1-1.cdninstagram.com/vp/91f61860b32c9cdc2d71912b8cc531e4/5D4E57F0/t51.2885-15/e35/53794656_2292597157428515_3647909755989942555_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 249 16
Bvgdq6Ygt-k 2019-03-27 10:46:44 https://scontent-waw1-1.cdninstagram.com/vp/15c839cff67fc9385962937f1269c6df/5D485C84/t51.2885-15/e35/53515511_353972501877292_5866158490742970838_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 176 10
Bvgz6QbnqKp 2019-03-27 14:01:04 https://scontent-waw1-1.cdninstagram.com/vp/7f490e7400d1ebf6e952ec0408428abf/5D339F20/t51.2885-15/e35/53568790_422123968358627_5440036648377527213_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 1 1
Bvgz5y6FGGZ 2019-03-27 14:01:00 https://scontent-waw1-1.cdninstagram.com/vp/9c3fa79a6cd47681e15044ef12a47e7e/5D2A187C/t51.2885-15/e35/53539966_361163941164108_5868792802005334821_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 1 0
Bvgz4o_F5nm 2019-03-27 14:00:51 https://scontent-waw1-1.cdninstagram.com/vp/5c49030128e94747b9d2c75d1d580c1a/5D392E9F/t51.2885-15/fr/e15/s1080x1080/55831796_2254890001398108_6134306923009509780_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 3 0
Bvgz4lvnbVz 2019-03-27 14:00:50 https://scontent-waw1-1.cdninstagram.com/vp/2127f45ba5e4751c412c59bba8efec76/5D2B16BC/t51.2885-15/e35/54512859_1123558314472151_1852936089099096522_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 1 0
Bvgz2y9grOh 2019-03-27 14:00:36 https://scontent-waw1-1.cdninstagram.com/vp/e516135249b540084fb5e37bfd707848/5D500DBA/t51.2885-15/e35/56168135_111851269989774_5404352276918388589_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 0
BvgzzAUlfx8 2019-03-27 14:00:04 https://scontent-waw1-1.cdninstagram.com/vp/d372ce011969d3456b2c286cf4067bdd/5D3868D5/t51.2885-15/e35/53366360_525732371591054_4495187113934333800_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 11 1
BvgzxwBBFn9 2019-03-27 13:59:54 https://scontent-waw1-1.cdninstagram.com/vp/23cd430b067b3ae4401a180564392294/5D394E58/t51.2885-15/e35/53547702_409660089864463_7869379145574160764_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 5 1
BvgzebanW7o 2019-03-27 13:59:22 https://scontent-waw1-1.cdninstagram.com/vp/86a2fa1b3ebaa253c616c9c73208a6bd/5C9E0D0E/t51.2885-15/e15/53593529_303260560350311_2901164257127586790_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 0
BvgzsbZgbeJ 2019-03-27 13:59:11 https://scontent-waw1-1.cdninstagram.com/vp/105f11ae304f4de61dca33cf61acafaf/5D4444BD/t51.2885-15/e35/53811103_2011383769156631_1586652261456550849_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 4 0
BvgzsOqAQCc 2019-03-27 13:59:09 https://scontent-waw1-1.cdninstagram.com/vp/8d1f46fafe5b6b257929b279f37eeb82/5D4B5FE0/t51.2885-15/e35/53320145_277236463188499_4126497442262513026_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 5 0
Bvgzr8OhU_7 2019-03-27 13:59:07 https://scontent-waw1-1.cdninstagram.com/vp/be9b6c3950968deb6274fd738b63849f/5D4ADC4D/t51.2885-15/e35/53501899_128156924934836_3973593278215285626_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 5 4
BvgzkImh5pO 2019-03-27 13:58:03 https://scontent-waw1-1.cdninstagram.com/vp/79e5a5c43ba78b6f046f900cdf6ecf5b/5D4490F6/t51.2885-15/e35/53727100_130031161456636_8502934798626324623_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 7 1
BvgzMb3nj47 2019-03-27 13:58:03 https://scontent-waw1-1.cdninstagram.com/vp/009bc6a370d8279a88a815370605f1c5/5C9DDAA0/t51.2885-15/e35/54266380_185017462464453_5344235562011338079_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 3 0
BvgzjikFepe 2019-03-27 13:57:58 https://scontent-waw1-1.cdninstagram.com/vp/f4d57fbe845cffba9955cc18d6a1aa2c/5D2F6724/t51.2885-15/e35/55961992_168074857520383_4258068488194064544_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 1
Bvgzil8H_1s 2019-03-27 13:57:50 https://scontent-waw1-1.cdninstagram.com/vp/ea31669e873084ac212c05c88d232132/5D475A5E/t51.2885-15/e35/54511557_125981308544148_7866925235858869015_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 24 2
BvgziTdlJ7K 2019-03-27 13:57:48 https://scontent-waw1-1.cdninstagram.com/vp/8ead17089489ae1f41add5c5bcdb3ad2/5D4498B6/t51.2885-15/e35/54510788_2097716263597666_7031760171802760707_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 6 0
BvgzgpXAUKf 2019-03-27 13:57:34 https://scontent-waw1-1.cdninstagram.com/vp/798a525f20cc3d1eb92291d778c521fb/5D2BF151/t51.2885-15/e35/54511164_408380903270097_4191496977886505672_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 0
BvgzgPwn3f1 2019-03-27 13:57:31 https://scontent-waw1-1.cdninstagram.com/vp/735ab0c0c564b3d9c900f5a707484797/5D153FD0/t51.2885-15/e35/53827132_387791138443499_9030475626214013620_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 8 0
BvgzfVfFbbh 2019-03-27 13:57:23 https://scontent-waw1-1.cdninstagram.com/vp/6c2f83d6c3a81fadd16aab40b522b4b5/5D4636A2/t51.2885-15/e35/54731599_138456857205245_7406647351124072735_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 0
Bvgze_uAeBb 2019-03-27 13:57:21 https://scontent-waw1-1.cdninstagram.com/vp/3441f8e035aa267b76682093e678f82e/5D33F2A8/t51.2885-15/e35/53824281_127201001716206_3751673952227628617_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 4 1
BvgzfDzlacF 2019-03-27 13:57:21 https://scontent-waw1-1.cdninstagram.com/vp/7a5442b107e5fe674d3eccfb36afd5f2/5D354CA6/t51.2885-15/e35/54247677_943197059404813_670740029510607339_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 6 0
BvgzdeoBTU0 2019-03-27 13:57:08 https://scontent-waw1-1.cdninstagram.com/vp/c610e17a60c66125252f165e64141012/5D4952F9/t51.2885-15/e35/52798360_424693915004097_116098457263596948_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 4 0
BvgzbmFn_bx 2019-03-27 13:56:53 https://scontent-waw1-1.cdninstagram.com/vp/83c0a0dbdad777758c7cab49f9d54664/5D487322/t51.2885-15/e35/53926654_338781513413281_8516498886835701882_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 4 0
BvgzWN-AzlY 2019-03-27 13:56:09 https://scontent-waw1-1.cdninstagram.com/vp/cdac23af96f368f54bd82b77a907b917/5D14C0BC/t51.2885-15/e35/54277717_344811139466966_4050770272010238415_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 3 0
BvgzUaKA0fQ 2019-03-27 13:55:54 https://scontent-waw1-1.cdninstagram.com/vp/67f61a63ee78a80b301045f83e893e34/5D15DC3F/t51.2885-15/e35/s1080x1080/53502901_324807568393631_5319865615289624799_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 229 0
BvgzUQLFRIq 2019-03-27 13:55:53 https://scontent-waw1-1.cdninstagram.com/vp/2db7292943682b47850ffd7d3e058f67/5D399239/t51.2885-15/e35/53327683_278178663104191_4877763968762434275_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 0
BvgzNHpgRbI 2019-03-27 13:55:43 https://scontent-waw1-1.cdninstagram.com/vp/4e1e17eb36c864da69381d57037cce57/5C9DE573/t51.2885-15/e35/53678290_2125088387605263_6813710379356356260_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 17 0
BvgzSe9lJaD 2019-03-27 13:55:38 https://scontent-waw1-1.cdninstagram.com/vp/de44697de6c3cdf4f3d7042420a27dfa/5D130933/t51.2885-15/e35/53796721_2242881202422098_5034377048362732565_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 20 2
BvgzR0Qg56y 2019-03-27 13:55:33 https://scontent-waw1-1.cdninstagram.com/vp/46a1afe333db9d86c38eb7d53c0e8b07/5D4A026B/t51.2885-15/e35/54277577_304105836933959_7777260152423013831_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 3 0
BvgzRwanFFS 2019-03-27 13:55:32 https://scontent-waw1-1.cdninstagram.com/vp/ffb795f3752664659b028df504aa2ba8/5D40A107/t51.2885-15/e35/53850454_172619980393272_5348711651738894497_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 7 1
BvgzRsKHY9d 2019-03-27 13:55:32 https://scontent-waw1-1.cdninstagram.com/vp/043922733c3be9c4ff4b934cc867eb02/5D17495D/t51.2885-15/e35/54512347_127715315000380_3972469117259108014_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 14 0
BvgzQnaFLUF 2019-03-27 13:55:23 https://scontent-waw1-1.cdninstagram.com/vp/8165c6032759096bfbc1a8cce53ffa81/5D4F643F/t51.2885-15/e35/53720126_319536748756691_7697211337249874569_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 6 1
BvgzP8dni9X 2019-03-27 13:55:17 https://scontent-waw1-1.cdninstagram.com/vp/caad8293ee5c71cf16c7a0c512d6ddf9/5D444EFC/t51.2885-15/e35/54266439_569741093518120_7093541086387427474_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 26 1
BvgzPvVAqeJ 2019-03-27 13:55:16 https://scontent-waw1-1.cdninstagram.com/vp/6eb3d981b4534caca234fd7eec00cdb2/5D2E6E42/t51.2885-15/e35/53439405_432165740938087_3322867705342682570_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 14 1
BvgzPovhhuN 2019-03-27 13:55:15 https://scontent-waw1-1.cdninstagram.com/vp/16c6b8082d2170a92ae4ee338cb129d1/5D48683B/t51.2885-15/e35/53659001_126826568398616_3708367251128822017_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 0 0
BvgzOpugThC 2019-03-27 13:55:07 https://scontent-waw1-1.cdninstagram.com/vp/5620ed02c5abafc2bb038cd994c25a60/5D4AE6A5/t51.2885-15/e35/54511107_193614318273396_9212180333710444232_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 6 0
BvgzOAxASsj 2019-03-27 13:55:01 https://scontent-waw1-1.cdninstagram.com/vp/5442f88d6e7f27c9e0ab7240475fad92/5D4C6D88/t51.2885-15/e35/54247828_843558562653399_2723685210637486090_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 10 0
BvgzMS2gC8P 2019-03-27 13:54:47 https://scontent-waw1-1.cdninstagram.com/vp/25337d5c541f5e44becec73e09c240fa/5D14F8DD/t51.2885-15/e35/54513675_128889734902056_6066411693438624071_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 14 1
BvgzI4aF9oL 2019-03-27 13:54:19 https://scontent-waw1-1.cdninstagram.com/vp/5b50e57b275153663e57d9547828b348/5D346BA3/t51.2885-15/e35/53843371_141867073528624_4376675500109978839_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 21 2
BvgzGSTHyU7 2019-03-27 13:53:58 https://scontent-waw1-1.cdninstagram.com/vp/9615beb6ee97438795e38c575ab626ba/5D1639A4/t51.2885-15/e35/54731916_151319045891582_4974794642749677380_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 65 2
BvgzEH8gnXB 2019-03-27 13:53:40 https://scontent-waw1-1.cdninstagram.com/vp/7b086ad03a9901b326828d4d52ab058d/5D406798/t51.2885-15/e35/53928410_1520195981445659_6266138540509183812_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 7 0
BvgzDofh_QY 2019-03-27 13:53:36 https://scontent-waw1-1.cdninstagram.com/vp/774867f37ba86d3f47aab9bb72ba4c4f/5D46D205/t51.2885-15/e35/53708724_2066613920122170_776959188254205424_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 4 0
BvgzDlEjxBU 2019-03-27 13:53:36 https://scontent-waw1-1.cdninstagram.com/vp/f00619836c239da05f1e7ccda1717f82/5D4C3685/t51.2885-15/e35/55928057_272706103663926_8860941510996426750_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 17 0
BvgzB9wFkEO 2019-03-27 13:53:23 https://scontent-waw1-1.cdninstagram.com/vp/0f48224077a026bbfd210aa319a1af62/5D2BCFF6/t51.2885-15/e35/53797854_629711147469106_159399666676402285_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 13 1
BvgzBoPFRgh 2019-03-27 13:53:20 https://scontent-waw1-1.cdninstagram.com/vp/9209dcdb0f87ee269a902050d4177645/5D38AA53/t51.2885-15/e35/52435302_2582813455082167_2952129876582402692_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 9 1
BvgzBcdlUvr 2019-03-27 13:53:18 https://scontent-waw1-1.cdninstagram.com/vp/5c9880485cf6642786317ecae0eb5461/5D14F689/t51.2885-15/e35/56375879_337057930257614_2290972340683151503_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 5 0
Bvgy-HCh7yH 2019-03-27 13:52:51 https://scontent-waw1-1.cdninstagram.com/vp/152157917c16e27867a2ea6006351961/5D30C471/t51.2885-15/e35/55906293_2277494605866018_5214646889404449877_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 323 1
Bvgy7qslTFe 2019-03-27 13:52:31 https://scontent-waw1-1.cdninstagram.com/vp/dabdf6f3914d1bc9e735d08f0028852f/5D4F13C5/t51.2885-15/e35/54512555_436097340266765_1691843746973493319_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 2 0
Bvgy7BSATd6 2019-03-27 13:52:26 https://scontent-waw1-1.cdninstagram.com/vp/08c5afba70f6d7add177d2a9a813ad7e/5D4D1670/t51.2885-15/e35/53759636_2647910661895287_707675728239675967_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 5 2
Bvgyt5eAbTc 2019-03-27 13:50:38 https://scontent-waw1-1.cdninstagram.com/vp/70659b22de245367f0345d5098a50018/5D46551E/t51.2885-15/e35/53869346_2297864670489929_8955736706314132891_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 12 1
BvgyS8jlyFI 2019-03-27 13:50:09 https://scontent-waw1-1.cdninstagram.com/vp/fe94e18b9df4fee481aed94c72e0aaa8/5C9DACCE/t51.2885-15/e35/54247319_125942451842213_7572532083729147868_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 7 0
BvgyoT8AKNp 2019-03-27 13:49:53 https://scontent-waw1-1.cdninstagram.com/vp/d0991c40b44c898c02feea0b96821bde/5D4CB98D/t51.2885-15/e35/s1080x1080/54248163_268022137458876_6620621520595875712_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 28 1
Bvgymi4nFsX 2019-03-27 13:49:38 https://scontent-waw1-1.cdninstagram.com/vp/a4d5b418d424c9b623b8a78fce240684/5D31BE1C/t51.2885-15/e35/54277241_183670329271135_480648369093497352_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 32 3
Bvgykqdgd6l 2019-03-27 13:49:23 https://scontent-waw1-1.cdninstagram.com/vp/06f91eb4362bbd631a50fdbedfbb1bfc/5D4B8F1F/t51.2885-15/e35/54513557_1610463582419527_2582399528612243078_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 5 0
BvgyjphnQS9 2019-03-27 13:49:14 https://scontent-waw1-1.cdninstagram.com/vp/40602dd50a524102e2a47b5479dce600/5D413D9B/t51.2885-15/e35/53813366_151259105901645_7310288329394129667_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 30 1
BvgyhirngnK 2019-03-27 13:48:57 https://scontent-waw1-1.cdninstagram.com/vp/64653ef5cb085f0734cbf2efb431fa70/5D31B36B/t51.2885-15/e35/56162971_414315489125910_2556652894102878189_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 32 2
BvgyhcoA5tK 2019-03-27 13:48:56 https://scontent-waw1-1.cdninstagram.com/vp/5643c3cfc6ec003780b8e7cf3d99bca5/5D4838A7/t51.2885-15/e35/54169447_785993418466573_1207618505476338352_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 9 0
Bvgyf_BgG8r 2019-03-27 13:48:44 https://scontent-waw1-1.cdninstagram.com/vp/f478abcab7f3b4a8981318ece45ce6a6/5D49C542/t51.2885-15/e35/54429319_1404380083032671_6850730683143653661_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 10 0
BvgyemRlEA5 2019-03-27 13:48:33 https://scontent-waw1-1.cdninstagram.com/vp/405390b5f1dbc4064097e1531a8194e8/5D374866/t51.2885-15/e35/53821050_305451786767665_3661591846043973797_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 17 2
BvgyXNlnCfH 2019-03-27 13:47:33 https://scontent-waw1-1.cdninstagram.com/vp/823789727e34009869719693e5d444ca/5D4F7C2D/t51.2885-15/e35/54512580_312311536152262_2375614104631723437_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 17 2
BvgurEzhC8y 2019-03-27 13:15:18 https://scontent-waw1-1.cdninstagram.com/vp/0c5d0b911420bd8456c94e500f9a4f49/5D171CBE/t51.2885-15/e35/53845884_983143868562109_5620702233373756118_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 150 11
BvdoxSSg0Kp 2019-03-26 08:26:00 https://scontent-waw1-1.cdninstagram.com/vp/c96e995355b89456c8c9285914deee57/5D35B350/t51.2885-15/e35/53695225_126713785086935_1215825207725697786_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 278 52
BvcOy7DHU_V 2019-03-25 19:19:47 https://scontent-waw1-1.cdninstagram.com/vp/aa443be1c233553fa6e34554edbe3d56/5D45F3C3/t51.2885-15/e35/53927360_1059152867584811_9106980136095018114_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 16 2
BvbiLBBn-S6 2019-03-25 12:49:52 https://scontent-waw1-1.cdninstagram.com/vp/99c733cae57b1b27c5a776672dbcec66/5D2FD33A/t51.2885-15/e35/52797124_130040261455794_7304103768463631695_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 942 57
BnzXyRQhu7o 2018-09-16 23:49:43 https://scontent-waw1-1.cdninstagram.com/vp/a4ffb8d9c0e19a36259d2ad10fd28364/5D350B23/t51.2885-15/e35/40616628_553911711707950_777201250856903223_n.jpg?_nc_ht=scontent-waw1-1.cdninstagram.com 26 1

W sumie mamy jakieś 80 zdjęć (ta liczba się różni dla różnych tagów i w różnym czasie, szczerze mówiąc nie badałem dlaczego).

Niestety nie mamy informacji o autorze zdjęcia, co komplikuje nieco sprawę. Precyzyjniej: ta informacja jest, ale autor jest ukryty pod numerkiem, a nie nickiem. Dlatego nawet jej nie pobieram.

Na koniec możemy mieć ochotę na zapisanie zdjęcia na dysk. To już banalna sprawa – wystarczy po prostu zapisać plik spod adresu image_url. Też funkcja (ta dodatkowo potrzebuje pakietu fs dla użytych funkcji dir_exists() oraz dir_create(), które są też w podstawowym R – odpowiednio dir.exists() i dir.create()):

Funkcja przyjmuje trzy parametry:

  • post_id – ID postu z którego pochodzi zdjęcie. Potrzebne tylko po to, aby obrazek na dysku nazwać tym ID
  • image_url – adres zdjęcia
  • dest – folder, do którego obrazek ma zostać zapisany. bo możemy chcieć zapisywać pliki w folderach podzielonych według autorów

Wszystkie przygotowane funkcje mają swoje zasadnicze ograniczenie – biorą to, co jest widoczne bez przewijania strony. Ma to swoje zalety (działa szybko), ale też sporą wadę – żeby zebrać więcej danych trzeba uruchamiać je co jakiś czas. Można próbować pozbyć się tej niedogodności z użyciem np. Selenium i symulować przeglądarkę, przewijanie strony itd. Do Selenium za chwilę dojdziemy, ale na potrzeby tego postu przygotowałem skrypt, który uruchamiał się co piętnaście minut (na przemian dla tagu #warszawa i #warsaw).

Skrypt zapisywał dane do pliku lokalnego, zbierał wszystko co zwraca funkcja get_post_details() (a zatem też komentarze i hashtagi). Jeśli czegoś nie potrzebujemy to możemy nie zbierać :) I o wiele lepszym rozwiązaniem jest zapisywanie wyniku do bazy danych (np. jakiś SQL) niż trzymanie wszystkiego w pliku.

Algorytm działania był następujący:

  • co 15 minut wejdź na stronę tagu
  • pobierz informacje o wszystkich zdjęciach jakie są na tej stronie (ich ID) (get_tag_index())
  • dla każdego pobranego zdjęcia:
    • wejdź na stronę zdjęcia (get_post_details())
    • zapisz dane do pełnej bazy
    • znajdź autora zdjęcia (kolumna post_author)
      • idź na stronę autora i zbierz najnowsze jego zdjęcia (get_account_index())
      • dla każdego z zdjęć autora
        • sprawdź czy to zdjęcie już mamy w pełnej bazie
        • jeśli nie mamy:
          • wejdź na stronę zdjęcia
          • zbierz informacje o zdjęciu (get_post_details())
          • zapisz te informacje do pełnej bazy
        • jeśli mamy – idziemy do następnego zdjęcia
      • idź do następnego autora
    • idź do następnego zdjęcia ze strony tagu
  • koniec

Dzięki takiemu podejściu dostajemy nie tylko najnowsze zdjęcie danego użytkownika z wybranego tagu, ale też kawałek jego starych zdjęć, być może nawet wcześniejszych niż początek zbierania danych (w moim przypadku to i sprzed kilku lat, taki jestem aktywny! ;-).

Na stronie tagu pojawia się wspomniane 80 zdjęć. Niech każde będzie unikalne z unikalnym autorem – musimy więc sprawdzić 80 stron pojedynczego zdjęcia, aby znaleźć 80 autorów. To już 81 zapytań (1 na stronę tagu, 80 na autorów zdjęć z tagu). Teraz dla 80 autorów sprawdzamy ich profil (kolejne 80 zapytań), aby pobrać ich najnowsze zdjęcia (12 na każdego autora, łącznie 80*12 = 960 zapytań). Część będzie się powtarzać (są na stronie tagu, były już wcześniej), ale licząc maksimum mamy do pobrania jedną stronę tagu + 80 zdjęć z tagu + 80 stron autorów + 80*12 ich najnowszych zdjęć co daje 1121 zapytań. Bardzo dużo. Łatwo dostać bana za takie coś. Warto też pomyśleć o optymalizacji (na przykład nie pobierając szczegółów zdjęcia o ile nie potrzebujemy tagów).

Szybka analiza

Przygotowałem odpowiedni skrypt, który działał według powyższego algorytmu przez kilka dni i zebrał (w tym momencie) informacje o 158.4 tys obrazków. Skrypt zbierał zaczynając od tagów #warszawa i #warsaw (ale przecież zgodnie z algorytmem brał też historię autorów zdjęć).

Zobaczmy jak wygląda liczba publikowanych zdjęć w czasie:

Dane zacząłem zbierać około południa 22 marca, stąd dni wcześniejsze są nieco niższe (ale jak widać algorytm dociągnął historię co pozwoliło na ładne wyrównanie). Wyraźnie widać dzień i noc oraz z grubsza rytm internetu w ciągu dnia (pik rano, płasko w południe i więcej wieczorem). 24 marca wieczorem był mecz Polska-Łotwa na Stadionie Narodowym co zaowocowało zwiększoną liczbą zdjęć z Warszawy.

Możemy też popatrzyć na rozkład liczby zdjęć publikowanych w ciągu tygodnia, chociaż w momencie przygotowywania tego postu nie minął pełny tydzień zbierania danych (sprawne oko zauważy kiedy post był renderowany do publikacji):

Zobaczmy jeszcze jakie tagi są najpopularniejsze, bo to jest ciekawe (społecznie, wiele mówi o Instagramie):

Oczywiście dużo jest tagów warszawskich, bo to one są głową dla zbieranych danych i od nich się zaczyna. Dużo mamy też autolansu, o który chyba na Insta chodzi…

Sprawdźmy teraz gdzie były robione zdjęcia.

Tutaj idealnie byłoby użyć danych EXIF, ale ze względów bezpieczeństwa wszystkie serwisy społecznościowe czyszczą te dane przy uploadzie plików (a jeśli tego nie robią to bardzo źle), więc nie dowiemy się prawdy a jedynie to co podają użytkownicy. A podają:

Warszawa dominuje, czasem wskazane są konkretne dzielnice. Szare paski oznaczają wszystkie zdjęcia, zielone – te, które mają tag #warszawa i/lub #warsaw. Liczba przy słupku to procent zdjęć z którymś z tych tagów. Zatem około 70% zdjęć oznaczonych jako zrobione w Warszawie (konkretnie, bez agregacji z dzielnic) ma jeden z wybranych tagów. Lokalizacje, które mają największy udział warszawskich tagów (spośród górnego 2% lokalizacji pod względem popularności):

Lokalizacja zdjęcia Liczba wszystkich zdjęć Liczba zdjęć warszawskich Procent
EXPO XXI Warszawa – Międzynarodowe Centrum Targowo-Kongresowe 58 51 87.93
Zamek Królewski w Warszawie 58 51 87.93
Pałac Kultury i Nauki Warszawa 417 358 85.85
Stadion Miejski Legii Warszawa im. Marszałka Józefa Piłsudskiego 62 51 82.26
Warszawa Old Town 520 424 81.54
Praga, Warszawa 115 92 80.00
Warszawa Stare Miasto 89 71 79.78
Łazienki Królewskie 363 289 79.61
PGE Narodowy 241 189 78.42
klub Stodoła 68 53 77.94
Progresja 74 57 77.03
Śródmieście, Warszawa 1010 776 76.83
Lotnisko Chopina 76 58 76.32
Warszawa, Centrum 227 173 76.21
Ptak Warszawa Expo 79 60 75.95
COS Torwar 133 101 75.94
Centrum Praskie Koneser 71 53 74.65
Bulwary Wiślane 84 62 73.81
Neon Muzeum 67 49 73.13
Bielany dzielnica Warszawy 80 58 72.50

To się zmienia dynamicznie i zależy od puli zgromadzonych zdjęć. W każdym razie wszystkie leżą w Warszawie. Ale tagami warszawskimi oznaczane są też takie lokalizacje jak:

  • 3 Warszawa
  • Bubbleology Polska
  • Centrum
  • Cleve, Germany
  • Fitness Klub Aplauz
  • Jasnochówka
  • Jenna JKO Tattoo
  • Kondratowicza
  • Kreator Mocy
  • KROPKA nad ink
  • Leonardo Verde
  • Lombard Ruska 38 Rynek Wrocław 7 dni w tygodniu 792 038 038
  • Miasto Ogród Komorów, Warszawa
  • Niezły Mexyk Tattoo
  • Plac Narutowicza
  • Powisle, Warszawa
  • Przestrzeń Tattoo
  • Razors Barber Shop
  • Restauracja Krasnodwór
  • Si Fashion
  • Skinissimo
  • Stacja Grawitacja Warszawa
  • Waves Tattoo
  • Zespół Szkół Odzieżowych Poznań

No jak widać niektóre firmy na swoich profilach tagują jak opętane, żeby tylko zwiększyć zasięg ;-).

Zobaczmy jeszcze co ciekawego ludzie piszą w komentarzach. Najprościej będzie na poziomie bi-gramów, bo pojedyncze słowa niewiele wnoszą to takiej informacji (no dobra – sprawdzałem i wiem, że niewiele odbiega to od bi-gramów):

lt 3 to serduszko zapisane jako <3. Poprawnie byłoby poczyścić takie rzeczy (rozkodować znaki UTF i encje). Z kolei warszawa warsaw to zapewne to samo co #warszawa #warsaw, czyli tagi u komentarzach – też można to wyczyścić.

Ogólnie rzecz biorąc szału nie ma. Wszyscy wszystko sobie chwalą i zapraszają do siebie. Ale Instagram to nie jest forum publicystyczne czy miejsce wymiany opinii – tutaj ogląda się zdjęcia dziewczyn, ich paznokci i kosmetyków oraz daje serduszka i wysyła buziaczki. IQ na poziomie chomika wystarczy.

Co jeszcze można zrobić z tymi danymi?

Wiele rzeczy. Można zobaczyć rozkład liczby lajków i komentarzy, można zobaczy kto komu komentuje posty (analiza sieci społecznych). A w prosty sposób można przygotować dokument RMarkdown, który po wyrenderowaniu da nam statyczną stronę z na przykład najnowszymi zdjęciami z danego tagu. Przykładowy dokument:

który zapisany jako plik instagram.Rmd można wyrenderować do HTMLa za pomocą:

co powinno utworzyć plik HTML (razem z kilkoma folderami) z przeglądem zdjęć zgromadzonych z tagu warszawa (zgodnie z podanym parametrem hashtag). Uwaga – im bardziej popularny tag tym więcej zdjęć będzie musiało się załadować przy otwarciu wygenerowanego dokumentu. #Warszawa nie jest więc za mądrym wyborem :) Oczywiście wybór zdjęć do pokazania może być zupełnie inny – tutaj pokazujemy po prostu wszystkie z ostatnich 7 dni z podanym tagiem. Ale można zastosować inne filtry (np. po ilości komentarzy czy lajków, po lokalizacji).

W podobny sposób można przygotować aplikację w Shiny, która pozwoli na filtrowanie (np. po tagu i czasie) zdjęć.

W tego typu rozwiązaniach rozsądniej jednak zbierać dane do bazy danych i na jej poziomie wyszukiwać odpowiednie zdjęcia.

Komentowanie i lajkowanie

Przejdźmy do następnego poziomu zaawansowania, czyli automatyki. Potrafimy pobrać dane o zdjęciach, zdjęcia z tagu i z profilu. Może da się też je automatycznie komentować albo lajkowac? Oczywiście!

Do tego potrzebujemy już konta i maszyny, która będzie udawała nasze poruszanie się po stronie. Pisałem o tym już w poście Webscrapping w R, tutaj krótkie przypomnienie.

(R)Selenium

Przede wszystkim potrzebujemy zainstalowanego Dockera i obrazu z przeglądarką. W niniejszym przykładzie skupimy się na obrazie selenium/standalone-firefox-debug z dwóch powodów:

  • wersja debug pozwala na podpięcie się przez VNC i podglądanie na żywo jak skrypty sobie radzą (co robią, czasem na reakcję jeśli potrzeba)
  • firefox bo można zmienić w prosty sposób User Agenta przeglądarki w tym obrazie (a będziemy udawać przeglądarkę mobilną)

Zatem instalujemy (jeśli nie mamy) Dockera, ściągamy odpowiedni obraz przez docker pull selenium/standalone-firefox-debug z konsoli Shella i uruchamiamy go (też z konsoli) poprzez:

Na porcie 4444 Docker słucha nas, a na 5900 mamy dostęp po VNC. Po szczegóły odsyłam do rozsianych po sieci przykładów – ten post to nie instrukcja do Dockera :)

W R będziemy potrzebować biblioteki RSelenium.

Aby dać like albo napisać komentarz potrzebujemy kilku rzeczy:

  • być zalogowanym w Instagramie
  • wejść na stronę zdjęcia
  • kliknąć serduszko – aby dać lajka
  • wpisać komentarz – aby… dodać komentarz

Zaczynamy zatem od punku pierwszego.

Logowanie do Instagrama

Pierwsza rzecz to jednak uruchomienie przeglądarki w kontenerze Dockera:

W tym momencie warto połączyć się przez klienta VNC i zobaczyć co tam się dzieje na serwerku (w Dockerze). Żeby to wszystko działało warto mieć system Linuxowy, najlepiej na jakimś własnym serwerze. O przygotowaniu takiego serwera pisałem już kiedyś, ja używam serwera VPS z Webh.pl. Jeśli chcesz taki kupić skorzystaj proszę z tego linku – dzięki programowi partnerskiemu wspomożesz tego bloga.

Zalogujmy się zatem do Instagrama:

Uwaga – przy logowaniu możemy dostać jakieś komunikaty (widać je będzie w VNC, można z tego poziomu je kliknąć) albo i maile o próbie logowania z innego niż zazwyczaj adresu. Pierwszy raz albo i dwa to się zadzieje, ale po potwierdzeniu że to my się logujemy (np. z Chin) dalej już nie będzie takiej konieczności. Jest to nieco upierdliwe, ale to wynik dbania o bezpieczeństwo.

Lajkowanie

Jesteśmy zalogowani, aby dać lajka trzeba kliknąć w serduszko na stronie zdjęcia. Odpowiednia funkcja otworzy nam stronę zdjęcia (na podstawie ID postu), znajdzie element z serduszkiem i kliknie w niego:

W zmiennej remDr mamy driver Selenium, zatem danie lajka zdjęciu o ID BvUAaQkFb9_ (to moja fota, pozwalam spamować :) sprowadza się do wywołania powyższej funkcji:

Komentowanie

Podobnie jest z komentarzem: wchodzimy na stronę postu, znajdujemy element na wpisanie komentarza (pole tekstowe), wpisujemy jego treść i zatwierdzamy Enterem:

Wywołanie funkcji podobne do add_like_to_photo():

W ten sposób możemy hurtem lajkowac i komentować zdjęcia. Proces jest prosty:

  • dla danego ID postu:
    • wywołujemy add_like_to_photo() aby post zalajkować
    • wywołujemy add_comment_to_photo() aby post skomentować

Możemy to puścić w pętli dla wszystkich zdjęć wybranych w jakiś sposób (po użytkowniku, tagu, dacie – cokolwiek). Uwaga – lepiej pomiędzy jednym a drugim lajkiem czy komentarzem dać rozsądną chwilę (5-10 sekund, najlepiej losowo) przerwy, aby Instagram nie zorientował się że ma do czynienia z automatem. Hurtowe działanie w bardzo krótkim czasie nie jest mile widziane w tego typu serwisach i może powodować blokadę konta. Tak na przykład jest przy masowym dodawaniu i usuwaniu obserwowanych na Twitterze (przytrafiło mi się na bocie @IleRoku – swoją drogą, obserwujesz go już na Twitterze, prawda?).

Publikowanie zdjęć

To wyższa szkoła jazdy i szczerze mówiąc nie przeskoczyłem tego problemu. To dla dodawania zdjęć była potrzebna mobilna wersja przeglądarki (precyzyjniej: mobilny User Agent) – w wersji desktopowej nie ma guziczka do dodania zdjęcia (otwórz stronę Instagrama na komputerze i w przeglądarce na telefonie – widzisz różnicę?).

Dodanie zdjęcia z poziomu przeglądarki mobilnej sprowadza się do kliknięcia w odpowiedni przycisk na stronie, wybraniu zdjęcia i… tyle! Czyli powinno wystarczyć:

Na koniec możemy zamknąć stosownego Dockera – jeśli jest tylko jeden to wystarczy w shellu:

To tyle na temat obsługi Instagrama z poziomu języka R. Mam nadzieję, że przedstawione kody są na tyle czytelne, że z łatwością dasz radę przenieść je na przykład na Pythona (o ile potrzebujesz).

Jeśli Ci się podobało to podziel się wpisem ze światem (odpowiednie guziczki poniżej). Wpadnij też na Dane i Analizy na Facebooku – tam więcej takich smaczków (szczególnie dla praktyków). Nieco więcej smaczków znajdziesz też w nie-tak-bardzo cyklicznym newsletterze, którego archiwum tutaj (a na dole guzik do zapisania się na kolejne wydania).

Możesz też rzucić piniądz autorowi, czy tam postwić witrualną kawę :)

5 komentarzy do “Instagram – zbieranie danych i bot”

  1. Cześć Łukasz! Bardzo fajny wpis, miałbym pytanie do Ciebie czy da się jakoś dobrać do dokładniejszej lokalizacji zdjęć ? czy próbowałeś robić coś takiego w jakiś innych serwisach społecznościowych ? mógłbyś coś polecić ? Pozdrawiam!

    1. Jeśli są dane EXIF z aparatu to jest szansa na współrzędne GPS (o ile aparat je zapisuje). Zrób jakieś zdjęcie (najlepiej telefonem, z włączonym zapisem lokalizacji) i wrzuć obrazek tutaj http://exif.regex.info/exif.cgi. Magia, co? :) A teraz weź dowolne zdjęcie z serwisu społecznościowego (sam URL wystarczy) i użyj tego samego narzędzia.
      W R jest pakiet do czytania EXIFów https://github.com/Ironholds/exif, w Pythonie na pewno też coś jest.

    2. Cześć, ciekawie jak zwykle. Próbuję zrobić coś podobnego, ale ciągle dostaje bany na konto za aktywność, automatyka z protraktora(selenium). Czy możesz rozwinąć wątek „oszukiwania” algorytmów instagrama?

      1. Szczerze mówiąc co miałem na myśli półtora roku temu to nie wiem. Ale pewnie user agent na jakiś telefon albo coś.
        No i może coś po stronie Instagrama się zmieniło…

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *