Первые шаги в программировании на Python

Пару месяцев назад взялся я за изучение Python. Прочитав про используемые структуры, работу со строками, генераторы, основы ООП, размышлял какую полезную программу написать, что бы это все применить на реальной задаче.
По счастливому стечению обстоятельств ко мне обратились знакомые с просьбой скачать мультфильм «Чудеса на виражах».

Ближе к делу


Зайдя на один из популярных трекеров в UA-IX нашел данный мультфильм, только вот каждая серия была выложена отдельно, а нажимать на кнопку «Загрузить» 65 раз не хотелось. В этот момент я и вспомнил о Python.
Сразу начал искать информацию о том, как получить файлы с сайта. Ответ быстро получил благодаря Google и небезизвестному сайту stackoverflow. Оказалось, что «вытянуть» файлы можно импортированием библиотеки и добавлением пары строк. Опробовав на файлах небольшой размерности, как это все работает, перешел к следующему этапу. Нужно было собрать все ссылки для скачивание и соответствующие им названия файлов.
В пределах одного тега они нигде не указывались, поэтому ссылки и названия файлов собирал отдельно.
Для сбора ссылок использовалась библиотека lxml, которая уже рассматривалась на данном сайте. После скачивания и установки данной библиотеки, перешел к написанию самой программы. Код программы представлен ниже:

#! /usr/bin/env python

import urllib
import lxml.html
 
load = 'load'
page = urllib.urlopen('http://www.***.ua/view/12345678')
doc = lxml.html.document_fromstring(page.read())
for link in doc.cssselect('p span.r_button_small a'):
    if link.text == None:
        continue
    if load not in link.get('href'):
        continue
    print 'http://***.ua'+link.get('href')

Все собранные ссылки сохранялись в файл, для дальнейшей работы с ними. Конструкции if использовались для фильтрации всех данных. Тем самым я получал только ссылки, которые применялись для загрузки файла на компьютер.
Названия файлов имели не совсем удобный вид. Поэтому, когда программа получала название файла, она сразу изменяла его на более удобный. Таким образом все файлы получали название вида: «Чудеса на виражах. Серия XX», вместо ХХ — номер серии.
Код программы:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import urllib
import lxml.html

file_name = u'Чудеса на виражах. Серия '
episode = 0
page = urllib.urlopen('http://www.***.ua/view/12345678')
doc = lxml.html.document_fromstring(page.read())
for name in doc.cssselect('tr td a'):
    if name.text == None:
        continue
    if not name.text.endswith('.avi'):
        continue
    name.text = file_name + str(episode) + name.text[-4:]
    print name.text.encode('utf8')
    episode += 1

Так, как версия используемого интерпретатора Python 2.6, то для корректной работы с кирилицей пришлось использовать метод encode. Собранные данные также сохранялись в файл.
После работы обеих программ, на жестком диске имелось два текстовых файла. В одном хранились ссылки для скачивания файлов, а в другом названия серий.
Для связывания ссылки и названия файла я воспользовался словарем. Ключем выступала ссылка, а в значении ключа хранилось название файла. После чего необходимо было только брать ключ, подставлять его в вызывающую функцию и указать место, имя файла для сохранения.
Код выполняющий эти действия:

#! usr/bin/env python
# -*- coding: utf-8 -*-

import urllib

links = open('link','r')
names = open('file_name', 'r')
download = {}
path = '/media/6A9F550C59BC1824/TaleSpin/'
url = 'http://www.***.ua/load/12345678'
loadf = []

download = dict(zip(links, names))
for link in download.iterkeys():
    name = download[link].rstrip()
    if name not in loadf:
        urllib.urlretrieve(link,path+name)
        loadf.append(name)
    else:
        continue

Также используется список, в который заносяться названия серий, которые уже скачались. Используется это для того, что бы в случае прерывания скачивания, не качались серии, которые уже есть на жестком диске.

Заключение

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

Использованные материалы

  1. «LXML» или как парсить HTML c лёгкостью
  2. Официальная документация к lxml
  3. Документация к библиотеки urllib
  4. Python Tips, Tricks, and Hacks (часть 2)

Благодарю за внимание.
Адрес сайта скрыт, чтобы не сочли за рекламу.
Метки:
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 35
  • +18
    на написание всего этого кода ушло больше времени, по сравнению с тем, если бы я вручную нажимал на кнопку «Загрузить». Но работающая программа принесла гораздо больше удовольствия.
    Как говорят, Welcome To The Club!

    Здорово, что начали изучение с Питона. Когда откроете для себя его отличия от других скриптовых языков (того же php), например генераторы, оцените этот прекрасный язык по достоинству.
    • –1
      Чую, минусуют приверженцы PHP :)
      • +13
        Попрошу не разводить холиваров на эту тему.
      • +3
        Кстати, я серьезно теперь задумался о том что бы изучит в кое то веки Питон)
      • +5
        Я пару месяцев назад учил python выполняя задания с www.pythonchallenge.com/ — вообще, язык очень понравился!
        • +1
          вот скажите: выполнение заданий там Вам сильно помогло? Что, грубо говоря, прокачали? Вообще есть ли серьёзный смысл этим позанматься? Просто сам хочу попробовать… но времени не так много свободного, хочется мнение уже участвовавшего там… Спасибо
          • +1
            Это как минимум весело. А качает смекалку и умение максимально быстро «на коленке» решать одноразовые нетривиальные задачи.
            • 0
              понял, думаю стоит заняться 4 fun :) главное время найти
              • 0
                Ага… У меня была цель просто познакомиться с некоторыми основными возможностями языка. В принципе, если какая-то задача вызывает сильные сложности, в и-нете можно решения найти.
              • 0
                Простите, а в вашей трудовой деятельности так мало одноразовых задач, которые требуют решений по методу «на коленке»?
                Может я чего-то не понимаю, но мне кажется, что куда лучше оглянуться и направить свой пыл на решение тех задач, которые вроде как одноразовые и и нетривиальные, однако могут помочь в работе других людей: Жены, коллег, родителей, родственников, человека на форуме.
          • +1
            Эхх… «Чудеса на виражах» моё детство ))
            • +3
              Сегодня как раз по поводу питона в рассылке CodeProject интересную ссылку прислали по поводу некоторых нюансов, рекомендую. Ссылка
            • +5
              else:
                  continue
              
              Зачем?

                  if link.text == None:
                      continue
                  if load not in link.get('href'):
                      continue
              
              Можно перефразировать в
                  if link.text and 'load' not in link.get('href'):
                      continue
              


              Статья о том как питон мило пригождается для повседневных нужд.
              • 0
                Ошибся, правильно будет
                not link.text or
                • +3
                  В общем случае

                  link.text == None

                  это не то же самое что и

                  not link.text

                  Второй вариант так же сработает и на пустую строку.
                • 0
                  download = dict(zip(links, names))
                  for link in download.iterkeys():
                  name = download[link].rstrip()
                  if name not in loadf:
                  urllib.urlretrieve(link,path+name)
                  loadf.append(name)
                  else:
                  continue

                  upload = [(k,v) for k,v in zip(links, names) if v.rstrip() not in loadf]

                  for item in upload:
                  try:
                  urllib.urlretrieve(item[0],path+item[1])
                  expect urllib.Эксепшоны:
                  pass(?)
                  else:
                  oadf.append(itemp[0])

                  Если уж делать, то как-то так получается. Да и много чего еще сделано не правильно и нужно читать документацию по Python.
                  • 0
                    upload = [(k,v) for k,v in zip(links, names) if v.rstrip() not in loadf]

                    Не подскажете как такой финт в списках называется? что читать чтобы делать такие же конструкции?
                    • +1
                      Списочные сборки?

                      Можно с этого начать: ru.wikibooks.org/wiki/%D0%A3%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D0%BA_Python_2.6

                      А далее и посерьёзнее литературу можно (преимущественно, на английском).
                      • +3
                        • +2
                          List Comprehensions

                          На самом деле это просто укороченная запись
                          upload = []
                          for k, v in zip(links, names):
                              if v.rstrip() not in loadf:
                                  upload.append((k,v))

                          • 0
                            дело в том что я часто натыкался как у нормальных python кодеров были такие конструкции. Изза того что я их не понимаю, не получалось понять точно что же скрипт делает.
                          • 0
                            все есть в PEP'ах. Там оооочень много всего.
                      • +3
                        Правильной дорогой идете: стараетесь писать меньше кода, используете готовые известные решения и стандартную библиотеку вместо изобретения велосипедов, так держать.
                        • 0
                          Ох, как я мечтаю перейти с AutoIT на python.
                          • +4
                            не холивара ради — очевидно, вам необходимо поменять ОС ))
                            • 0
                              Хороший совет, нужно будет любой свой autoit-скрипт попробовать переделать для linux на python.

                              Так сказать вариант обучения плаванию, когда бросают в самое глубокое место без спас жилета.
                            • 0
                              Попробуйте Sikuli.
                            • –2
                              Эх… Вот зашли бы вы на КинозалТВ — и статьи бы не было :)
                              • +2
                                У меня на мир скорость значительно меньше, чем по Украине. Поэтому смотрел в UA-IX.
                                • 0
                                  Это просто шутка была. ;)
                              • –1
                                Сурово и по делу — ни одного класса, скрипт как он есть :) Собственно питоновского в статье — только синтаксис, т.е. все прелести питона и понимание его «пути» у автора ещё далеко впереди, если он продолжит им заниматься конечно, а пока — заколачиваем гвозди микроскопом…
                                • 0
                                  К слову, на каждой страничке, непосредственно над списком файлов есть ссылка «файл-лист», которая указывает на файл *.urls. Файл содержит список ссылок на все файлы, которые представлены на данной странице ресура.
                                  Этот файл замечательно открывается в Download Master, о котором, наверное, рассказывать нет смысла :)

                                  В целом, в учебных целях Ваш пример хорош, но с точки зрения использования — связка *.urls + DM и стабильнее, и удобнее, и возможно даже быстрее.

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.