Экспорт фотоальбомов из ВКонтакта

от автора

Преамбула

Дело было вечером, делать было нечего и тут мне в голову пришла мысль: «Как же мне выгрузить все фотографии из ВКонтакта на компьютер?» Недолго думая, я написал утилиту для этого и решил поделиться с общественностью, возможно я не один такой.

Поехали

В качестве инструмента для работы с API, путём кратких поисков, была выбрана библиотека vk_api. Для работы с сетью она использует Requests, поэтому и эта библиотека требуется для запуска.

Пощупать

GitHub Pages проекта

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

#!/usr/bin/env python  """     :mod:`vkporter`     ~~~~~~~~~~~~~~~      A micro tool for export photo albums from `vk.com <https://vk.com>`_.      It's based on `VK_API <https://github.com/python273/vk_api>`_      by Kirill Python <mikeking568@gmail.com>,      `Requests <python-requests.org>`_      and `ProgressBar <https://code.google.com/p/python-progressbar/>`_.      :copyright: (c) 2013 by Andrey Maksimov.     :license: BSD, see LICENSE for more details. """  __author__ = 'Andrey Maksimov <meamka@me.com>' __date__ = '09.03.13' __version__ = '0.1.1'  import argparse import datetime from getpass import getpass import os import time import sys  try:     import requests except ImportError:     print("Cannot find 'requests' module. Please install it and try again.")     sys.exit(0)  try:     from vk_api import VkApi except ImportError:     print("Cannot find 'vk_api' module. Please install it and try again.")     sys.exit(0)   def connect(login, password):     """Initialize connection with `vk.com <https://vk.com>`_ and try to authorize user with given credentials.      :param login: user login e. g. email, phone number     :type login: str     :param password: user password     :type password: str      :return: :mod:`vk_api.vk_api.VkApi` connection     :rtype: :mod:`VkApi`     """     return VkApi(login, password)   def get_albums(connection):     """Get albums list for currently authorized user.      :param connection: :class:`vk_api.vk_api.VkApi` connection     :type connection: :class:`vk_api.vk_api.VkApi`      :return: list of photo albums or ``None``     :rtype: list     """     try:         return connection.method('photos.getAlbums')     except Exception as e:         print(e)         return None   def get_photos(connection, album_id):     """Get photos list for selected album.      :param connection: :class:`vk_api.vk_api.VkApi` connection     :type connection: :class:`vk_api.vk_api.VkApi`     :param album_id: album identifier returned by :func:`get_albums`     :type album_id: int      :return: list of photo albums or ``None``     :rtype: list     """     try:         return connection.method('photos.get', {'aid': album_id})     except Exception as e:         print(e)         return None   def download(photo, output):     """Download photo      :param photo:     """     url = photo.get('src_xxxbig') or photo.get('src_xxbig') or photo.get('src_xbig') or photo.get('src_big')      r = requests.get(url)     title = photo['pid']     with open(os.path.join(output, '%s.jpg' % title), 'wb') as f:         for buf in r.iter_content(1024):             if buf:                 f.write(buf)   def sizeof_fmt(num):     """Small function to format numbered size to human readable string      :param num: bytes to format     :type num: int      :return: human readable size     """     for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:         if num < 1024.0:             return "%3.1f %s" % (num, x)         num /= 1024.0   if __name__ == '__main__':     parser = argparse.ArgumentParser(description='', version='%(prog)s ' + __version__)     parser.add_argument('username', help='vk.com username')     # parser.add_argument('password', help='vk.com username password')     parser.add_argument('-o', '--output', help='output path to store photos',                         default=os.path.abspath(os.path.join(os.path.dirname(__file__), 'exported')))      args = parser.parse_args()      # expand user path if necessary     if args.output.startswith('~'):         args.output = os.path.expanduser(args.output)      start_time = datetime.datetime.now()     try:         password = getpass("Password: ")          # Initialize vk.com connection         connection = connect(args.username, password)          # Request list of photo albums         albums = get_albums(connection)         print("Found %s album%s:" % (len(albums), 's' if len(albums) > 1 else ''))         ix = 0         for album in albums:             print('%3d. %-40s %4s item%s' % (             ix + 1, album['title'], album['size'], 's' if int(album['size']) > 1 else ''))             ix += 1          # Sleep to prevent max request count         time.sleep(1)          if not os.path.exists(args.output):             os.makedirs(args.output)          for album in albums:             response = get_photos(connection, album['aid'])             output = os.path.join(args.output, album['title'])             if not os.path.exists(output):                 os.makedirs(output)              processed = 0              for photo in response:                 percent = round(float(processed) / float(len(response)) * 100, 2)                 sys.stdout.write(                     "\rExporting %s... %s of %s (%2d%%)" % (album['title'], processed, len(response), percent))                 sys.stdout.flush()                  download(photo, output)                 processed += 1      except Exception as e:         print(e)         sys.exit(1)      except KeyboardInterrupt:         print('VKPorter exporting stopped by keyboard')         sys.exit(0)      finally:         print("Done in %s" % (datetime.datetime.now() - start_time))  

Примеры

По умолчанию экспорт происходит в папку ./exported

$ ./vkporter.py username@vk.com 

Путь для экспорта можно указать при запуске

$ ./vkporter.py -o ~/Documents/Exported username@vk.com 

Выглядит это примерно так:
image

ссылка на оригинал статьи http://habrahabr.ru/post/172131/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *