Source code for vk_api.audio

# -*- coding: utf-8 -*-
"""
:authors: python273
:contact: https://vk.com/python273
:license: Apache License, Version 2.0, see LICENSE file

:copyright: (c) 2018 python273
"""

import re

from bs4 import BeautifulSoup

from .audio_url_decoder import decode_audio_url
from .exceptions import AccessDenied

RE_AUDIO_ID = re.compile(r'audio(-?\d+)_(\d+)')
RE_ALBUM_ID = re.compile(r'act=audio_playlist(-?\d+)_(\d+)')

TRACKS_PER_USER_PAGE = 50
TRACKS_PER_ALBUM_PAGE = 100
ALBUMS_PER_USER_PAGE = 100


[docs]class VkAudio(object): """ Модуль для получения аудиозаписей без использования официального API. :param vk: Объект :class:`VkApi` """ __slots__ = ('_vk', 'user_id') def __init__(self, vk): self.user_id = vk.method('users.get')[0]['id'] self._vk = vk
[docs] def get_iter(self, owner_id=None, album_id=None): """ Получить список аудиозаписей пользователя (по частям) :param owner_id: ID владельца (отрицательные значения для групп) :param album_id: ID альбома """ if owner_id is None: owner_id = self.user_id if album_id is not None: url = 'https://m.vk.com/audio?act=audio_playlist{}_{}'.format( owner_id, album_id ) offset_diff = TRACKS_PER_ALBUM_PAGE else: url = 'https://m.vk.com/audios{}'.format(owner_id) offset_diff = TRACKS_PER_USER_PAGE offset = 0 while True: response = self._vk.http.get( url, params={ 'offset': offset }, allow_redirects=False ) if not response.text: raise AccessDenied( 'You don\'t have permissions to browse user\'s audio' ) tracks = scrap_data(response.text, self.user_id) if not tracks: break for i in tracks: yield i offset += offset_diff
[docs] def get(self, owner_id=None, album_id=None): """ Получить список аудиозаписей пользователя :param owner_id: ID владельца (отрицательные значения для групп) :param album_id: ID альбома """ return list(self.get_iter(owner_id, album_id))
[docs] def get_albums_iter(self, owner_id=None): """ Получить список альбомов пользователя (по частям) :param owner_id: ID владельца (отрицательные значения для групп) """ if owner_id is None: owner_id = self.user_id offset = 0 while True: response = self._vk.http.get( 'https://m.vk.com/audio?act=audio_playlists{}'.format( owner_id ), params={ 'offset': offset }, allow_redirects=False ) if not response.text: raise AccessDenied( 'You don\'t have permissions to browse {}\'s albums'.format( owner_id ) ) albums = scrap_albums(response.text) if not albums: break for i in albums: yield i offset += ALBUMS_PER_USER_PAGE
[docs] def get_albums(self, owner_id=None): """ Получить список альбомов пользователя :param owner_id: ID владельца (отрицательные значения для групп) """ return list(self.get_albums_iter(owner_id))
[docs] def search_user(self, owner_id=None, q=''): """ Искать по аудиозаписям пользователя :param owner_id: ID владельца (отрицательные значения для групп) :param q: запрос """ if owner_id is None: owner_id = self.user_id response = self._vk.http.get( 'https://m.vk.com/audio', params={ 'id': owner_id, 'q': q }, allow_redirects=False ) if not response.text: raise AccessDenied( 'You don\'t have permissions to browse {}\'s audio'.format( owner_id ) ) return [ i for i in scrap_data(response.text, self.user_id) if i['owner_id'] == owner_id ]
[docs] def search(self, q='', offset=0): """ Искать аудиозаписи :param q: запрос :param offset: смещение """ response = self._vk.http.get( 'https://m.vk.com/audio', params={ 'act': 'search', 'q': q, 'offset': offset } ) return scrap_data(response.text, self.user_id)
def scrap_data(html, user_id): """ Парсинг списка аудиозаписей из html странцы """ soup = BeautifulSoup(html, 'html.parser') tracks = [] for audio in soup.find_all('div', {'class': 'audio_item'}): if 'audio_item_disabled' in audio['class']: continue artist = audio.select_one('.ai_artist').text title = audio.select_one('.ai_title').text duration = int(audio.select_one('.ai_dur')['data-dur']) full_id = tuple( int(i) for i in RE_AUDIO_ID.search(audio['id']).groups() ) link = audio.select_one('.ai_body').input['value'] if 'audio_api_unavailable' in link: link = decode_audio_url(link, user_id) tracks.append({ 'id': full_id[1], 'owner_id': full_id[0], 'url': link, 'artist': artist, 'title': title, 'duration': duration, }) return tracks def scrap_albums(html): """ Парсинг списка альбомов из html странцы """ soup = BeautifulSoup(html, 'html.parser') albums = [] for album in soup.find_all('div', {'class': 'audioPlaylistsPage__item'}): link = album.select_one('.audioPlaylistsPage__itemLink')['href'] full_id = tuple(int(i) for i in RE_ALBUM_ID.search(link).groups()) stats_text = album.select_one('.audioPlaylistsPage__stats').text plays = int(stats_text.split(maxsplit=1)[0]) albums.append({ 'id': full_id[1], 'owner_id': full_id[0], 'url': 'https://m.vk.com/audio?act=audio_playlist{}_{}'.format( *full_id ), 'title': album.select_one('.audioPlaylistsPage__title').text, 'plays': plays }) return albums