Несколько месяцев назад Instagram начал выводить из строя их общедоступный API, удалив большинство функций и отказавшись принимать новые приложения для большинства областей разрешений. На этой неделе были внесены дополнительные изменения, которые еще больше ограничивают возможности разработчиков.
Многие из нас обратились к частному веб-API Instagram, чтобы реализовать функции, которые у нас были ранее. Один выдающийся ping/instagram_private_api позволяет перестроить большую часть прежней функциональности, однако, с публично объявленными изменениями на этой неделе, Instagram также внес основные изменения в свой частный API, требуя магических переменных, пользовательских агентов и хеширования MD5, чтобы сделать просмотр веб-страниц запросы возможны. Это можно увидеть по последним выпускам в ранее связанном git-репозитории, а точные изменения, необходимые для продолжения извлечения данных, можно увидеть здесь.
Эти изменения включают в себя:
- Сохранение агента пользователя и токена CSRF между запросами.
- Первоначальный запрос к
https://instagram.com/
дляrhx_gis
магического ключаrhx_gis
из тела ответа. - Установка заголовка
X-Instagram-GIS
, который формируется путем магической конкатенации ключаrhx_gis
и переменных запроса перед передачей их через хеш MD5.
Все, что меньше этого, приведет к ошибке 403. Эти изменения были успешно реализованы в вышеупомянутом репозитории, однако моя попытка в JS продолжает терпеть неудачу. В приведенном ниже коде я пытаюсь получить первые 9 сообщений с временной шкалы пользователя. Параметры запроса, которые определяют это:
-
query_hash
из42323d64886122307be10013ad2dcc44
(получить носитель с временной шкалы пользователя). -
variables.id
любого идентификатора пользователя в виде строки (пользователь, из которого нужно получить медиафайл). -
variables.first
, количество сообщений, которые нужно извлечь, в виде целого числа.
Ранее этот запрос мог быть выполнен без каких-либо вышеуказанных изменений, просто получая с https://www.instagram.com/graphql/query/?query_hash=42323d64886122307be10013ad2dcc44&variables=%7B%22id%22%3A%225380311726%22%2C%22first%22%3A1%7D
, так как URL был незащищенным.
Тем не менее, моя попытка реализовать функциональность для успешного написания в вышеупомянутом хранилище не работает, и я получаю только 403 ответа из Instagram. Я использую суперагент в качестве библиотеки запросов в среде узла.
/*
** Retrieve an arbitrary cookie value by a given key.
*/
const getCookieValueFromKey = function(key, cookies) {
const cookie = cookies.find(c => c.indexOf(key) !== -1);
if (!cookie) {
throw new Error('No key found.');
}
return (RegExp(key + '=(.*?);', 'g').exec(cookie))[1];
};
/*
** Calculate the value of the X-Instagram-GIS header by md5 hashing together the rhx_gis variable and the query variables for the request.
*/
const generateRequestSignature = function(rhxGis, queryVariables) {
return crypto.createHash('md5').update('${rhxGis}:${queryVariables}', 'utf8').digest("hex");
};
/*
** Begin
*/
const userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5';
// Make an initial request to get the rhx_gis string
const initResponse = await superagent.get('https://www.instagram.com/');
const rhxGis = (RegExp('"rhx_gis":"([a-f0-9]{32})"', 'g')).exec(initResponse.text)[1];
const csrfTokenCookie = getCookieValueFromKey('csrftoken', initResponse.header['set-cookie']);
const queryVariables = JSON.stringify({
id: "123456789",
first: 9
});
const signature = generateRequestSignature(rhxGis, queryVariables);
const res = await superagent.get('https://www.instagram.com/graphql/query/')
.query({
query_hash: '42323d64886122307be10013ad2dcc44',
variables: queryVariables
})
.set({
'User-Agent': userAgent,
'X-Instagram-GIS': signature,
'Cookie': 'rur=FRC;csrftoken=${csrfTokenCookie};ig_pr=1'
}));
Что еще я должен попробовать? Что делает мой код неудачным, и предоставленный код в репозитории выше работает нормально?
Обновление (2018-04-17)
Как минимум 3 раза в неделю Instagram снова обновляет свой API. Для изменения больше не требуется, чтобы токен CSRF являлся частью хешированной подписи.
Вопрос выше был обновлен, чтобы отразить это.
Обновление (2018-04-14)
Instagram снова обновил свой частный API GraphQl. Насколько каждый может понять:
- Пользовательский агент больше не нужно включать в расчет
X-Instagram-Gis
md5.
Вопрос выше был обновлен, чтобы отразить это.