![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Качая подкасты
Однажды я делился своим опытом велосипедостроения, когда накодил на питоне качалку аудиофайлов из rss потоков. Потом имел неосторожность на работе обмолвиться о своем поделии, и коллега спросил меня: "а что, wget нельзя было?". Я ответил уклончиво, стесняясь признаться, что слышу про эту утилиту... не совсем впервые, конечно, но почти. Пообещал сам себе, что в следующий раз ради расширения кругозора попробую обойтись одним башем и другими подручными средствами. Хотя питон тоже почти всегда в системе из коробки есть, но вот тем не менее. Сейчас мне опять приспичило много чего накачать и вспомнил о том обете. Bash, curl, grep, awk и wget мне были в помощь, благо ставить их не надо, они есть.
Мне захотелось иметь все подкасты Sprachbar с сайта dw.com. На рутрекере есть раздача, я оттуда про этот подкаст и узнал, однако там сейчас не совсем полный набор. Существуют готовые решения для скачивания добра с сайтов, тот же wget имеет ключи для рекурсивной загрузки по ссылкам. Но мне не нужно было вообще все, а только набор mp3 и pdf файлов, причем красиво разложенных и поименованных. Поэтому накропал скрипт, щас покажу какой. Мотивацией было не желание похвастать, какой я прекрасный код написал, а скорее наоборот. Уверен, что его можно переписать в два раза короче и в десять раз эффективнее. Но он был написан с нуля в том смысле, что одним глазом я смотрел в редактор, а вторым в документацию, где для меня почти все было в новинку. Буквально каждая строчка рождалась в режиме "ага, вот так значит тоже можно". Результат меня вдохновил и порадовал: все заработало и скачалось. Приятно, когда компьютер делает то, о чем его просишь. Всегда бы так.
Сначала сам скрипт, а потом будет история его создания с позитивной моралью в конце
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #!/bin/sh # Качалка архива подкаста Sprachbar с сайта http://www.dw.com dwstart="http://www.dw.com/de/deutsch-lernen/sprachbar/s-9011" archiv_list=`curl $dwstart | grep '<a href="/de/sprachbar-archiv' | awk -F"\"" '{print " http://www.dw.com"$2}'` #ссылка на страницу с архивом: (например http://www.dw.com/de/sprachbar-archiv-a/a-2216456) for archiv_url in $archiv_list do #имя каталога для архивов по буквам: /sprachbar-archiv-a, /sprachbar-archiv-b и т.д. dirname=`echo "$archiv_url" | awk -F"/" '{print $5}'` if [ ! -d $dirname ]; then mkdir $dirname fi cd $dirname podlist=`curl -s $archiv_url | grep '<a href="/de/[^/]*/a-[0-9]*">' | awk -F"\"" '{print " http://www.dw.com"$2}' ` if [ ! -e "podlist.txt" ]; then echo "$podlist" >> "podlist.txt" fi for podcast in $podlist do if echo "$podcast" | grep -i "sprachbar-archiv" >/dev/null then echo "skip " "$podcast" else podname=`echo "$podcast" | awk -F"/" '{print $5}'` echo "process " "$podname" "( " "$podcast" " )" pdfname="$podname"".pdf" mp3name="$podname"".mp3" # выкачиваем pfd файл из http://www.dw.com/downloads/28067485/ab-die-post.pdf pdflinks=`curl -s $podcast | grep 'pdf' | awk -F"\"" '{ print "http://www.dw.com"$2}'` for pdfurl in $pdflinks do if [ ! -e $pdfname ]; then echo "saving file from" "$pdfurl" " into " "$pdfname" wget -O "$pdfname" "$pdfurl" sleep 5 else echo "file " "$pdfname" " already exist" fi done # выкачиваем mp3 файл из http://www.dw.com/overlay/media... + http://radio-download.dw...dwdownload.mp3 medialinks=`curl $podcast | grep '/overlay/media' | awk -F"\"" '{print "http://www.dw.com"$2}'` for mediaurl in $medialinks do mp3links=`curl -s $mediaurl | grep '^<a href=\"[^"]*mp3' | awk -F "\"" '{print $2}'` for mp3 in $mp3links do if [ ! -e $mp3name ]; then echo "saving file from" "$mp3" "into" "$mp3name" wget -O "$mp3name" "$mp3" sleep 5 else echo "file " "$mp3" " already loaded" fi done done fi done cd ".." done |
На сайте dw.com подкаст sprachbar расположен вот так примерно:

C заглавной страницы Sprachbar, как впрочем и с любой другой этого подкаста, есть ссылки на архивы аудиозаписей.

На странице архива ссылки на подкасты

На странице подкаста есть прямая ссылка на файл с транскриптом.

Иногда есть и прямая ссылка на mp3, но чаще ссылка на попап

Из которого уже можно забирать аудиофайл.
То есть файловая иерархия выглядит так
http://www.dw.com/de/deutsch-lernen/sprachbar/s-9011 http://www.dw.com/de/sprachbar-archiv-a/a-2216456 Архив A http://www.dw.com/de/ab-die-post/a-16454927 Подкаст №1 http://www.dw.com/downloads/28067485/ab-die-post.pdf Ссылка на pdf файл http://www.dw.com/overlay/media/de/ab-die-post/16431472/16454927 Всплывающее окно с медиа содержимым http://radio-download.dw.com/Events/ ... /65CF2EDA_1_dwdownload.mp3 http://www.dw.com/de/abk%C3%BCrzungen/a-2987918 Подкаст №2 ... http://www.dw.com/de/sprachbar-archiv-b/a-2216464 Архив B
Открыл терминал и начал эксперименты в консоли. Сначала получил содержимое самой первой страницы. Хотя вместо s-9011 тут можно подставить почти любую, потому что ссылки на каталог архивов есть на каждой странице подкаста.
curl http://www.dw.com/de/deutsch-lernen/sprachbar/s-9011
В выводе увидел такие строчки
<a href="/de/sprachbar-archiv-a/a-2216456"> <a href="/de/sprachbar-archiv-b/a-2216464"></pre> ...
Это ссылки на нужные архивы, выцепил их с помощью утилиты grep, которая ищет в тексте строки по заданному образцу
curl http://www.dw.com/de/deutsch-lernen/sprachbar/s-9011 | grep '<a href="/de/sprachbar-archiv' <a href="/de/sprachbar-archiv-a/a-2216456"> <a href="/de/sprachbar-archiv-b/a-2216464"> <a href="/de/sprachbar-archiv-cd/a-2216467"> ... <a href="/de/sprachbar-archiv-xyz/a-2216821">
Если вместо html тега до первой кавычки подставить http://www.dw.com, убрать обе кавычки и закрывающую скобку, то получится список ссылок на страницы с архивами. Утилита awk поможет в этом
curl http://www.dw.com/de/deutsch-lernen/sprachbar/s-9011 | grep '<a href="/de/sprachbar-archiv' | awk -F"\"" '{print "http://www.dw.com"$2}'
В чем смысл последней команды? Программа awk воспринимает текст как таблицу и позволяет выполнять всякие действия над полями. Первый параметр -F"\"" означает, что указываем кавычку в качестве символа разделителя столбцов. То есть каждая строка состоит из трех полей. Первое и последнее - это html теги, а между ними как раз нужный адрес. Печатаю его (print $2), прицепив сначала "http://www.dw.com"
Вот результат работы:
http://www.dw.com/de/sprachbar-archiv-a/a-2216456 http://www.dw.com/de/sprachbar-archiv-b/a-2216464 ... http://www.dw.com/de/sprachbar-archiv-xyz/a-2216821
Есть полный список корректных ссылок на архивы, по которым теперь можно идти и добираться уже до ссылок на подкасты и текст. Если сurl'ом поглядеть на страницу с первым архивом, в выводе можно найти ссылки на конкретные подкасты
<a href="/de/ab-die-post/a-16454927"> <a href="/de/abkürzungen/a-2987918"> <a href="/de/adeliges-allerlei/a-3090984">
Их опять вытаскиваю с помощью grep и awk.
curl http://www.dw.com/de/sprachbar-archiv-a/a-2216456 | grep '<a href="/de/[^/]*/a-[0-9]*">' | awk -F"\"" '{print " http://www.dw.com"$2}' ... http://www.dw.com/de/ab-die-post/a-16454927 http://www.dw.com/de/abkürzungen/a-2987918 http://www.dw.com/de/adeliges-allerlei/a-3090984
Регулярное выражение
a href="/de/[^/]*/a-[0-9]*"находит ссылки вида /de/ab-die-post/a-16454927. К сожалению, под этот образец подходят и ссылки на архивы /de/sprachbar-archiv-a/a_NNNN. Отфильтровать их у меня по-быстрому не получилось, поэтому потом в цикле проверяю ссылки явно на наличие подстроки sprachbar-archiv и пропускаю их.
Наконец добирался до странички с подкастом и сначала добываю прямую ссылку на pdf файл с транскриптом.
curl http://www.dw.com/de/ab-die-post/a-16454927 | grep 'pdf' | awk -F"\"" '{ print "http://www.dw.com"$2}' http://www.dw.com/downloads/28067485/ab-die-post.pdf
Потом ссылку на всплывающе окно с медиасодержимым и оттуда ссылку на mp3
curl http://www.dw.com/de/ab-die-post/a-16454927 | grep '/overlay/media' | awk -F"\"" '{print "http://www.dw.com"$2}' http://www.dw.com/overlay/media/de/ab-die-post/16431472/16454927
curl http://www.dw.com/overlay/media/de/ab-die-post/16431472/16454927 | grep '^<a href=\"[^"]*mp3' | awk -F "\"" '{print $2}' http://radio-download.dw.com/Events/dwelle/dira/mp3/deutschkurse/sprachbar/65CF2EDA_1_dwdownload.mp3
Ок, есть две ссылки на файлы. Их можно выкачать утилитой wget.
wget http://www.dw.com/downloads/28067485/ab-die-post.pdf
Для аудифайла еще подменяю имя на красивое
wget -O ab-die-post.mp3 http://radio-download.dw.com/Events/dwelle/dira/mp3/deutschkurse/sprachbar/65CF2EDA_1_dwdownload.mp3
Завернул в цикл, добавил проверки, чтобы можно было запустить повторно и не тянуть заново уже скаченное. Еще, держа в памяти как меня забанили на гутенберге за автоматизацию выкачивания, добавил пятисекундную задержку, чтобы не создавать слишком плотную нагрузку. Наверное тут можно было и без этого обойтись, но в случае реальной опасности бана можно наоборот задержку сделать случайной продолжительности и добавить закачку из-под прокси, у wget есть такой режим. В строчках 36, 49 и 52 поиск ссылок на файлы сделан через итерацию по списку, а пишется только первый элемент, что выглядит ошибкой. Если честно, так оно и есть, и здесь код как говорится "попахивает", но во всех местах, из-за которых пришлось так наговнокодить нужный документ шел как раз первым, поэтому и так сойдет не стал закапываться, раз уж рабочий вариант.
Вот и все. Позитивная мораль здесь в том, что последние строчки скрипта писались гораздо быстрее первых. Пусть даже самые простые регулярки или синтаксис awk кажутся на первый взгляд птичьим языком (да и на второй взгляд тоже), но осваивается этот свист довольно просто. Гугл в помощь. Так что если вам вдруг когда захочется по-быстрому накидать ходилку по сайтам или качалку, не выходя из терминала, то делюсь восторгом неофита: curl, grep, awk, wget!
no subject
no subject
no subject
А потом ещё и для этого велосипеда написать фреймворк 😀👍
no subject
реально быстрее навелосипедить
no subject
линукс вообще приятен тем, что там куча скриптовых языков сразу под рукой, настроены и готовы хоть сейчас в бой.
я тут некоторое время назад решил, что никуда не годится не уметь вгетить в основном языке програмирывания, и полез в интернеты
деградироватьчитать как это делается. конечно же, никто велосипедов не строит, берут готовую либу и вперёд. но даже взять готовую libcurl и скачать всё что надо за отведённые нибисами пятнадцать свободных минут в день как-то до сих пор не удалось. позор мнеno subject
no subject
2. wget имеет ключ -A pdf -A mp3 что означает сохранять только эти типы файлов.
no subject