Я люблю автоматизацию, но иногда лень побеждает. Конечно, пока не настолько, чтобы менять URL в адресной строке браузера мышкой, “потому что лень клавиатуру вынимать”, но уже движусь к этому. А в итоге получается дедрофекальное программирование. Если вы не любите читать описание костылей или нытье, то можно проходить мимо этой заметки.

Захотел я скачать пару альбомов из ВК, продолжая его архивирование. Поискал что-нибудь онлайн — надо регистрироваться, да еще и входить там через VK надо — не, параноик во мне пока сильнее. Может, есть какое-нибудь расширение браузера, но искать рабочее тоже лень. Ладушки, попробуем через VK API сделать.

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

Во-первых, последняя версия API (5.126) вместо адекватных ссылок на изображение вернет массив с описаниями копий:

"sizes": [
  {
    "url": "https://pp.vk.me/c633825/v633825034/7369/wbsAsrooqfA.jpg",
    "width": 130,
    "height": 87,
    "type": "m"
  }, {
    "url": "https://pp.vk.me/c633825/v633825034/736e/SKfi-9SeR0I.jpg",
    "width": 200,
    "height": 133,
    "type": "p"
  },
...
]

Конечно, это правильный подход с точки зрения API — ведь размеры могут поменяться с версиями, там еще большая вариативность для разных соотношений высоты и ширины картинки, удобно делать превьюшки и т.п. Но можно же было ссылку на оригинал как-нибудь отдельно поставить! Парсить сайт не хочется (хоть и умею, но не всю же жизнь краулер ВК писать). Написать код, который проходится по массиву и ищет картинку с максимальной шириной и/или высотой — задача для школьника, но даже этот код писать лень. Самое простое решение — переключиться на версию 5.21 и там поперек всех best-practice прочитать ссылку на максимальный размер из поля “photo_2560”.

Во-вторых, тот JSON, который показывается в окошке справа — не просто текст, а “красиво” отформатированный HTML. И если попробовать оттуда скопировать JSON, то ссылки будут урезанные, с троеточием: “https://sun9-30.u...Ktwc&type=album”. Это не наши©, подумал я. Благо есть инструменты разработчика в браузере и можно перехватить ответ сервера. Он будет примерно такого формата:

{
  "payload": [
    0,
    ["JSON с ответом API, сереализованный в строку"]
  ]
}

М-м-м, JSON-строка внутри JSON, мое любимое! Ну ладно, тут уже много мозгов не надо, сохраняем в файл, и накидываем немного питона:

import json
import sys

with open(sys.argv[1]) as f:
    response = json.load(f)

photos = json.loads(response["payload"][1][0])

for photo in photos['response']['items']:
    print(photo["photo_2560"])

Вывод можно кинуть либо в промежуточный файл, либо сразу в | xargs -P 10 -n 1 curl -sO, который знаком по предыдущей статье.

Одна проблемка осталась: название файла уж больно длинное и содержит куски запроса после ‘?’. И порядок фото будет случайный.

Немного мазохизма с башем приведут к такой комбинации:

| nl -nrz | xargs -L1 -P10 sh -c 'curl -s -o"$0.jpg" "$1"'

nl нумерует строки (но это можно сделать и через cat -n), а его аргумент -nrz добавляет нули справа для тех просмотрщиков фото, которые не умеют понимать человеческий порядок. А портянка с xargs работает через промежуточный шелл, чтобы можно было разделить аргументы. Это можно сделать и попроще: xargs -L1 -P10 curl -s -o, но тогда не будет расширения .jpg у файлов, а нормальное разбивать аргументы так, чтобы еще их можно было подставлять, xargs не умеет.

Что бы ни делать, лишь бы нормальный код не писать! Однако цель достигнута: ВК поруган, альбом скачан, полениться удалось, что-то новое узнать — тоже.