Как быстро и просто скачать плейлист с Вконтакте

[ Версия для печати ]
Добавить в Telegram Добавить в Twitter Добавить в Вконтакте Добавить в Одноклассники
  [ ОТВЕТИТЬ ] [ НОВАЯ ТЕМА ]
VampirBFW
31.10.2017 - 10:59
Статус: Online


Главный Сапиосексуал Япа.

Регистрация: 20.02.10
Сообщений: 18384
11
Как все начиналось

Дело было вечером, делать было нечего… Точнее, я просто хотел загрузить аудиокнигу перед парами и тут меня ждал сюрприз. Кэш в кейт мобайле отключили. Как так? Что делать? Конечно же писать свое приложение с кэшем и аудиозаписями. Но для начала нужно понять, как вк превращает ссылки вида audio%user_id%_%track_id% в прямые ссылки на mp3. Что из этого вышло приложения я не написал и как скачать определенный плейлист можно прочитать под катом.

Это сообщение отредактировал VampirBFW - 31.10.2017 - 11:15
 
[^]
Yap
[x]



Продам слона

Регистрация: 10.12.04
Сообщений: 1488
 
[^]
VampirBFW
31.10.2017 - 10:59
Статус: Online


Главный Сапиосексуал Япа.

Регистрация: 20.02.10
Сообщений: 18384
Дебажим js

Начинаем с очевидного — открываем вкладку аудиозаписей и смотрим код. Видим onclick на кнопке у каждой аудиозаписи:

onclick="return getAudioPlayer().toggleAudio(this, event)"

Открываем audioplayer.js, включаем Pretty print и ищем функцию toggleAudio().

toggleAudio()
AudioPlayer.prototype.toggleAudio = function(t, e) {
if (vk && vk.widget && !vk.id && window.Widgets)
return Widgets.oauth(),
!1;
if (domClosest("_audio_row__tt", e.target))
return cancelEvent(e);
var i = domClosest("_audio_row", t)
, o = AudioUtils.getAudioFromEl(i, !0);
if (window.getSelection && window.getSelection().rangeCount) {
var a = window.getSelection().getRangeAt(0);
if (a && a.startOffset != a.endOffset)
return !1
}
if (e && hasClass(e.target, "mem_link"))
return nav.go(attr(e.target, "href"), e, {
navigateToUploader: !0
}),
cancelEvent(e);
if (hasClass(e.target, "_audio_row__title_inner") && o.lyrics && !o.isInAttach)
return AudioUtils.toggleAudioLyrics(i, o),
cancelEvent(e);
if (hasClass(e.target, "audio_row__performer"))
return checkEvent(e) || vk.widget ? !0 : (AudioUtils.audioSearchPerformer(e.target, o.performer, e),
cancelEvent(e));
var s = cur.cancelClick || e && (hasClass(e.target, "audio_lyrics") || domClosest("_audio_duration_wrap", e.target) || domClosest("_audio_inline_player", e.target) || domClosest("audio_performer", e.target));
if (cur._sliderMouseUpNowEl && cur._sliderMouseUpNowEl == geByClass1("audio_inline_player_progress", i) && (s = !0),
delete cur.cancelClick,
delete cur._sliderMouseUpNowEl,
s)
return !0;
if (AudioUtils.isClaimedAudio(o) || o.isReplaceable) {
var r = AudioUtils.getAudioExtra(o)
, l = r.claim;
if (l)
return void (hasClass(i, "no_actions") || o.isInEditBox || showAudioClaimWarning(o, l, AudioUtils.replaceWithOriginal.bind(AudioUtils, i, o)))
}
if (o.isPlaying)
this.pause();
else {
var n = AudioUtils.getContextPlaylist(i);
this.play(o.fullId, n.playlist, o.context || n.context),
cur.audioPage && cur.audioPage.onUserAction(o, n.playlist)
}
AudioUtils.onRowOver(i, !1, !0)
}


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

Видим, что переменная o через несколько шагов содержит кучу полезной информации: исполнитель, название, хэши, всякие айди. Но не содержит главного свойства — url.
Идем дальше, выходим из toggleAudio(), попадаем в файл common.js в функцию, работающую с эвентами. Ага, значит ссылку мы получим асинхронно, надо бы посматривать на сетевую активность, что ж, шагаем дальше. Через n шагов замечаем, что во вкладке network появляется интересный запрос:

Request URL:https://vk.com/al_audio.php
Request Method:POST

Form Data:
act:reload_audio
al:1
ids: список id вида %user_id%_%track_id%, которые нужно обновить

И не менее интересный ответ:

4089188939145<!><!>0<!>6854<!>0<!><!json>[[456239119,%my_id%,"https:\/\/vk.com\/mp3\/audio_api_unavailable.mp3?extra=ofvLohaZvtDKnOPmEtHWl2rJCLLMrJiZy1i4D3blohn4AZLflLqZtMn3utbJmeTrCdq2Be1LyJ1HDvqTBKnUne8YrJfzzKrVENKXzL9JmMHgEgz3u3nbDwfuBMDiywLJBOrfl2fQwJDRmvrFzwDbwtGWvwThDxy6lxLHt1KOlvDODhbTAgjOzffOzdvTBOvOms9nvO9Ix1bxrNqUwgnfAfLWnwfLDLb0CLLxAvCVr2r4ExbHzhPTlKS2p3zcodu3yxm4Ea#CWS1mZi","Сон смешного человека ","Ф.М. Достоевский",4705,0,0,"",0,2,"","[]","6adb4186ee0c1d3ad0\/5102a312745ae505a7\/08eb0e4bd407e74e76\/d313ec4b6051942649\/","",[]],[456239118,%my_id%,"https:\/\/vk.com\/mp3\/audio_api_unavailable.mp3?extra=AdbkuuLOywjuou0Zme1yrdzJsI9Tm2qYvIO2AJaWnMnIztKOzgLxmMfbu3rgyJ8Tme5MBNrKlMLpChPIBLLFngjvu3zZAxztuOXJztfgrK9vq1rznLCYDJznBMrMCMT4rO9PytD3oc5kAhyYm1jMmZeZlxqZsKfWyKO9DNGUmvfuBtfOudjXrvbmyZLVltvICvPIver5zg5Zm2jWmJvWsue5nuXWzgPnBZq6l2n3x30OCgCVC2SVmxjqzvD6Egrlnc1zyq#CWSYmdC","автостопом в москву","црвених цветова",359,0,0,"",0,18,"","[]","57c59cffa93d47effa\/836d457cff34e02fa0\/6374a8e457c763a8c6\/96db3ddc8c210b1fb0\/","",[]],[456239117,%my_id%,"https:\/\/vk.com\/mp3\/audio_api_unavailable.mp3?extra=AgDYnY1TmwmOm2vTos5Ylu9Juwzkugv4zMzZyJbVlKjcqI9LB2vdzhe6DufVqY9KA1uZy3bfnhm4AgDOAwHIzMDztMTxsLjHn2K9veXuttvKq2fxogTWxY1fzJvumJrADLDlCdnLAv8UAfPiB2zxEKTrttLTrtK2ntrLCLnOww5rtI1Rq2vzsgr2vMnYp1P5BeOOx3rIEs8WBI10yLntCNzOCKrLBtznBMzRC29ewMOOC3uTueuYl29OztnWDhCXoffz#CWSYntC","Sal sér hon standa (Völuspá, 64-66)","Nytt Land",272,0,0,"",0,82,"","[]","4881448c55978a3374\/40a707901f551a4572\/778fe59467e6a629a9\/02a308905303098496\/","https:\/\/pp.userapi.com\/c837628\/v837628453\/829d0\/kLoB-0G_r78.jpg,https:\/\/pp.userapi.com\/c837628\/v837628453\/829cf\/C39pJ5b-t-w.jpg",80],[456239116,%my_id%,"https:\/\/vk.com\/mp3\/audio_api_unavailable.mp3?extra=l1yUmI1MCc8Vsxq2qxHYoM1Ku2i9C1y\/EdzWzZfADhrpDgGYrwvJwwTRtZzHDwL3A2HZqKXXrOfHtZDVDKzZn1zIrKLJD3PVBKqOzxLylKDjvZuYqKf5qLG3rhn4nJnHs1rlt1PUy29mCvLuuxD6DJHJAtGXvNfjrMzkt29Wme93mKuWze55x1PotO01lMqZnuHfzJLgBM1Jluzqogvkr3KYs1fNmtn6qODYyx0XnxDZDNnvvO9Lsgn0tdrKDc9Kowm2#CWSOmJy","After Dark "," Mr.Kitty",351,0,0,"",0,18,"","[]","353d934506a14abed5\/5745fb63e4e5f4abb4\/2ed8c9b81df35317d7\/01404a5db986cf16b8\/","",[]],[456239115,%my_id%,"https:\/\/vk.com\/mp3\/audio_api_unavailable.mp3?extra=mJfWyY1SBMm\/m1HYDc5YzgO5BwvdndC5nZDyvNzWyMvsEgfwyMvmsJzXm2fqEhq5mJvXvw50qIO4xZKTEefVsxq3yMfkltLpnJvWzfDrCZHgywiXEgzZqwntsJvMn21Nss9psKDkBKHKlY1LzI1vlJPyEuu3l3nyEhjsBNuWAhrlq3rezZfxmJn4A2zwtZbowhq3B1CWlZe4ytHZnhzhu19Lt29fvJDkCfLOzgvewI43rtjWmd1YBKLysOe2uMfKztbr#CWSZmJG","Storm","Godspeed You! Black Emperor",1352,0,0,"",0,34,"","[]","81b9d46c10d9df8d03\/5299d303c627944df7\/5ec696a0453d27253e\/ce7a1e0600cff40c53\/","",[]]]<!><!bool><!>7212f741260c90ab47

Понимаем, что это json, распаковываем

Это сообщение отредактировал VampirBFW - 31.10.2017 - 11:01

Как быстро и просто скачать плейлист с Вконтакте
 
[^]
VampirBFW
31.10.2017 - 11:01
Статус: Online


Главный Сапиосексуал Япа.

Регистрация: 20.02.10
Сообщений: 18384
Отлично, теперь у нас есть хоть какая-то ссылка, но выглядит она не очень рабочей, что делать дальше?

Расшифровываем ссылку

Шагаем по скрипту дальше и понимаем, что ничего не выходит, на каком-то этапе ссылка просто превращается из audio_api_unavailable в ссылку на mp3. Значит где-то что-то происходит!
Но где именно? В одной из функций setUrl() вызывается функция с говорящим именем audioUnmaskSource()

Код функции
function i() {
return window.wbopen && ~(window.open + "").indexOf("wbopen")
}
function o(t) {
if (!i() && ~t.indexOf("audio_api_unavailable")) {
var e = t.split("?extra=")[1].split("#")
, o = "" === e[1] ? "" : a(e[1]);
if (e = a(e[0]),
"string" != typeof o || !e)
return t;
o = o ? o.split(String.fromCharCode(9)) : [];
for (var s, r, n = o.length; n--; ) {
if (r = o[n].split(String.fromCharCode(11)),
s = r.splice(0, 1, e)[0],
!l[s])
return t;
e = l[s].apply(null, r)
}
if (e && "http" === e.substr(0, 4))
return e
}
return t
}
function a(t) {
if (!t || t.length % 4 == 1)
return !1;
for (var e, i, o = 0, a = 0, s = ""; i = t.charAt(a++); )
i = r.indexOf(i),
~i && (e = o % 4 ? 64 * e + i : i,
o++ % 4) && (s += String.fromCharCode(255 & e >> (-2 * o & 6)));
return s
}
function s(t, e) {
var i = t.length
, o = [];
if (i) {
var a = i;
for (e = Math.abs(e); a--; )
o[a] = (e += e * (a + i) / e) % i | 0
}
return o
}
Object.defineProperty(e, "__esModule", {
value: !0
}),
e.audioUnmaskSource = o;
var r = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/="
, l = {
v: function(t) {
return t.split("").reverse().join("")
},
r: function(t, e) {
t = t.split("");
for (var i, o = r + r, a = t.length; a--; )
i = o.indexOf(t[a]),
~i && (t[a] = o.substr(i - e, 1));
return t.join("")
},
s: function(t, e) {
var i = t.length;
if (i) {
var o = s(t, e)
, a = 0;
for (t = t.split(""); ++a < i; )
t[a] = t.splice(o[i - 1 - a], 1, t[a])[0];
t = t.join("")
}
return t
},
x: function(t, e) {
var i = [];
return e = e.charCodeAt(0),
each(t.split(""), function(t, o) {
i.push(String.fromCharCode(o.charCodeAt(0) ^ e))
}),
i.join("")
}
}
}


Ставим брейкпоинт на o(t) и смотрим, что приходит и что уходит. t — наша ссылка вида audio_api..., в ?extra= содержатся два параметра. Насколько я понял, один содержит зашифрованную ссылку, а второй — это что-то вроде ключа. Можно зареверсить алгоритм, понять, как именно он все это шифрует, а можно просто вызвать o('https://...audio_api_...'). Так я и решил сделать, и получил на выходе прямую ссылку на mp3

Получаем зашифрованные ссылки

Расшифровывать ссылки научились, метод для получения зашифрованной ссылки знаем. Как же нам теперь получить айди, которые нужно передать методу, возвращающему зашифрованные ссылки? Идем смотреть сетевую активность. Как мы поняли ранее, взаимодействие с audio API происходит через al_audio.php. Ставим фильтр на данный запрос, загружаем страницу с аудиозаписями заново и видим уже новый запрос

Request URL:https://vk.com/al_audio.php
Request Method:POST
Status Code:200
Form Data:
access_hash:
act:load_section
al:1
claim:0
offset:30
owner_id:my_id
playlist_id:-1
type:playlist

И в ответ получаем большой json в том же виде, что и раньше, который содержит данные о плейлисте. Поле offset отвечает за смещение, начиная с которого, мы будем получать данные о плейлисте. Кроме того, ответ содержит полезные данные: поля hasMore и nextOffset.

Собираем все вместе

Мы знаем как получить данные о плейлисте, как получить зашифрованные ссылки и как их расшифровать. Осталось собрать все воедино


Вот так легко и просто можно скачать всю нужную Вам музыку.

как это сделал савелий журавлев.

Это сообщение отредактировал VampirBFW - 31.10.2017 - 11:02
 
[^]
Rents
31.10.2017 - 11:01
31
Статус: Offline


Дворянин в 0,5 поколении

Регистрация: 31.01.09
Сообщений: 917
я конечно понимаю,что ТС админ.Но если ты хотел таким чайникам,как я,подсобить,то я понял только слова "вечером" и "аудиокнига".
 
[^]
Chasm
31.10.2017 - 11:02
8
Статус: Offline


Optimus Prime

Регистрация: 29.10.13
Сообщений: 1115
А можно я не буду это делать? Пожалуйста.
 
[^]
marlaTs
31.10.2017 - 11:02
4
Статус: Offline


цветок

Регистрация: 8.07.13
Сообщений: 2776
так никто же не сидит вконтактике и телевизоры все 5 лет назад выкинули в окно.
 
[^]
barney
31.10.2017 - 11:03
15
Статус: Offline


комментатор гифкофил

Регистрация: 28.05.15
Сообщений: 1550
бля открыл Пост и у меня всё зависло нахуй

 
[^]
AleXXX82
31.10.2017 - 11:03
5
Статус: Offline


Статус заблокирован

Регистрация: 2.02.16
Сообщений: 2167
Цитата
Как быстро и просто скачать плейлист с Вконткте


Ну в принципе понятно все стало alik.gif

Это сообщение отредактировал AleXXX82 - 31.10.2017 - 11:04

Как быстро и просто скачать плейлист с Вконтакте
 
[^]
IlyaFF
31.10.2017 - 11:03
5
Статус: Offline


Юморист

Регистрация: 31.01.14
Сообщений: 441
Так обычно Сотону вызывают.
 
[^]
Bu3uTeP
31.10.2017 - 11:04
3
Статус: Offline


Весельчак

Регистрация: 12.02.13
Сообщений: 189
Я не много прихуел от такого расклада, можно я не буду быстро скачивать плейлист.

Отправлено с мобильного клиента YAPik+
 
[^]
anubbis
31.10.2017 - 11:05
1
Статус: Offline


Юморист

Регистрация: 3.03.12
Сообщений: 466
Я сломал два пальца и все три руки.
 
[^]
Tpuдевятый
31.10.2017 - 11:05
4
Статус: Offline


Ярила

Регистрация: 29.06.14
Сообщений: 2150
Тот случай, когда комментарии интереснее самой новости
 
[^]
Himer
31.10.2017 - 11:06
4
Статус: Offline


Юморист

Регистрация: 17.09.13
Сообщений: 442
Круто! А кресло компьютерное мне можешь починить, чтоб не скрипело?
 
[^]
ahsanm
31.10.2017 - 11:07
7
Статус: Offline


Весельчак

Регистрация: 9.01.15
Сообщений: 160
ТС "Вот так легко и просто можно скачать всю нужную Вам музыку. " это значит, что пользователю достаточно нажать одну кнопку. Вот это будет легко и просто, а в этой статье нихера не просто. Я бы больше сказал, что из этой статьи вообще не следует вариант скачивания музыки.

Это сообщение отредактировал ahsanm - 31.10.2017 - 11:08
 
[^]
Minzdraw
31.10.2017 - 11:09
0
Статус: Offline


ЗамкадышЪ

Регистрация: 7.10.11
Сообщений: 424
Очень СЛОЖНААААаа) проще через расширение по 1 песенке выкачать)...

Это сообщение отредактировал Minzdraw - 31.10.2017 - 11:09
 
[^]
Hanglider
31.10.2017 - 11:09
7
Статус: Offline


Ярила

Регистрация: 3.01.15
Сообщений: 2491
bravo.gif Утер слезу. Мне понравилось. Честно!
Но потом вспомнил, что у меня есть DownLoadHelper на случай что надо какой-то поток мультимедиа дернуть с сайта.

Но, блин.. Ты красиво сделал. Чувствуется профи.

Это сообщение отредактировал Hanglider - 31.10.2017 - 11:10
 
[^]
moodween
31.10.2017 - 11:12
1
Статус: Offline


Бля Буддист

Регистрация: 4.07.14
Сообщений: 1399
Прости, дружище! :)

如何他妈的整个世界他妈的,而不是错误!
 
[^]
VampirBFW
31.10.2017 - 11:14
1
Статус: Online


Главный Сапиосексуал Япа.

Регистрация: 20.02.10
Сообщений: 18384
Цитата (moodween @ 31.10.2017 - 11:12)
Прости, дружище! :)

如何他妈的整个世界他妈的,而不是错误!

Простите, но мы тут музыку качаем, а не занимаемся сексом с миром без ошибок.
 
[^]
moodween
31.10.2017 - 11:22
1
Статус: Offline


Бля Буддист

Регистрация: 4.07.14
Сообщений: 1399
Цитата (VampirBFW @ 31.10.2017 - 11:14)
Цитата (moodween @ 31.10.2017 - 11:12)
Прости, дружище! :)

如何他妈的整个世界他妈的,而不是错误!

Простите, но мы тут музыку качаем, а не занимаемся сексом с миром без ошибок.

Немного не так.

Ты выебал весь окружающий мир и не ошибся :)
А ведь реально, зачем нужен Гитхаб, гуглькод и прочие фрикхабы....

Когда есть ЯП!

Это сообщение отредактировал moodween - 31.10.2017 - 11:24
 
[^]
Аквариумист
31.10.2017 - 11:28
1
Статус: Offline


Юморист

Регистрация: 27.01.15
Сообщений: 425
Рыбки уснули в пруду... !!! И не проснулись!!!!
 
[^]
Инсульт
31.10.2017 - 12:14
0
Статус: Offline


Ярила

Регистрация: 18.03.14
Сообщений: 1043
Так обычно потом платить биткоинами за расшифровку просят...
 
[^]
ZMEELOV
31.10.2017 - 12:33
2
Статус: Offline


Приколист

Регистрация: 2.05.16
Сообщений: 304
Спасибо ТС
Охуительно просто и доступно обьяснил
Скачал все плейлисты..наслаждаюсь музыкой теперь cheer.gif brake.gif cheer.gif
 
[^]
Wait
31.10.2017 - 12:42
1
Статус: Offline


Хохмач

Регистрация: 8.11.13
Сообщений: 646
хаброеб
 
[^]
Woodcutter
31.10.2017 - 16:11
0
Статус: Offline


Ярила

Регистрация: 6.07.17
Сообщений: 1797
Тс, хоть бы для дилетантов в программировании объяснил бы по человечески. Непонятно же ни хрена.
 
[^]
Понравился пост? Еще больше интересного в Телеграм-канале ЯПлакалъ!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии. Авторизуйтесь, пожалуйста, или зарегистрируйтесь, если не зарегистрированы.
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) Просмотры темы: 5834
0 Пользователей:
[ ОТВЕТИТЬ ] [ НОВАЯ ТЕМА ]


 
 



Активные темы






Наверх