Данная страница будет полезной для тех, кто решил взять заказ на парсер аудио-треков VK и резко понял, что ничего не понял.
Знакомо?
Если да — то вы пытались парсить мобильную версию сайта и успешно доставали ссылки. Неверные ссылки. Ссылки на 25-секундный голос, сообщающий что все идет не по плану.
Если нет — вам стоит попробовать.
А вот это верный вопрос! Дело в том, что перед воспроизведением записи, вк натравливает на такой url заготовленные js-скрипты. В общем-то ничего сложного — несколько переворотов строк, побитовые сдвиги, даже одно побитовое отрицание. И все это сжато компрессором.
Честно говоря, раньше искать функции, отвечающие за это дело, было сложнее. Судя по всему во Вконтакте завелись кроты)) Иначе как блин объяснить то, что они подписали, буквально повесили вывеску на самом нужном месте:
Ладно, ладно, все мы рабы сборщиков…
В обоих случаях
Думаю, при надобности с PHP на другой язык перевести код будет уже проще.
Статья написана с целью снизить кол-во человекоминут в мире, затрачиваемых на эту задачу.
P.s: Актуальное решение всегда можно будет найти здесь: gist.github.com/in4in-dev/09f32f313f11b2c10778d9e2ffe7e60e
P.s2: Пользователь ImIeee также обновляет свое решение в репозитории github.com/vodka2/vkaudio (тут вы найдете решение на Python)
В чем проблема
Знакомо?
https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=AeL2rMfFyZzlD3HkyvfnvNvLx1KOqw5UDfuXCOTvttm4ts1OBJnYELvHyxvODI9fnM9YztD5A3iOyI14sxv2mNiXt3iTzdLInduXzvG9C2uVr3b5mezinfj2lJbpDhGYC25rDxbwsOPQmg1eu2Pbyxr3ntPowNLhDMrrDs8XnKu2sOuOyO8XzMf1otDmBtL6BNvllNjZx3aZuLHpq3aOBvvhzenJnZKTzKnMuwfKBI4TquffrtzKv2nymMyVDu1LzJnuwMLxwMm/BeTcserWlun3ExLVBG#AqSZntu
Если да — то вы пытались парсить мобильную версию сайта и успешно доставали ссылки. Неверные ссылки. Ссылки на 25-секундный голос, сообщающий что все идет не по плану.
Если нет — вам стоит попробовать.
Как получить верный URL
А вот это верный вопрос! Дело в том, что перед воспроизведением записи, вк натравливает на такой url заготовленные js-скрипты. В общем-то ничего сложного — несколько переворотов строк, побитовые сдвиги, даже одно побитовое отрицание. И все это сжато компрессором.
Честно говоря, раньше искать функции, отвечающие за это дело, было сложнее. Судя по всему во Вконтакте завелись кроты)) Иначе как блин объяснить то, что они подписали, буквально повесили вывеску на самом нужном месте:
Ладно, ладно, все мы рабы сборщиков…
Без лишних слов, актуальный код
Декодер на JavaScript
var id = 0; //Ваш userid
var n = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/=",
i = {
v: function(e) {
return e.split("").reverse().join("")
},
r: function(e, t) {
e = e.split("");
for (var i, o = n + n, s = e.length; s--;) i = o.indexOf(e[s]), ~i && (e[s] = o.substr(i - t, 1));
return e.join("")
},
s: function(e, t) {
var n = e.length;
if (n) {
var i = r(e, t),
o = 0;
for (e = e.split(""); ++o < n;) e[o] = e.splice(i[n - 1 - o], 1, e[o])[0];
e = e.join("")
}
return e
},
i: function(e, t) {
return i.s(e, t ^ id)
},
x: function(e, t) {
var n = [];
return t = t.charCodeAt(0), each(e.split(""), function(e, i) {
n.push(String.fromCharCode(i.charCodeAt(0) ^ t))
}), n.join("")
}
};
function o() {
return window.wbopen && ~(window.open + "").indexOf("wbopen")
}
function s(e) {
if (!o() && ~e.indexOf("audio_api_unavailable")) {
var t = e.split("?extra=")[1].split("#"),
n = "" === t[1] ? "" : a(t[1]);
if (t = a(t[0]), "string" != typeof n || !t) return e;
n = n ? n.split(String.fromCharCode(9)) : [];
for (var s, r, l = n.length; l--;) {
if (r = n[l].split(String.fromCharCode(11)), s = r.splice(0, 1, t)[0], !i[s]) return e;
t = i[s].apply(null, r)
}
if (t && "http" === t.substr(0, 4)) return t
}
return e
}
function a(e) {
if (!e || e.length % 4 == 1) return !1;
for (var t, i, o = 0, s = 0, a = ""; i = e.charAt(s++);) i = n.indexOf(i), ~i && (t = o % 4 ? 64 * t + i : i, o++ % 4) && (a += String.fromCharCode(255 & t >> (-2 * o & 6)));
return a
}
function r(e, t) {
var n = e.length,
i = [];
if (n) {
var o = n;
for (t = Math.abs(t); o--;) t = (n * (o + 1) ^ t + o) % n, i[o] = t
}
return i
}
Буква в букву декодер на PHP
global $n, $i, $id;
$n = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/=";
$id = 123456789; //user_id
$i = [
'v' => function($e) {
return strrev($e);
},
'r' => function($e, $t){
global $n;
$e = str_split($e);
for ($o = $n . $n, $s = count($e); $s--;){
$i = stripos($o, $e[$s]);
if(~$i){
$e[$s] = substr($o, $i - $t, 1);
}
}
return implode("", $e);
},
's' => function($e, $t) {
$n = strlen($e);
if ($n) {
$i = r($e, $t);
$o = 0;
$e = str_split($e);
for (; ++$o < $n;){
$p = array_splice($e, $i[$n - 1 - $o], 1, $e[$o]);
$e[$o] = $p[0];
}
$e = implode("", $e);
}
return $e;
},
'i' => function($e, $t){
global $i, $id;
$k = $i['s'];
return $k($e, $t ^ $id);
},
];
function o() {
return false;
}
function a($e){
global $n;
if (!$e || strlen($e) % 4 == 1) {
return !1;
}
$s = 0;
for ($o = 0, $a = "";$s < strlen($e);) {
$i = $e[$s++];
$i = strpos($n, $i);
if ($i !== false) {
$t = ($o % 4) ? 64 * $t + $i : $i;
if ($o++ % 4) {
$a .= chr(255 & $t >> (-2 * $o & 6));
}
}
}
return $a;
}
function r($e, $t) {
$n = strlen($e);
$i = [];
if ($n) {
$o = $n;
$t = abs($t);
for (; $o--;){
$t = ($n * ($o + 1) ^ $t + $o) % $n;
$i[$o] = $t;
}
}
return $i;
}
function s($e){
global $i;
if (!o() && strpos($e, "audio_api_unavailable") !== false) {
$t = explode("?extra=", $e);
$t = $t[1];
$t = explode("#", $t);
$n = ("" === $t[1]) ? "" : a($t[1]);
$t = a($t[0]);
if (!is_string($n) || !$t){ return $e;}
$n = $n ? explode(chr(9), $n) : [];
for ($l = count($n); $l--;) {
$r = explode(chr(11), $n[$l]);
$s = array_splice($r, 0, 1, $t);
$s = $s[0];
if (!$i[$s]){ return $e; }
$t = $i[$s](...$r);
}
if ($t && "http" === substr($t, 0, 4)){ return $t;}
}
return $e;
}
В обоих случаях
s("https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=encodeextraurl");
Думаю, при надобности с PHP на другой язык перевести код будет уже проще.
Статья написана с целью снизить кол-во человекоминут в мире, затрачиваемых на эту задачу.
P.s: Актуальное решение всегда можно будет найти здесь: gist.github.com/in4in-dev/09f32f313f11b2c10778d9e2ffe7e60e
P.s2: Пользователь ImIeee также обновляет свое решение в репозитории github.com/vodka2/vkaudio (тут вы найдете решение на Python)