Музыка, я думаю, её любят все…
Наверное, я люблю её больше чем другие, потому что решился поднять заброшенный проект интернет радиостанции. Конечно же у меня возник вопрос «Где взять музыку?». Я решил не спешить и понаблюдать за более развитыми радиостанциями, что они крутят, как часто etc. Для этого был написан небольшой скрипт на питоне, который определял текущий трек и заносил его в базу.
После недели ожидания у меня была база из 686 песен, которые отыграли 3750 раз. Качать это все вручную явно плохая идея.
Поэтому я, вооружившись интернетом, пайтоном, набравшись терпения, начал писать.
В качестве источника mp3шек я выбрал сайт vkontakte.
Чтобы не мучиться с обработкой кукисов, я совсем немного изменил готовый http клиент.
#filename: http.py
import urllib, urllib2, cookielib

class client
    def __init__(self, proxy=None, headers=[]):      
        self.cookie_handler   = urllib2.HTTPCookieProcessor(cookielib.CookieJar())
        self.redirect_handler = urllib2.HTTPRedirectHandler()
        self.http_handler     = urllib2.HTTPHandler()
        self.https_handler    = urllib2.HTTPSHandler()
        self.opener = urllib2.build_opener(self.http_handler, 
                                           self.https_handler, 
                                           self.cookie_handler, 
                                           self.redirect_handler)
        if proxy: 
            self.proxy_handler = urllib2.ProxyHandler(proxy)
            self.opener.add_handler(self.proxy_handler)
        self.opener.addheaders = headers      
        urllib2.install_opener(self.opener)
        
    def request(self, url, params={}, timeout=5):
        params = urllib.urlencode(params)
        html = urllib2.urlopen(url, params)
        return html.read()

Тут все просто, при инициализации мы устанавливаем заголовки, обработчики редиректов, кук и т.д.
А при вызове request кодируются пост параметры, открывается соединение и функция возвращает прочтенные данные.

Теперь сам скрипт.
#filename: vkdl.py
import re
import http

class song:
    def __init__(self, name, params):
        self.name = '%s - %s' % tuple(name)
        self.dur = float(params[1])
        self.title = name[1]
        self.author = name[0]
        self.url = params[0]
        self.size = None
        
    def bitrate(self):
        self.size = http.filesize(self.url)
        self.bitrate = round(self.size/self.dur*0.008)
        self.bitrate = round(self.bitrate*1.25,-1)*0.8
        return self.bitrate

class mp3(http.client):
    def __init__(self):
        http.client.__init__(selfNoneself.headers)

    def login(self, email, passw):
        self.post1['email'= email
        self.post1['pass']  = passw
        res  = self.request(self.url[0], self.post1)
        res  = res.decode('cp1251')
        self.post2['s'= re.findall(self.pat[0], res)[0]
        self.request(self.url[1], self.post2)

    def search(self, sname):
        self.post3['c[q]'= sname
        result = self.request(self.url[2], self.post3)
        names = re.findall(self.pat[2], result)
        params = re.findall(self.pat[1], result)
        return map(song, names, params)

    headers = [("Content-type""application/x-www-form-urlencoded"), ("Accept""text/plain")]
    post1 = {'act':'login''to':'''pda':'1''from_host':'m.vk.com''email':'''pass':''}
    post2 = {'s':'''op':'slogin''redirect':1'expire':0'to':''}
    post3 = {'al':'1''c[q]':'''c[section]':'audio'}
    query = "?from=audio&q=%s&section=audio"
    url = ('http://login.vk.com/''http://m.vk.com:80/login''http://vk.com/al_search.php')
    pat = ("name='s' value='(.+?)' />"
           '<input type="hidden" id="audio_info.+?" value="(.+?),(\d+)" />'
           'audio_title.+?;">(.+?)</a>.+?">(.+?)</span')

К сожалению вконтакте не хранит информацию о размере трека, поэтому пришлось создать структуру song которая хранит информацию о треке, посчитать битрейт и размер файла можно вызовом метода bitrate. А чтобы этот метод работал необходимо добавить в наш предыдущий модуль http.py функцию filesize.
#filename: http.py
def filesize(url):
    try:
        f = urllib2.urlopen(url, timeout=30)
        inf, c = f.info(), f.close()
        length = inf.getheaders("Content-Length")
        return int(length[0])
    except
        return 0

Далее у нас следует класс mp3. Он унаследован от класса http клиента.
После создания экземпляра класса, мы должны авторизоваться.
Для этого был создан метод login, авторизация на мобильной версии контакта проще поэтому авторизуемся на мобильной версии а ищем на полной. С поиском тоже все просто используется тот же request плюс несколько регулярных выражений.
Вот пример того как этот класс можно использовать:
#filename: main.py
import vkdl

path = 'E:/clubarchive/'
def download(url, fname):
    from urllib2 import urlopen
    wf = urlopen(url)
    lf = open(path+fname, 'wb')
    lf.write(wf.read())
    lf.close, wf.close()
    
= open('file2.txt''r')
songs = f.read().split('\n')
f.close

downloader = vkdl.mp3()
downloader.login('***@gmail.com''***')

for song in songs:
    res = downloader.search(song)
    download(res[0].url, song+'.mp3')
    print song, '- download complete'

В этом примере мы определили функцию download, прочитали названия треков из file2.txt и загрузили каждую по очереди.
Конечно, это примитивный пример использования, можно искать песни определенной продолжительности и определенного битрейта.
Но я думаю что на сегодня кода хватит.
P.S. Искать песни вконтакте слишком часто не стоит, потому что после такого ДОСа контакт начинает врать о том что ничего не нашел.