Мобильная
версия

Instagram API. Автоматический постинг

Дата: Категория: PHP

В данной статье мы разобрались с автоматическим постингом на стену контакта без сторонних приложений. 
Ну, разобрались, и забыли. Но теперь, дабы развивать группу, я вспомнил еще про одну социальную сеть - instagram.

Не буду описывать все ее возможности, преимущества, и все такое. Сегодня мы поговорим об обратной стороне красивого сайта с фотографиями - о его API и возможности автоматически постить на фотографии с комментариями.

Лень - самое главное качество программиста. Если программист не ленивый - он плохой программист.
Да, да. Все именно так. Ведь только очень ленивый человек делает огромную работу единовременно, чтобы в будущем не делать практически ничего.

Загружать фотографии в инстаграм мне было лень, но для моего проекта это было бы очень полезно, и я стал искать.

В API самого инстаграма нет ничего интересного - поиск по фотографиям, изменение профиля, и все в этом духе. И ни слова как автоматически загрузить фотографию с комментарием.
Это меня очень раздосадовало, и я обратился к своему самому главному помощнику - интернету.

После нескольких часов поиска я нашел скрипт который более менее подходил под мои нужды, и немного подправил его.

Ну и собственно, хочу поделиться им с вами.
Для того чтобы запостить в инстаграм фотографию и текст нужна следующая функция

sendInstagramm($image, $text);
  • $image - Полный путь до изображения (отправляется с помощью cURL). Изображение должно быть квадратным, и должно быть локальным!
    загрузка по ссылке невозможна!
  • $text - ваш текст. Для вставки переносов применяется "\n", с поддержкой хэштэгов (#тэг)

Как видите - все достаточно просто. В ответ приходит статус, или ошибка (string)

Если вам лень пользоваться скриптом, то узнав, что статья пользуется неплохой популярностью, я решил написать сервис IPosting для автоматической публикации изображений в instagram

А вот собственно и сам код который все это делает

<?php

function SendRequest($url, $post, $post_data, $user_agent, $cookies) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://instagram.com/api/v1/'.$url);
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    if($post) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }

    if($cookies) {
        curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
    } else {
        curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
    }

    $response = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return array($http, $response);
}

function GenerateGuid() {
    return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand(0, 65535),
        mt_rand(0, 65535),
        mt_rand(0, 65535),
        mt_rand(16384, 20479),
        mt_rand(32768, 49151),
        mt_rand(0, 65535),
        mt_rand(0, 65535),
        mt_rand(0, 65535));
}

function GenerateUserAgent() {
    $resolutions = array('720x1280', '320x480', '480x800', '1024x768', '1280x720', '768x1024', '480x320');
    $versions = array('GT-N7000', 'SM-N9000', 'GT-I9220', 'GT-I9100');
    $dpis = array('120', '160', '320', '240');

    $ver = $versions[array_rand($versions)];
    $dpi = $dpis[array_rand($dpis)];
    $res = $resolutions[array_rand($resolutions)];

    return 'Instagram 4.'.mt_rand(1,2).'.'.mt_rand(0,2).' Android ('.mt_rand(10,11).'/'.mt_rand(1,3).'.'.mt_rand(3,5).'.'.mt_rand(0,5).'; '.$dpi.'; '.$res.'; samsung; '.$ver.'; '.$ver.'; smdkc210; en_US)';
}

function GenerateSignature($data) {
    return hash_hmac('sha256', $data, 'b4a23f5e39b5929e0666ac5de94c89d1618a2916');
}

function GetPostData($filename) {
    if(!$filename) {
        echo "The image doesn't exist ".$filename;
    } else {
        $post_data = array('device_timestamp' => time(),
            'photo' => '@'.$filename);
        return $post_data;
    }
}


function sendInstagramm($filename, $caption)
{
    $username = _ВАШ_ЛОГИН_;
    $password = _ВАШ_ПАРОЛЬ_;

    $agent = GenerateUserAgent();
    $guid = GenerateGuid();
    $device_id = "android-" . $guid;
    $data = '{"device_id":"' . $device_id . '","guid":"' . $guid . '","username":"' . $username . '","password":"' . $password . '","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}';
    $sig = GenerateSignature($data);
    $data = 'signed_body=' . $sig . '.' . urlencode($data) . '&ig_sig_key_version=4';
    $login = SendRequest('accounts/login/', true, $data, $agent, false);
    $text = '';

    if (strpos($login[1], "Sorry, an error occurred while processing this request.")) {
        $text .= "Request failed, there's a chance that this proxy/ip is blocked";
        return $text;
    }

    if (empty($login[1])) {
        $text .= "Empty response received from the server while trying to login";
        return $text;
    }
    $obj = @json_decode($login[1], true);

    if (empty($obj)) {
        $text .= "Could not decode the response" ;
        return $text;
    }
    $data = GetPostData($filename);
    $post = SendRequest('media/upload/', true, $data, $agent, true);

    if (empty($post[1])) {
        $text .= "Empty response received from the server while trying to post the image";
        return $text;
    }
    $obj = @json_decode($post[1], true);

    if (empty($obj)) {
        $text .= "Could not decode the response";
        return $text;
    }
    $status = $obj['status'];

    if ($status != 'ok') {
        $text .= "Status isn't okay";
        return $text;
    }

    $media_id = $obj['media_id'];
    $device_id = "android-" . $guid;

    $data = (object)array(
        'device_id' => $device_id,
        'guid' => $guid,
        'media_id' => $media_id,
        'caption' => trim($caption),
        'device_timestamp' => time(),
        'source_type' => '5',
        'filter_type' => '0',
        'extra' => '{}',
        'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
    );
    $data = json_encode($data);
    $sig = GenerateSignature($data);
    $new_data = 'signed_body=' . $sig . '.' . urlencode($data) . '&ig_sig_key_version=4';

    $conf = SendRequest('media/configure/', true, $new_data, $agent, true);

    if (empty($conf[1])) {
        $text .= "Empty response received from the server while trying to configure the image";
    } else {
        if (strpos($conf[1], "login_required")) {
            $text .= "You are not logged in. There's a chance that the account is banned";
        } else {
            $obj = @json_decode($conf[1], true);
            $status = $obj['status'];
            if ($status != 'fail') {
                $text .= "Success";
            } else {
                $text .= 'Fail';
            }
        }
    }
    return $text;
}

Вам остается только заменить строки 75 - 76

$username = _ВАШ_ЛОГИН_;
$password = _ВАШ_ПАРОЛЬ_;

Все - теперь с помощью этого удобного скрипта можно автоматизировать еще один рутинный процесс.
Всем спасибо за внимание.

PS

  • Изображение должно быть квадратным
  • Изображение должно быть локальынм - лежать на машине со скриптом. По ссылке НЕ РАБОТАЕТ.
  • Не забудьте установить необходимые права на файлы для никсов
  • Сервис IPosting - для тех кто не умеет, у кого не получается, или кому просто лень ;)

PSS

Если у вас что-то не работает, значит вы что-то сделали не так. На сайте https://iposting.ru скрипт работает по сей день. Заходите - проверяйте ;)

Теги: #cURL, #работа с файлами, #Instagram, #API

Ваша оценка:

Рейтинг: 9.1 (Оценок: 36)

Комментарии (40):

AytoMaximo
2015-10-08 22:33
Извините, если задам тупой вопрос. А логин/пароль нужно ведь в кавычках указать? Как текст?
Например:
$username = "user";
    $password = "pass";
Просто я в PHP вообще 0, но выхода другого нет как попытаться хоть немного разобраться. Методом тыка просто удалось выяснить, что у меня тоже все останавливается на ошибке Empty response received
DOC_tr
2015-10-09 00:27
@AytoMaximo:да, в кавычках.
Например если логин user, а пароль 1234, то указывать нужно
$username = 'user';
$password = '1234';
AytoMaximo
2015-10-09 00:39
@DOC_tr:В общем, я не знаю, что за фигня. Уже php скрипт разместила на одном из имеющихся у меня сайтов (мало ли, вдруг апач тупит). Залезла в глубины android устройства, через root права и GikDbg вытащила другой signature key, все равно не хочет логиниться и всё, хоть убей.
AytoMaximo
2015-10-09 02:55
@DOC_tr:Короче говоря, если долго обновлять страницу, то ошибка "Empty response received from the server while trying to post the image" может смениться на "Could not decode the response". Не работают куки. А приложенный здесь скрипт не может работать только потому, что версия Instagram уже давно не 4, а 7. И сигнатура давно другая. Вы зря всем отвечаете, что оно продолжает все работать без всяких правок.
DOC_tr
2015-10-09 11:46
@AytoMaximo:Я уже устал всем писать что если у вас что-то не получается, то это вы чтото сделали не так. Читайте последний абзац статьи и думайте.
Djsanchez
2015-10-07 19:50
Скажите пожалуйста, а пути "media/upload/" - я должен на свои заменить, правильно?
DOC_tr
2015-10-08 21:33
@Djsanchez:Нет. Это параметры передачи данных непосредственно на серверах инстаграмма.
Все что вы должны заменить это логин и пароль. А все необходимое для постинга (картинку и текст) функция принимает в качестве параметров.
lleokaganov
2015-09-28 03:00
Огромное чесловеческое спасибо. Все работает (28 сентября 2015)
Beyka
2015-09-25 00:39
Добрый день. Я в PHP не силен, пытаюсь перевести ваш скрипт на Java. Для теста включил денвер и туда засунул скрипт с правкой логина и пароля.
Мне в ответ приходит Empty response received from the server while trying to login
В чем может быть проблема?
вот некоторый трейс по скрипту:

User Agent: Instagram 4.2.0 Android (10/3.5.5; 240; 320x480; samsung; GT-N7000; GT-N7000; smdkc210; en_US)
Guid: 6d190176-750f-4fb9-ae1c-37966fc936eb
device id: android-6d190176-750f-4fb9-ae1c-37966fc936eb
data: {"device_id":"android-6d190176-750f-4fb9-ae1c-37966fc936eb","guid":"6d190176-750f-4fb9-ae1c-37966fc936eb","username":"changed","password":"changed","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}
Sig: ad10513e8ffb3a86fbc15d838372081c4339ae918fbb85d52b1f6651742d28a7
data signed: signed_body=ad10513e8ffb3a86fbc15d838372081c4339ae918fbb85d52b1f6651742d28a7.%7B%22device_id%22%3A%22android-6d190176-750f-4fb9-ae1c-37966fc936eb%22%2C%22guid%22%3A%226d190176-750f-4fb9-ae1c-37966fc936eb%22%2C%22username%22%3A%22changed%22%2C%22password%22%3A%22changed%22%2C%22Content-Type%22%3A%22application%2Fx-www-form-urlencoded%3B+charset%3DUTF-8%22%7D&ig_sig_key_version=4
Empty response received from the server while trying to login
tester
2015-09-24 11:12
Если сюда еще cron привязать, можно постить по расписанию
DOC_tr
2015-09-24 12:32
@tester:Все верно ;) именно так и реализовано на https://iposting.ru
Dmitry
2015-09-15 12:38
Хотелось бы узнать - почему если к фотографии поставить #тег, то в поиске по тэгу новой фотографии нет.
Dmitry
2015-09-15 13:49
@Dmitry:Это кстати и iposting.ru касается
DOC_tr
2015-09-15 13:56
@Dmitry:Да, я в курсе этой ошибки. Пока, к сожалению, точно не могу сказать почему.
Dmitry
2015-09-15 14:01
@DOC_tr:печально.я пытался через Wireshark перехватить данные, но ничего нормального не получил. похоже приложение ещё какой-то параметр передаёт, хотя интересно как другие сервисы на php работают
Dmitry
2015-09-15 15:48
@DOC_tr:а комментировать у меня только не получается или этой общий баг?(коммент с другого аккаунта)
DOC_tr
2015-09-15 15:51
@Dmitry:Всмысле? что именно комментировать?
Dmitry
2015-09-15 15:55
@Dmitry:картинку, опубликованную через этот скрипт
DOC_tr
2015-09-15 16:12
@Dmitry:С такой ошибкой сталкиваюсь впервые. У меня все получается, да и вы первый, у кого она появилась.
Dmitry
2015-09-15 16:24
@Dmitry:Оказался глюк веб версии инстаграма, через которую я комментировал. сейчас приложение комментировал - всё норм. остаётся только проблему с тегами решить...
Олег
2015-08-29 22:34
Подтверждаю слова Дмитрия! Скрипт перестал работать, пишет "Fail".
DOC_tr
2015-08-30 15:11
@Олег:Значит вы что-то неправильно делаете.
На сайте https://iposting.ru с помощью этого скрипта последний пост был опубликован сегодня в 14.00, и за сегодня запощено более 20 постов.
Дмитрий
2015-08-31 12:38
@DOC_tr:Делаю постинг, приходит одобрение, ссылка на фотку и прочее.но в аккаунте его нет
DOC_tr
2015-08-31 14:58
@Дмитрий:Вариантов множество. Фото не квадратное, вы загружали изображение слишком много раз и инстаграмм автоматически его удаляет, в любом случае я не смогу помочь. После открытия сервиса iposting я не оказываю тех поддержку по скрипту ;)
Могу сказать только то что он 100% рабочий.
Дмитрий
2015-08-23 17:13
Что-то перестала схемка работать
zaza
2015-07-15 22:54
Прикрыли, походу, лавочку
DOC_tr
2015-07-16 11:51
@zaza:нет, все исправно работает. Точно такойже скрипт стоит на http://iposting.ru - можете зайти и проверить ;)
gotcha
2015-07-13 22:25
Hi everyone,

Do you have any idea how it could be possible to get tag?
Because if I add some tag in caption, there is noway to find the picture from tag?

I tried also:
$data = (object)array(
        'device_id' => $device_id,
        'guid' => $guid,
        'media_id' => $media_id,
        'caption' => trim($caption),
        'tags' => $hashtag,
        'device_timestamp' => time(),
        'source_type' => '5',
        'filter_type' => '0',
        'extra' => '{}',
        'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
    );
DOC_tr
2015-07-14 11:33
@gotcha:sendInstagramm('img.jpg', 'Hello! #hello #hi');
it works fine
dev01100100
2015-09-15 01:12
@DOC_tr:Та же проблема. Другие пользователи не могут найти фото по хештегу.
Copyright © DOC_tr 2015-2017 г. Все права защищены
Яндекс.Метрика
Перейти к мобильной версии