Архивы: bash

Очередная качалка торрентов с lostfilm.tv

Предыстория.

Я давно написал bash-скрипт для парсинга и загрузки с лостфильма торрентов нужных мне сериалов. Работал он как часы, и поэтому я был настолько уверен в своём творении, что даже не удивлялся отсутствию новых серий последние пару месяцев. А оказывается как раз пару месяцев назад на сайте поменялся дизайн, вёрстка и многое другое. Об этих изменениях узнал случайно — пришла рассылка, что, мол, мы изменили дизайн сайта и всё такое. Я из интереса зашёл на сайт посмотреть и обнаружил, что есть новые серии сериалов, которые у меня почему-то не скачались. Сел рыть дальше и понял, что надо переделывать скрипт. Поменялось многое.

Результатом хочу поделиться. Может кому ещё сгодится. После тела скрипта будет разбор полётов, что там и к чему.

#!/bin/bash

# lostfilm.tv smart rss parser and torrent downloader, version 2.2
# 2017.04.03 by jack
# required external programs: curl, wget, lynx

INPUT="/home/jack/.rtorrent.rc"
OUTPUT="/data/video"
LYNX="eval lynx -nonumbers -stdin -dump -listonly -hiddenlinks=ignore|uniq"

LC_ALL=c wget --timeout=5 --tries=1 --timestamping -P /tmp http://www.lostfilm.tv/rss.xml 2>&1 >/dev/null|grep -q "not retrieving"
if [[ ${PIPESTATUS[0]} -ne 0 || ${PIPESTATUS[1]} -eq 0 ]]; then exit; fi

for LINE in `grep -o 'video.*torrent' $INPUT`; do
    STRING=`expr $LINE : '.*\(/.*\.\)'`                          # extract everything between / and .
    SERIAL=${STRING//[!a-z]/}                                    # remove everything except [a-z]
    STRINGS=`egrep "series.*$SERIAL" /tmp/rss.xml`               # search for link with serial in rss
    if [[ -n $STRINGS ]]; then
        for STRING in $STRINGS; do
            STRING=${STRING//}; LINK=${STRING/<\/link>/}         # clean link from  and  tags
            STRING=${LINK//[!0-9]/ }                             # remove from link everything except digits
            set $STRING; SEASON=$1; EPISODE=$2                   # get season and episode
            STRING=`curl -sL $LINK|egrep -o 'PlayEpisode\(.*\)'` # search on the page string with serial id
            STRING=${STRING//[!0-9]/ }                           # remove everything except digits
            set $STRING; SERIALID=$1                             # get serial id
            URL_REDIRECT=`curl -sLb "lf_session=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "http://www.lostfilm.tv/v_search.php?c=${SERIALID}&s=${SEASON}&e=${EPISODE}"|$LYNX`
            URL_TORRENT=`curl -sL $URL_REDIRECT|$LYNX|head -2|tail -1|sed 's/+/%2B/g'`
            wget -q -nc --content-disposition -P $OUTPUT $URL_TORRENT
#            echo -e "$SERIAL $SERIALID $SEASON $EPISODE\n$LINK\n$URL_REDIRECT\n$URL_TORRENT"
        done
    else
        rm -f $OUTPUT/*$SERIAL*.torrent
    fi
done

Итак, для начала список сериалов берётся из конфига rtorrent. Интересующие нас строки там имеют вид:

schedule = watch_directory_6,0,5,"load_start=/data/video/Vikings*.torrent,d.set_directory=/data/video/Vikings"

Если кому интересно, расшифрую: rtorrent каждые 5 секунд проверяет каталог /data/video на предмет появления в нём файлов Vikings*.torrent. Как только появляется такой файл, он добавляется в загрузку, а данные из торрента качаются в каталог /data/video/Vikings.

Конечно, этот конфиг не является обязательным. Список сериалов можно передать в виде списка из внешнего файла или прямо в теле скрипта. Единственное условие — это должно быть одно слово, и такое, чтобы уникально идентифицировать только один сериал. Мне так удобнее, так как я указываю сериалы только в одном файле. Для сравнения в первой версии скрипта у меня было два списка.

Идём дальше. Переменная OUTPUT задаёт каталог, куда будут складываться скачанные торрент-файлы. По описанию выше ясно, зачем я так делаю.

Третьим важным входным параметром является куки lf_session для авторизации на сайте. Без неё торрент-файл не получить. Я брал её из браузера после авторизации. В старой версии сайта название куки было другим и их было два. Теперь стало проще. Кука действует до 2038 года, так что хватит надолго.

На этом из самого необходимого вроде как всё.

Теперь, для тех, кого интересует bash-программирование, хочу немого остановиться на логике. Может мои решения не самые оптимальные, но они могут дать пищу для размышлений и отправную точку для дальнейшего усовершенствования скрипта или использования идей в других решениях.

Итак, всё начинается с загрузки rss-ленты. Скрипт выполняется по крону каждые 15 минут. Чтобы не тиранить почём зря сервер лостфильма, я не качаю файл полностью, а для начала только проверяю его временную метку. За это отвечает параметр timestamping в wget. Если файл не менялся, он не скачивается и скрипт завершает свою работу (exit). Это проверяется наличием в выхлопе wget’а фразы «not retrieving». LC_ALL=c перед вызовом нужно потому, что если wget локализован, ответ будет на соответствующем языке и grep’ать нужно будет другую фразу.

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

lynx используется сугубо для выдирания гиперссылок из html-страницы. Решение топорное, но писать свой парсер html мне очень не хотелось.

Важным моментом является определение переменной URL_TORRENT. Это фактически ссылка на торрент-файл. Лостфильм обычно даёт для каждой серии три варианта: SD, HD и FullHD (480p, 720p и 1080p соответственно). Я качаю сугубо 1080p. Поэтому конструкция из head и tail выбирает из списка только одну ссылку. Можно подкрутить это место так, чтобы качались, например, все три варианта или только 720p. Но это уже кому как захочется.

Также здесь важным является замена плюсов в ссылке на %2B. Как я не экранировал это дело, так и не смог добиться того, чтобы bash не бил ссылки из-за плюсов в них. В итоге такой вот костыль.

Чтобы скрипт не качал торрент повторно, если он уже есть в каталоге назначения, wget’у передается параметр -nc (no-clobber). То есть если в ленте была серия одного сериала (и она уже была скачана) и появилась ещё одна, то скачается торрент-файл только новой серии. Хотя здесь может получиться накладка. Честно говоря, не знаю, как отработает скрипт, если в ленте будет несколько серий сериала. Надо будет проверить это дело. Таки да, была проблема. Добавил ещё один цикл. Теперь из rss-ленты качаются все серии сериала.

Вывод переменных echo нужен только для отладки.

Поскольку список серий идёт в rss как по конвейеру, то когда сериал выпадает из ленты, соответствующие торрент-файлы этого сериала удаляются из каталога назначения (rm -f). У меня настроена 5-кратная раздача торрентов, после чего они останавливюется. Торрент-файл, соответственно, больше не нужен. Таким образом rtorrent не захлямляется тоннами старых раздач. Если кто-то хочет вручную контролировать удаление торрентов, могут переделать на своё усмотрение.

UPD: чуток подправил скрипт, так как из-за обновления то ли lynx, то ли сайта, скачивался торрент на SD-качество, а не FullHD.

MRTG без SNMP: скрипты для сбора данных + конфиг

mrtg_cpu.sh
#!/bin/sh
DATA=`vmstat 1 2 | tail -n1`
echo $DATA | awk '{print $14}'
echo $DATA | awk '{print $13}'





mrtg_disk.sh #!/bin/sh DATA=`df -B1 | grep $1` echo $DATA | awk '{print $3}' echo $DATA | awk '{print $2}'
mrtg_la.sh #!/bin/sh DATA=`cat /proc/loadavg` FIRST=`echo $DATA | cut -d" " -f1` SECOND=`echo $DATA | cut -d" " -f3` echo $FIRST*100 | bc echo $SECOND*100 | bc
mrtg_mem.sh #!/bin/sh DATA=`free -b | grep Mem` echo $DATA | awk '{print $3}' echo $DATA | awk '{print $7}'
mrtg_net.sh #!/bin/sh DATA=`grep $1 /proc/net/dev` echo $DATA | awk '{print $2}' echo $DATA | awk '{print $10}'
mrtg_uptime.sh #!/bin/sh DATA=`cat /proc/uptime | awk '{print $1}'` echo $DATA/\(60*60*24\)|bc echo $DATA/\(60*60*24\)|bc
 

Читать далее »

psplinker — воссоздание структуры паков с PSP-играми для раздачи на bitGAMER и PS2PTT

#!/bin/sh

prepare() {
    DIR=/media
    cd $DIR/ext2

    rm -fr psp
    mkdir psp
    for i in $DIR/fat32/psp/*/*; do
      ln -s $i ./psp/`basename $i`
    done
    echo "«psp» catalog was rebuilt"
}

bG() {
    echo "bG packs"
    for PUCK in .bG/*; do
      PACK=`basename $PUCK`
      rm -fr $PACK
      mkdir $PACK
      for RLZ in $(cat $PUCK); do
        find $DIR/ext2/psp -type l -name "$RLZ" -exec ln -s '{}' "$PACK"/$RLZ \;
      done
      echo $PACK
    done
}
PS2PTT() {
    echo "PS2PTT packs"
    for PUCK in .PS2PTT/*; do
      PACK=`basename "$PUCK"`
      rm -fr "$PACK"
      mkdir "$PACK"
      for RLZ in $(cat "$PUCK"); do
        find $DIR/ext2/psp -type l -name "$RLZ" -exec ln -s '{}' "$PACK"/"$RLZ" \;
      done
      echo $PACK
    done
}

case "$1" in
    rebuild)
	prepare
	;;
    bG)
	bG
	;;
    PS2PTT)
	PS2PTT
	;;
    *)
        echo "Usage: psplinker.sh {rebuild|bG|PS2PTT}" >&2
        exit 3
        ;;
esac

Обновление данных для mdk.jack.kiev.ua

mdk.jack.kiev.ua — это мой проект, где собирается и обрабатывается статистика переводов утилит для Mandriva Linux.

Работает эта статистика на скриптах l10n-stats v3.0 из проекта KDE. Однако для правильной работы этих скриптов структуру переводов Mandriva необходимо подогнать под структуру проекта переводов KDE, что и выполняется моим скриптом. Читать далее »