Загрузка музыки из VK средствами Python

в 15:08, , рубрики: python, автоматизация, метки: ,

Вступление

Лирическое отступление

Здравствуй, публика Хабрахабра. Я уже некоторое время наблюдаю за Вами, читаю Ваши работы. Честно признаться, меня завораживает тонкий и одновременно смелый мир Хабра. Поэтому, немного поразмыслив, я решил влиться в Вашу компанию. Это, как Вы уже, наверное, заметили, мой первый пост, но я не призываю Вас быть помягче ко мне. Скорее, я хочу испытать все те чувства, которые пережили или переживают бывалые пользователи. Давно хотел это написать здесь — добро пожаловать под кат.

Что, как и, главное, зачем?

Все просто: скрипт, написанный на Python 3.3, позволяющий загрузить указанную композицию с небезызвестного vk.com. Я использовал только стандартные модули: urllib и html.parser. Выражу общее мнение, если скажу, что это тот еще велосипед.

Код

Собственно, код разделен на три условные части: класс для парсинга формы, класс для парсинга списка композиций и главная часть.

Парсинг формы входа

Как я уже упоминал, парсить мы будем при помощи html.parser.

class FormParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.url = None
        self.params = {}
        self.in_form = False
        self.form_parsed = False
        self.method = "GET"

    def handle_starttag(self, tag, attrs):
        tag = tag.lower()
        if tag == "form":
            if self.form_parsed:
                raise RuntimeError("Second form")
            if self.in_form:
                raise RuntimeError("Already in form")
            self.in_form = True 
        if not self.in_form:
            return
        attrs = dict((name.lower(), value) for name, value in attrs)
        if tag == "form":
            self.url = attrs["action"] 
            if "method" in attrs:
                self.method = attrs["method"]
        elif tag == "input" and "type" in attrs and "name" in attrs:
            if attrs["type"] in ["hidden", "text", "password"]:
                self.params[attrs["name"]] = attrs["value"] if "value" in attrs else ""

    def handle_endtag(self, tag):
        tag = tag.lower()
        if tag == "form":
            if not self.in_form:
                raise RuntimeError("Unexpected </form>")
            self.in_form = False
            self.form_parsed = True

Класс занимается тем, что находит тег form, input и прилежащие к ним атрибуты, вроде method, action и так далее.

Парсинг списка композиций

Код имеет похожую структуру и приведен ниже.

class TrackSearch(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.url = None
        self.params = {}
        self.in_form = False
        self.form_parsed = False
        self.method = "GET"
        
    def handle_starttag(self, tag, attrs):
        if self.url == None or len(self.url) < 10:
            tag = tag.lower()
            if tag == "input":
                attrs = dict((name.lower(), value) for name, value in attrs)
                if attrs["type"] == "hidden":
                    self.url = attrs["value"]

Думаю, ничего сложного здесь нет. Класс парсит список в поисках первой композиции в начале списка — самый релевантный вариант — и сохраняет ссылку на неё в self.url. Проверка len(self.url) < 10 нужна лишь для того, чтобы отсеять первые два input, необходимые для функционирования поиска VK.

Интерфейс и вызовы

Конечно, классов, указанных выше, недостаточно. Чтобы успешно авторизоваться, необходимо правильно обработать cookie. На помощь приходит urllib.request и http.cookiejar. Создаем обработчик.

opener = urllib.request.build_opener(
        urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()),
        urllib.request.HTTPRedirectHandler())

Теперь, когда других препятствий нет, мы можем начать.

#Сбор необходимой информации
print("VK Music Downloader")
login = input("Телефон или email > ")
password = input("Пароль > ")
track = input("Исполнитель и название композиции > ")
filename = track + ".mp3"
track = urllib.parse.quote(track)

#Авторизация
print("Авторизация...")
parser = FormParser()
response = str(opener.open("http://m.vk.com/").read())
parser.feed(response)
parser.params["email"] = login
parser.params["pass"] = password
response = opener.open(parser.url, urllib.parse.urlencode(parser.params).encode())
parser.close()

#Поиск
print("Поиск композиции...")
response = str(opener.open("http://m.vk.com/audio?act=search&q=%s" % track).read())
seacher = TrackSearch()
seacher.feed(response)

#Загрузка
print("Загрузка > %s" % filename)
with urllib.request.urlopen(seacher.url) as data, 
     open(filename, 'wb') as fout:
     fout.write(data.read())

seacher.close()
input("Загрузка завершена")

Заключение

Пример работы скрипта.
Загрузка музыки из VK средствами Python

На этом мой первый пост заканчивается. Спасибо тем, кто уделил время, чтобы просмотреть его. Если у Вас появились вопросы, я с радостью отвечу. Всего доброго.

Автор: Merlen_Gross

Источник


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