После недавней шумихи вокруг аудиозаписей на сайте vk.com решил подстраховаться и скопировать всю свою коллекцию на жесткий диск. Для решения мною была написана простенькая утилита на Java. Ниже — её код c комментариями. Статья предназначена для читателей, знакомых с любым языком программирования общего назначения и умеющих компилировать и запускать написанные на нем программы.
Важное замечание: если Ваши аудиозаписи уже изъяты, то скачать их таким образом скорее всего не получится.
Подготовка
Список аудиозаписей получается через API сайта, для доступа к API нужен access token (токен доступа). Для получения токена необходимо в перейти по адресу (это стандартный способ, описанный в документации vk.com для разработчиков):
https://oauth.vk.com/authorize?client_id=3711445&scope=audio&
redirect_uri=https://oauth.vk.com/blank.html&display=page&v=5.0&response_type=token
и на загрузившейся страничке разрешить доступ приложению к своим аудиозаписям, после этого вы будете перенаправлены по адресу вида:
https://oauth.vk.com/blank.html#access_token=abc&expires_in=86400&user_id=123456
вот параметр access_token нам и нужен — запомним его. Последний параметр user_id — это ваш идентификатор пользователя, тоже понадобится.
Выполнив эти действия, Вы, фактически предоставили доступ моему приложению к списку ваших аудиозаписей, но т. к. полученный при это токен мне неизвестен — то и доступа нет, для пущей безопасности можете зарегистрировать свое приложения на vk.com и использовать его app_id.
Пишем код
Итак, токен у нас есть, можем приступить к скачиванию, в двух словах схема следующая: получаем список аудиозаписей в формате JSON, распарсиваем необходимою нам информацию (название песни, имя исполнителя и собственно адрес mp3 файла) и загружаем файл, придав ему осмысленное название.
Получение списка аудиозаписей выполняется отправкой POST запроса по адресу:
(см. метод API audio.get)
URIBuilder builder = new URIBuilder();
builder.setScheme("https").setHost("api.vk.com").setPath("/method/audio.get")
.setParameter("oid", USER_ID) // идентификатор пользователя, полученный ранее
.setParameter("need_user", "0")
.setParameter("count", "2000") // число загружаемых аудиозаписей
.setParameter("offset", "0") // смещение, необходимое для выборки определенного количества аудиозаписей
.setParameter("access_token", ACCESS_TOKEN); // токен доступа, полученный ранее
URI uri = builder.build();
Отправляем запрос и обрабатываем ответ:
(для работы с HTTP запросами используем библиотеку Apache HttpClient)
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = null;
try {
instream = entity.getContent();
String responseAsString = IOUtils.toString(instream);
parseAndDownload(responseAsString);
} finally {
if (instream != null)
instream.close();
}
}
Для парсинга JSON используем json simple, для загрузки файла — Apache Commons IO:
(важное замечание — необходимо чтобы папка в которую Вы хотите загружать файлы уже существовала)
private static void parseAndDownload(String resp) throws IOException, ParseException {
JSONParser parser = new JSONParser();
JSONObject jsonResponse = (JSONObject) parser.parse(resp);
JSONArray mp3list = (JSONArray) jsonResponse.get("response");
for (int i=1; i<mp3list.size(); i++) {
JSONObject mp3 = (JSONObject) mp3list.get(i);
// папка должна существовать!
String pathname = "e:/vkmp3/" + fixWndowsFileName(mp3.get("artist") +mp3.get("title"));
try {
File destination = new File(pathname + ".mp3");
if (!destination.exists()) {
FileUtils.copyURLToFile(new URL((String) mp3.get("url")), destination);
}
} catch (FileNotFoundException e) {
System.out.print("ERROR "+pathname);
}
}
}
В названиях композиций и именах исполнителей могут содержаться символы, запрещенные к использованию в именах файлов, убираем такие символы:
(используется Apache Commons Lang)
private static String fixWndowsFileName(String pathname) {
String[] forbiddenSymbols = new String[] {"<", ">", ":", """, "/", "\", "|", "?", "*"}; // для windows
String result = pathname;
for (String forbiddenSymbol: forbiddenSymbols) {
result = StringUtils.replace(result, forbiddenSymbol, "");
}
// амперсанд в названиях передаётся как '& amp', приводим его к читаемому виду
return StringEscapeUtils.unescapeXml(result);
}
Компилируем, запускаем — радуемся, глядя как вся онлайн коллекция аудио загружается на диск.
Заключительные замечания
- код достаточно грязный и не совсем подходит для промышленного использования (чтобы скачать очень большие по числу песен коллекции, его лучше модифицировать), но поставленную задачу он решает
- Java использован лишь для демонстрации идеи, думаю не составит труда перевести данный код на ваш любимый язык
- существует много программ для скачивания аудио, но доверия к ним нет абсолютно никакого (в плане передачи им своих личных данных)
- программу можно запускать несколько раз — будут загружены только несуществующие на диске файлы
Полный рабочий исходный код
Список зависимостей
- json-simple-1.1.1.jar
- commons-lang3-3.1.jar
- commons-io-2.4.jar
- httpcomponents-client-4.2.5-bin.zip (все jar файлы из архива)
Автор: kilonet