Pull to refresh

Скачивание музыки из vk.com

Reading time4 min
Views73K
После недавней шумихи вокруг аудиозаписей на сайте vk.com решил подстраховаться и скопировать всю свою коллекцию на жесткий диск. Для решения мною была написана простенькая утилита на Java. Ниже — её код c комментариями. Статья предназначена для читателей, знакомых с любым языком программирования общего назначения и умеющих компилировать и запускать написанные на нем программы.

Важное замечание: если Ваши аудиозаписи уже изъяты, то скачать их таким образом скорее всего не получится.

Подготовка

Список аудиозаписей получается через API сайта, для доступа к API нужен access token (токен доступа). Для получения токена необходимо перейти по адресу (это стандартный способ, описанный в документации vk.com для разработчиков):

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


и на загрузившейся страничке разрешить доступ приложению к своим аудиозаписям, после этого вы будете перенаправлены по адресу вида:

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 файлы из архива)
Tags:
Hubs:
+1
Comments17

Articles