Получение ссылок на аудио без VKApi

в 13:20, , рубрики: api, Decode, extra, javascript, php, vkapi, Вконтакте, Вконтакте API, музыка

Данная страница будет полезной для тех, кто решил взять заказ на парсер аудио-треков VK и резко понял, что ничего не понял.

В чем проблема

Знакомо?

https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=AeL2rMfFyZzlD3HkyvfnvNvLx1KOqw5UDfuXCOTvttm4ts1OBJnYELvHyxvODI9fnM9YztD5A3iOyI14sxv2mNiXt3iTzdLInduXzvG9C2uVr3b5mezinfj2lJbpDhGYC25rDxbwsOPQmg1eu2Pbyxr3ntPowNLhDMrrDs8XnKu2sOuOyO8XzMf1otDmBtL6BNvllNjZx3aZuLHpq3aOBvvhzenJnZKTzKnMuwfKBI4TquffrtzKv2nymMyVDu1LzJnuwMLxwMm/BeTcserWlun3ExLVBG#AqSZntu

Если да — то вы пытались парсить мобильную версию сайта и успешно доставали ссылки. Неверные ссылки. Ссылки на 25-секундный голос, сообщающий что все идет не по плану.

Если нет — вам стоит попробовать.

Как получить верный URL

А вот это верный вопрос! Дело в том, что перед воспроизведением записи, вк натравливает на такой url заготовленные js-скрипты. В общем-то ничего сложного — несколько переворотов строк, побитовые сдвиги, даже одно побитовое отрицание. И все это сжато компрессором.

Честно говоря, раньше искать функции, отвечающие за это дело, было сложнее. Судя по всему во Вконтакте завелись кроты)) Иначе как блин объяснить то, что они подписали, буквально повесили вывеску на самом нужном месте:

image

Ладно, ладно, все мы рабы сборщиков…

Без лишних слов, актуальный код

Декодер на 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 = 150032691; //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;
}

function bcmod($k, $i){

	for(;$k >= $i; $k -= $i){}
	return $k;

}

В обоих случаях

s("https://m.vk.com/mp3/audio_api_unavailable.mp3?extra=encodeextraurl");

Думаю, при надобности с PHP на другой язык перевести код будет уже проще.

Статья написана с целью снизить кол-во человекоминут в мире, затрачиваемых на эту задачу.

Автор: In4in

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js