Powershell: скачиваем фотографии из Вконтакте

Раньше я уже публиковал powershell скрипт с помощью которого можно скачать из Вконтакте все аудиозаписи с вашей страницы, на этот раз делюсь скриптом который поможет скачать общедоступные фотографии указанной страницы, профиля, группы.

Скрипт скачивает все фотографии из фотоальбомов и складывает их по соответствующим папкам. Также скачиваются фотографии из служебного альбома "Фотографии на стене сообщества", это может пригодится, если нужно скачать фотографии из какого-либо фото-паблика Вконтакте, который в принципе не пользуется фотоальбомами, просто публикует фотографии сразу на стену.

Но и это еще не все: скрипт записывает в метаданные (поле "Название") скачанного файла количество набранных лайков к фотографии. Это может пригодится тем, кто хочет скачать у группы-конкурента все фотографии и отсортировать изображения по лайкам для добавления наиболее залайканных фотографий - так сказать снять самые сливки. При следующем запуске скрипта если изображение уже скачано, то будет лишь обновлена информация в метаданных о количестве лайков:

Powershell скачать фотографии вконтакте

Скрипт также запоминает какие фотографии были скачаны (в текстовом файле downloaded_files.txt каждой папки-альбом) и потом удалены - такие фотографии заново не перекачиваются.

 

Код скрипта:

#скрипт скачивает фотографии из вконтакте
#автор: elims.org.ua
<# #>

$photo_path = "D:\vk-photos\" #папка для сохранения изображений
$id = -22786271 #HD Обои

#альбомы которые нужно исключить:
$need_albums_id = 147102139,134040033,147102144,132334095

$global:photos_array = $null #обнулили масив всех фотографий сохраненного альбома 
$global:album_photos_count = $null #обнуление переменной с количествов фотографий в альбоме
$sleep_time = 1 #время задержки между запросами
[void][reflection.assembly]::loadwithpartialname("system.drawing") #для доступа как метаданным в файлах изображений
function get_photo_list { #функция получения списка фотографий
 $j = 0 
 do { #выбираем по 1000 фотографий пока не дойдем до конца альбома 
  Start-Sleep -s $sleep_time 
  $uri = $uri_part1 + $j + "&extended=1&v=5.24" 
  $request = $null
  do { #пытаемся получить ответ от сервера пока это не получится
   "Ссылка запроса: " + $uri
   $request = Invoke-WebRequest -Uri $uri
   Start-Sleep -s 1 #задержка в одну секунду
  } while ($request -eq $null) #пока не получим нормальный ответ
  $response_array = $request.content | ConvertFrom-Json #Конвертируем полученные данные из формата JSON в массив 
  $global:album_photos_count = $response_array.response.count #переопределяем количество фотографий в альбоме исходя из данных последнего запроса
  $global:photos_array = $photos_array + $response_array.response.items #сохраняем в масив список фотографий 
  "Сохраненны данные " + $photos_array.count + " фотографий" 
  $j = $j + 1000 
 } while ($j -le $global:album_photos_count) #выбираем по 1000 фотографий пока не дойдем до конца альбома 
}
function save_photos { #функция сохранения фотографии
 "начинаем сохранять фотографии, если есть задержка значит найдены уже скачанные фотографии и происходит их пропуск"
 $file_of_downloaded_files = $path + "\downloaded_files.txt" #имя файла со списком скачанных файлов
 if (Test-Path $file_of_downloaded_files) { #если список скачанных файлов существует
  $array_of_downloaded_files = Get-Content $file_of_downloaded_files #считываем его в массив
 }
 else { #если списка скачанных файлов не существует
  $array_of_downloaded_files = @() #создаем пустой массив
 }
 foreach ($photo_id in $photos_array.id) { 
  if ($photos_array.photo_2560[$i_photo] -ne $null) { $photo = $photos_array.photo_2560[$i_photo] } #пытаемся скачать фотографию в качестве 2560
  elseif ($photos_array.photo_1280[$i_photo] -ne $null) { $photo = $photos_array.photo_1280[$i_photo] } #если нет качества 2560 пытаемся скачать в 1280
  elseif ($photos_array.photo_807[$i_photo] -ne $null) { $photo = $photos_array.photo_807[$i_photo] } #если нет качества 1280 качаем в 807
  elseif ($photos_array.photo_604[$i_photo] -ne $null) { $photo = $photos_array.photo_604[$i_photo] } #если нет качества 807 качаем в 604
  else { $photo = $null } #если нет необходимого качества, то ничего не качаем
  $likes = $photos_array.likes[$i_photo].count #количество лайков к фотографии
  $likes_sum = $likes_sum + $likes #сумма лайков к фотографиям в альбоме
  $album_and_photo_id = [string]$photos_array.owner_id[$i_photo] + "_" + [string]$photos_array.id[$i_photo] 
  $filename = $path + $album_and_photo_id + ".jpg" #формируем имя файла без лайков в метаданных
  $filename2 = $filename.substring(0,$filename.length - 5) + "_with_likes.jpg" #формируем временное имя файла с лайками в метаданных
  if ( $photo -ne $null ) { #если ссылка на фотографию не пуста 
   "Альбом " + $i + " из " + $album_count + " : " + $album_title + " Фото " + $i_photo + " из " + $global:album_photos_count + ": " + $photo + " idPhoto: " + $photos_array.id[$i_photo] + " likes: " + $likes 
   if ((-not(Test-Path $filename))-and(-not($array_of_downloaded_files -contains $album_and_photo_id))) { #если такого файла не существует и он ранее не скачивался 
    Invoke-WebRequest $photo -OutFile $filename #скачиваем и сохраняем изображение
   } 
   #прописывание количества лайков в метаданные изображения, в поле "название"
   if (Test-Path $filename) { #если такой файл существует
    if (-not($array_of_downloaded_files -contains $album_and_photo_id)) { #если ранее этот файл не скачивался
     $array_of_downloaded_files = $array_of_downloaded_files + $album_and_photo_id 
    } 
    $img = [System.Drawing.Image]::Fromfile($filename) 
    $item = $img.psbase.GetPropertyItem(20624) #взяли в качестве примера не пустое поле с метаданными
    $item.id = 270 #поле "название"
    $item.type = 2 
    $likes_string = [int[]][char[]][string]("likes: " + $likes)
    $likes_string = $likes_string + 0
    $item.len = $likes_string.count 
    $item.Value = $likes_string #поле с количеством лайков
    $img.SetPropertyItem($item) #сохраняем информацию о лайках
    $filename2 = $filename.substring(0,$filename.length - 5) + "_with_likes.jpg" 
    $img.Save($filename2) #сохраняем файл с временным именем с информацией о лайках
    $img.dispose() #закрываем файл без информации о лайках
    Remove-Item $filename #удаляем файл без информации о лайках
    Rename-Item $filename2 $filename #переименовываем временное имя файла с метаданными в исходное имя
   } 
  }
  $i_photo++
 } 
 $likes_average = $likes_sum/$i_photo #подсчитываем в альбоме среднее количество лайков на фотографию
 $likes_text = "Суммарное количество лайков: " + $likes_sum + " количество фотографий: " + $i_photo + " средняя оценка фотографии: " + $likes_average + " лайков" 
 $export_file = $path + "\likescount.txt"
 $likes_text | Out-File $export_file -Encoding UTF8 #сохраняем в файл информацию о среднем количестве лайков на фотографию
 $array_of_downloaded_files | Out-File $file_of_downloaded_files -Encoding UTF8 #сохраняем в файл информацию о скачанных фотографиях
 $i_photo = 0 #обнулили порядковый номер фотографии в альбоме
 $likes_sum = $null #обнулили сумарное количество лайков 
}

#Получаем имя страницы\группы
if ($id -gt 0) { $uri = "https://api.vk.com/method/users.get?user_ids="+$id }
else {
 $group_id = $id * -1
 $uri = "https://api.vk.com/method/groups.getById?group_ids="+$group_id 
}
$request = Invoke-WebRequest -Uri $uri
$response_array = $request.content | ConvertFrom-Json #Конвертируем полученные данные из формата JSON в массив 
$id_name = $response_array.response.name + $response_array.response.first_name + $response_array.response.last_name
$id_name = $id_name -replace '(\\)|(\/)|(\*)|:|(\?)|"|<|>|(\|)|(\[)|(\])|(\n)', "_" #убираем некорректные знаки для имени файла
$id_name #имя страницы

$uri = "https://api.vk.com/method/photos.getAlbums?owner_id="+$id
$request = Invoke-WebRequest -Uri $uri
$response_array = $request.content | ConvertFrom-Json #Конвертируем полученные данные из формата JSON в массив 
$album_count = $response_array.response.aid.count #количество альбомов
$i = 0 #счетчик альбомов

foreach ($album in $response_array.response.aid) { #обходим каждый альбом 
 $i_photo = 0
 $global:album_photos_count = $response_array.response.size[$i] #количество фотографий в альбоме
 $album_title = $response_array.response.title[$i] #название альбома
 "Обрабатываем альбом: " + $album + " " + $album_title + " который состоит из " + $global:album_photos_count + " фотографий" 
 if ($need_albums_id -contains $album) { "Этот альбом пропускаем: " + $album } #перечисленные альбомы исключаются
 #if (-not($need_albums_id -contains $album)) { "Этот альбом пропускаем: " + $album } #перечисленные альбомы включаются, все другие исключаются
 else { 
  #создаем папку альбома 
  $album_title = $album_title -replace '(\\)|(\/)|(\*)|:|(\?)|"|<|>|(\|)|(\[)|(\])|(\n)', "_" #убираем некорректные знаки для имени файла
  $path = $photo_path + $id + "_" + $id_name + "\" + $album_title+"-album" + $album + "\" #имя папки
  if (-not(Test-Path $path)) { #если папка не существует 
   $result = New-Item -ItemType directory -Path $path #создаем папку
  } 
  $uri_part1 = "https://api.vk.com/method/photos.get?owner_id="+$id+"&album_id="+$album+"&count=1000&offset=" 
  get_photo_list #функция получения списка фотографий 
  save_photos #функция сохранения фотографий 
  $global:photos_array = $null #обнулили масив всех фотографий сохраненного альбома 
  $global:album_photos_count = $null #обнулили количество фотографий в альбоме
 } 
 $i++
}

#качаем фотографии из альбома типа "Фотографии на стене сообщества"
$path = $photo_path + $id + "_" + $id_name + "\photos_from_wall\" #имя папки
if (-not(Test-Path $path)) { #если папка не существует 
 $result = New-Item -ItemType directory -Path $path #создаем папку
} 
$album_title = "photos_from_wall"
$uri_part1 = "https://api.vk.com/method/photos.get?owner_id="+$id+"&album_id=wall&count=1000&offset=" 
get_photo_list #функция получения списка фотографий 
save_photos #функция сохранения фотографий

В самом начале скрипта указываются три входных параметра:

$photo_path = "D:\vk-photos\" #папка для сохранения изображений
$id = -22786271 #HD Обои
#альбомы которые нужно исключить:
$need_albums_id = 147102139,134040033,147102144,132334095,147158535,135840729,139940911,144126590,148117034,150218783,152202307,153578867,154970595,156369728,158058558,159302933,160588607,162081006,164777317,165552996,166939786,169325173,170826148,172398650,128782649,133628616,154341193,131374960,162793467,137349112,132441241,124936139,147158522,203298792,137419682,147102182,147102200,135127647,199208496,187953367 

$photo_path - папка в которую будут сохраняться фотографии. У меня это папка "D:\vk-photos\". Можете указать свою папку
$id - id странички или группы во вконтакте из которой нужно скачать фотографии. У меня это id -22786271 которое принадлежит вот этому паблику vk.com/oboihd (если в id есть знак "-" значит это сообщество, ггруппа, паблик)
$need_albums_id - id альбомов которые нужно исключить, то есть не нужно скачивать.

Ну а если Вам нужно избавиться от дубликатов фотографий, то в этом поможет программа "Duplicate Photo Finder" или ее аналог.

Пользуйтесь! Если есть вопросы - задавайте их в комментариях =)

Понравилось? =) Поделись с друзьями:

Обсуждение записи “Powershell: скачиваем фотографии из Вконтакте”

  1. Антон says:

    а нет скрипта для скачивания удалённых фотографий? (они на сервере хранятся, чтобы с дефрагментацией проблем не было, но нужна ссылка… в ручную не найти)

  2. Владимир Демянович (elims.org.ua) says:

    Антон, к сожалению я не знаю каким образом можно получить ссылки на удаленные фотографии.

  3. name says:

    А вообще кто-нибудь проверял работоспособность скрипта? Помимо всех прочих ошибок, которые выдал мне PowerShell и с которыми удалось справиться, одну убрать не удалось — Missing while or until keyword in do loop.

  4. name says:

    Подпихнул всё в PS ise и процесс пошёл.

  5. Мстислав says:

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

    #Получение ссылки для загрузки рисунка в вк.
    $url=Invoke-WebRequest’https://api.vkontakte.ru/method/photos.getWallUploadServer?gid=ид группы&access_token=МОЙ ТОКЕН’
    #Получаем урл
    $up=($url.content | ConvertFrom-Json).response.upload_url

    #Параметр пост запроса
    $postParams=@{photo=»C:\11.jpg»}
    #Запрос
    Invoke-WebRequest -Uri $up -Method POST -Body $postParams

    В итоге получаю
    {«server»:629531,»photo»:»[]»,»hash»:»68432950d3ab93e42e51ce42a1886453″}

    Соответственно фото он не принимает, что я делаю не так?

  6. Владимир Демянович (elims.org.ua) says:

    Мстислав, загружать файлы ВК через апи я не пробовал. Так как было лень разбираться, она не так проста, как просто опубликовать пост.

    Поэтому я делаю так: заранее вгружаю в ВК фотографии в какой-то фотоальбом, а потом уже публикую текст с фотографией (которая уже загружена в вк):

    «wall.post?owner_id=»+$id+»&message=» + $text + «&attachments=» + $photo_id + «&v=5.24&access_token=»+$token

  7. sambu says:

    была ошибка допилил
    была ошибка деление на ноль

    133 строка
    if (-not(Test-Path $path)) { #если папка не существует
    $result = New-Item -ItemType directory -Path $path #создаем папку
    }

  8. Найки says:

    А можете совсем немного изменить скрипт, чтобы имя файла сохранялось оригинальное.

    Например сейчас -60545552_453635558.jpg, а надо 3T2Vt9XA2t4.jpg

  9. Владимир Демянович (elims.org.ua) says:

    К сожалению нет свободного времени на это.

  10. Ильдар says:

    Здравствуйте, получается нужно просто вставить этот код в PS и изменить куда будет сохранятся, откуда качать и какие альбомы не трогать??Если это так, то я всё сделал правильно только выдает разные ошибки :( помогите!!!

  11. Ильдар says:

    ну ответь пожалуйста!!!

  12. Владимир Демянович (elims.org.ua) says:

    Ильдар, увы, нет времени на помощь в разбирании ошибок. Скрипт публиковался для тех людей, который знакомы с powershell и смогут сами поправить ошибки

  13. Ильдар says:

    Всё же спасибо за отклик!

Обсудить