Пользователь
0,1
рейтинг
12 января 2014 в 16:27

Разработка → Экспорт Избранного на Хабре в PDF

Доброго времени суток, хабровчане!


Думаю многих из вас когда-либо посещала мысль «вот бы сохранить статьи с Хабра».
Такая же мысль посетила и меня два дня назад. Сохранить захотел не просто каждую статью, а только те, что в избранном, да не поштучно, а сразу всё скопом.
Первая мысль — надо написать скрипт, который всё это вытянет. Python я уже подучил, но вот с генерацией PDF на нем сталкиваться ещё не приходилось.

Закручинился я было… Но OpenSource и Хабр спасли меня!
Краткая суть статьи для тех, кому не интересно много читать
В статье описан доработанный скрипт на Python fav2pdf.
Изначальный автор скрипта vrtx, за что ему большое спасибо.
«Usage — лучше тысячи слов!»
usage: fav2pdf.py [-h] [-d OUTPUT_DIR] [--from-date FROM_DATE]
                  [--to-date TO_DATE] [--all-in-one]
                  [--only-hubs [ONLY_HUBS [ONLY_HUBS ...]]] [--no-comments]
                  [--no-symlinks]
                  user

Tool for save favorite posts from habrahabr.ru in pdf's or html's

positional arguments:
  user                  habrahabr.ru username

optional arguments:
  -h, --help            show this help message and exit
  -d OUTPUT_DIR, --output-dir OUTPUT_DIR
                        Directory for output
  --from-date FROM_DATE
                        From date
  --to-date TO_DATE     To date
  --all-in-one          Save all posts in one PDF-file
  --only-hubs [ONLY_HUBS [ONLY_HUBS ...]]
                        Save only posts from hubs. For multiple: "--only-hubs
                        Hub1 Hub2 --"
  --no-comments         Dont save comments from posts
  --no-symlinks         Dont create symlinks to posts
  --create-html         Create html's instead of pdf's
  --create-url-list     Just save user.txt with all links



Из чего собрана картинка
Ещё раз спасибо Хабру. КДПВ собрана из двух, которые были в статьях раз и два.

После первой мысли меня посетила вторая. Наверняка не я один над этим задумывался. И стал методично обыскивать Хабр в поисках чего-нибудь вкусненького. И довольно быстро наткнулся на статью товарища vrtx, где он описывал примерно то, что я и хотел.

Но как всегда есть НО:
его скрипт fav2pdf.py собирает все статьи из избранного и сливает их в один PDF, да ещё и без комментариев, а в них часто намного больше ценной информации, чем бывает в самой статье.
Мне же хотелось иметь по отдельной PDF-ке на статью. Иметь возможность выбора: с коментариями или без, иметь или нет разбивку по хабам...

Сделав форк скрипта fav2pdf.py (за что низкий поклон движению OpenSource), я сначала сделал мелкие доработки, чтобы всё сохранялось по отдельным файлам. Порадовал автора тем, что его наработки кому-то пригодились.

Правда потом мне стало немного стыдно. Я кое-как поправил скрипт и сделал, что было нужно мне. Но не все же хабражители знают python и могут поправить скрипт под свои нужды.

Поэтому я потратил ещё немного времени и допилил скрипт fav2pdf до вполне себе полезной утилиты.
Теперь скрипт дает возможность:
— выбрать директорию, куда можно сохранить pdf (правда для набора pdf'ок будут созданы подпапки posts и hubs)
— задать ограничение по времени (например, сохранить только статьи за 2013 год)
— выбрать сохранять или нет комментарии
— сохранить все в один pdf или разбить на много pdf'ок
— если много pdf'ок, то можно ещё создать рубрикатор из симлинков (подпапки hubs/hub_name с симлинками на posts/post_id.pdf), чтобы можно было легче ориентироваться в коллекции.

Зависимости скрипта
Для корректной работы скрипта мне понадобилось через pip (для pyhton2) поставить следующие пакеты:
— pisa
— reportlab
— html5lib
— requests
— lxml

Параметры командной строки утилиты
usage: fav2pdf.py [-h] [-d OUTPUT_DIR] [--from-date FROM_DATE]
                  [--to-date TO_DATE] [--all-in-one]
                  [--only-hubs [ONLY_HUBS [ONLY_HUBS ...]]] [--no-comments]
                  [--no-symlinks]
                  user

Tool for save favorite posts from habrahabr.ru in pdf's or html's

positional arguments:
  user                  habrahabr.ru username

optional arguments:
  -h, --help            show this help message and exit
  -d OUTPUT_DIR, --output-dir OUTPUT_DIR
                        Directory for output
  --from-date FROM_DATE
                        From date
  --to-date TO_DATE     To date
  --all-in-one          Save all posts in one PDF-file
  --only-hubs [ONLY_HUBS [ONLY_HUBS ...]]
                        Save only posts from hubs. For multiple: "--only-hubs
                        Hub1 Hub2 --"
  --no-comments         Dont save comments from posts
  --no-symlinks         Dont create symlinks to posts
  --create-html         Create html's instead of pdf's
  --create-url-list     Just save user.txt with all links



На сим всё. Если кому понравилось, то пользуйтесь на здоровье!
Если кому-то чего-то не хватает, то пишите фич-реквест в комментах, по мере сил постараюсь реализовать.

PS. Реализован вывод в html. (В спойлерах обновлены описания командной строки.)
PS2. Реализован вывод в txt простого списка url постов. Все ограничения, что вы можете задать из командной строки (даты, хабы), распространяются и на этот список. (В спойлерах обновлены описания командной строки. )
Владимир @icoz
карма
45,0
рейтинг 0,1
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (93)

  • +2
    Я как раз уже несколько дней пытаюсь придумать, как бы реализовать удобный экспорт самых толковых howto на читалку, и тут такое. Спасибо, сейчас протестирую!
    • +1
      Хм. Думаю, без особых проблем можно сделать выгрузку в html. А html уже легко конвертится во что угодно…
      • +1
        Тем более, что скрипт изначально html и генерирует :)
        • +2
          А то! ;)
      • +2
        Реализовано.
  • +3
    Спасибо за доработки, удобная штука получилась!
  • 0
    Прошу прощения за бестолковый вопрос, но работает ли эта штука под Windows?
    • 0
      Не знаю. Не проверял.
      • +1
        Если все нужные библиотечки будут стоять, то должно работать.
        Единственное, что меня смущает, так это symlink'и в Windows. Так что с параметром --no-symlinks должно работать.
        • 0
          Еще в Висте появилась поддержка симлинков. Так что на современных версиях ОС даже без этого параметра должно заработать.
    • +19


      :)
      • 0
        Занятно. Ссылку бы тоже сразу лучше вставили. :)
    • +1
      Работает.

      Качаем скрипт, ставим необходимые библиотеки. Для версии python 2.7 помимо тех, которые указаны в статье, потребовалось поставить еще библиотеки six, lxml.

  • 0
    Кстати, раз уж утилитка консольная и на питоне — попробуйте вот такую вот либу:
    docopt.org/
    github.com/docopt/docopt
    • +1
      А чем вам argparse не нравится?
      Я же не сам аргументы разбираю, а argparse использую. В чем преимущество docopt?
      • +1
        Почитал доку. Неее… Там надо самому весь usage расписать, а docopt на базе этого сам разберет параметры.
        Я программист — много писать мне лень. Я лучше 10 строк для argparse напишу… Плюс к тому, проще задать ограничения на вводимые значения.
        • 0
          Блин, то ли я плохо объясняю, то ли вы не ту доку читаете…
          Usage всегда будет короче, чем код argpasre, который его стоит.
          Вот в этом месте видео автор либы сравнивает код консольного чекера pep8 с argparse и с docopt:
          www.youtube.com/watch?v=pXhcPJK5cMc#t=418

          Если и после этого не убедил, то видимо у нас разные вкусы.
          • +1
            Посмотрел пунктиром.
            Да, библиотечка стоящая. Но каждой библиотеке свои задачи.
            В примере разбирали очень крутую конфигурацию опций. Да, в этом случае docopt полезнее.

            Но не забывайте, что для изучения чего-то нового необходимо время.
            Когда случай сложный, то быстрее будет изучить docopt и использовать его, а иначе зачем заморачиваться?

            А вот в чем вы меня действительно не убедили, так это в том, зачем переделывать утилиту на использование новой библиотеки?

            PS. видюшка интересная, закинул ее себе в посмотреть попозже.
            • +1
              Ну я же вас не принуждаю код писать =)
              Это скорее было в академических целях, если вам интересно.
  • +1
    Я однажды делал экспорт избранного в FB2. Правда, потом на сайте что-то сделали с разметкой, и он перестал работать. Но желающие могут форкнуть и допилить.
    • +1
      Гляну. Может чего и оттуда полезного перетяну. :)
  • +1
    Работает, спасибо!
    Правда несколько модулей пришлось поставить.
    • +2
      Не понял, что я такого сказал? Если про модули, то кроме тех, что упомянуты.
      • 0
        Мне пришлось кроме указанных установить лишь lxml. Кстати, надо бы в readme добавить список зависимостей.
        • 0
          2.7?
          lxml точно ставил, и ещё что-то… забыл уже :)
          • 0
            cat .bash_history поможет
            • +1
              Разумеется, когда дома :)
              Глянул — у меня вроде всё. То есть lxml + то, что у вас в статье уже перечислено.
              • 0
                Да, у меня так же. Тоже для 2.7
        • +1
          Список неточен только из-за того, что у каждого на системе уже что-то может стоять.
          Да и если составлять такой список, то надо отследить все зависимости всех используемых библиотек.
          Скучно и бессмысленно.
          Ну и с другой стороны, никто не говорил, что у утилиты отсутствует порог вхождения.
          • 0
            Ну и с другой стороны, никто не говорил, что у утилиты отсутствует порог вхождения.

            Разумеется, он же на каждый чих пишет, что ему не нравится.
          • 0
            Как минимум, я бы добавил lxml, ибо уже минимум у двоих это потребовалось. ;)
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Скорее всего chrome будет сохранять статью так, как вы ее видите на экране, с менюшками и прочей рекламой.
      Скрипт же выдирает исключительно смысловую нагрузку.
      • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Для смысловой нагрузки можно использовать мобильную версию:

        m.habrahabr.ru/post/208802
        • 0
          Именно так и реализовано в скрипте.
  • 0
    Несколько замечаний:
    1. У меня в избранном 17 страниц, скрипт пытается обработать 25.
    2. Не все посты корректно сохраняются. У меня это 136056, 147996,163097,165527,172009,187210,206604. Создается pdf с нулевым размером
  • 0
    По первому пункту:
    На каждой странице по 10 постов, у вас 246 постов, логично, что скрипт пытается дернуть 25 страниц.
    Внимание, вопрос: а как так 17 страниц получается?

    По второму:
    Запустите еще раз. Бывает что какие-то таймауты выходят и скрипт не получает данных.
    Вот если проблема повторяется раз за разом именно на этих постах, то тогда есть повод подумать…
    • +1
      Проверил, по второму пункту у меня те же посты нулевыми получились.
      Буду думать что не так…
    • 0
      На счет постов, видно у хабра с этим проблема, вы можете сами посмотреть у меня всего 17 страниц в избранном. Скрипт сохраняет 170 файлов.
      По поводу нулевых файлов, я запускал несколько раз. Ошибки там разные, вам лучше самому посмотреть, я python-е ничего не понимаю.
      • 0
        Про нулевые файлы могу сказать пока только одно:
        в виде HTML они загружаются корректно.
        Может быть какой-нибудь косяк внутри библиотеки рендеринга pdf? Она ведь сама, например, картинки вытаскивает.
  • 0
    НАсколько сложно будет сделать .mobi => kindle?
    • 0
      У амазона есть плагин для киндла. Отлично все делает. Другое дело, что его надо использовать самому на каждой странице. chrome.google.com/webstore/detail/cgdjpilhipecahhcilnafpblkieebhea
      • 0
        спасибо, уже нашел отличную вещь от вендора
        Send to Kindle for Mac
        Есть такой же для PC
  • 0
    Можно ли как-то переделать скрипт для Python 3.3? Может кто подскажет?
    • +2
      Думал над этим.
      Даже попробовал. Но у меня всё валится на необходимости порта на python3 пакета reportlab.
      Нашел на stackoverflow, говорят есть порт.
      Но это экспериментальное всё и не мейнстрим, то есть ее нет даже в PyPI, только для python2.

      К чему это я…
      Ах да! Даже если с такими костылями и сделать порт, то поставить его смогут немногие.
      Либо переписывать скрипт с использованием других библиотек.
      • 0
        Ясно, спасибо.
  • 0
    А можно сделать опцию на выгрузку одной конкретной статьи? Или списка статей из файла, а не из избранного?
    • 0
      Ну вот как раз одну статью удобнее экспортировать средствами браузера, как выше сказали.
      • 0
        Да, согласен. Тогда вопрос снимается )
    • +1
      Да, можно.
      Можно добавить новый параметр --get-one.
      Можно и из списка…
      Актуально ещё?
      • 0
        Думаю, список актуален — можно, например, взять какую-нибудь сборную статью с выборкой лучшего по теме, скопировать оттуда все ссылки и сохранить в файл, а из него уже загрузить все статьи для чтения.
  • +1
    Не так давно тоже писал свой велосипед, но для Kindle. Скрипт умеет:
    1. Вытягивать лучшие статейки по хабам. (используя бд из моего предыдущего поста)
    2. Парсить избранное
    3. Просто стянуть рандомную статью.

    Для корректной работы, нужно скачать kindlen и указать у нему путь в habr_to_kindle.py.

    В итоге

    комментарии

    • +1
      Почитал. Хороший код. Понятный.
      Прям приятно почитать перед сном… :)
  • 0
    Спасибо за скрипт!

    Все предыдущие варианты что я пробовал быстро загибались под натиском моего избранного, а Ваш уже 9/99 страниц обработал. Пока держится молодцом! =)
    • 0
      Увы, на 137 статье завис скрипт. habrahabr.ru/post/162747/ — на этом топике.
      • 0
        После 10 минут тупняка опять пошло — уже 42 страницу парсит.
        • +1
          О_о
          Вы меня поражаете.
          Надеюсь хоть по разным файлам?
          И тогда уж в формате html…
          • +1
            Из параметров я указал только свой ник — так что по разным файлам и в pdf =)

            html на айпаде не очень удобно читать, так что закину pdf-ки в iBooks. Жаль только, что метаданные не заполняются у pdf:


            Реквестирую вставку в метаданные ника автора, заголовка статьи и тегов (в поле «Тема»).
          • 0
            stackoverflow.com/questions/2574676/change-metadata-of-pdf-file-with-pypdf
            Вот, можно так сделать добавление метаданных. Иначе при импорте всех 900 файлов в ibooks будут проблемы — как выбрать нужную статью.
            • 0
              Идея хорошая. Возьму на заметку. Подумаю.
              Возможно есть решение проще.
  • +1
    Фух, распарсил 900+ статей. Всё таки справился, спасибо автору! Первый парсер, который сделал свою работу.
    И всего лишь один нулевой файл на выходе.
    • +1
      Вы меня поражаете…
      • 0
        И не удивительно, что все предыдущие парсеры не справлялись — памяти им не хватало. =)
  • 0
    Добавил эту статью в избранное, и забыл про неё. Всё правильно сделал?
    • 0
      Да, если вы не забыли сохранить скрипт.
  • +2
    Сделал версию(анлог) на QML/C++ с GUI, думаю кому-нибудь понадобится. Пока умеет только: сам экспорт в отдельные файлы, экспорт из отдельных тегов и убирать ссылка из поста. Скоро добавлю остальной функционал, так что не судите строго. На Github
    • 0
      Честно говоря, для GUI я бы добавил побольше.
      Да и вообще сделал бы в виде Мастера.
      Шаг 1. ввести ник, нажать далее.
      Шаг 2. собрать инфу с его избранного и вывести в древовидной(хабы и посты) форме или списком все статьи. Ввести фильтры: по времени, по хабу, по автору.
      Шаг 3. поотмечать галочками что сохранить, а что нет. Нужны комментарии или нет.
      Шаг 4. вытянуть и сохранить. Формат на выбор: html, pdf, может конвертация в какой-нибудь fb2.

      Может и сам когда-нибудь этим займусь, когда время будет. Или вы попробуйте, если время есть.
      • 0
        Спасибо! А вы не могли-бы скомпилировать и под Windows для тех, кому это сделать трудновато по причине незнания, даже в теории, как это делать? :) Буду крайне благодарен!
        • 0
          Дык такое я и не начинал еще. Идей проектов много, а времени крайне мало. :(
          • 0
            Упс, кажется промахнулся в ответе, мой комментарий был адресован уважаемому RAZVOR, т.к. по его ссылке на Github есть такие строки: «Now only for OSX. You can compile it for Linux or Windows from source.». Прошу прощения что ввел в заблуждение )
  • 0
    Можно пример даты для скрипта?
    • 0
      ./fav2pdf.py --from-date "3 января 2014" user
  • 0
    С reportlab версии 3.0 не работает, выдает ошибку. Пришлось специально ставить 2.7
  • 0
    Насколько я понял после обновления дизайна — не работает?
    У меня скрипт теперь проходит по всем статьям и говорит что они — «is locked».
    • 0
      Аналогично :( Большая просьба к автору, поправьте, если есть такая возможность.
      • 0
        Я смотрел, не так все просто.
        У меня сейчас в разработке новый парсер страниц. Своеобразный фреймворк для парсинга хабра. Пока сырой и не все еще реализовано. Поэтому пока класть в опенсурс стыдно.
        Если есть желающие попилить — прошу в личку.
      • 0
        Отмечу, что я в описанной программе взял чужой парсер и сделал к нему консольную обертку.
        А сейчас пишу свой парсер.
        • 0
          В таком случае, будем ждать с нетерпением :)
          • +1
            Парсер написан. Баги есть, но по ходу дела вылавливаются.
            Но я столкнулся с другой проблемой — чем сохранять в третьем питоне в pdf?
            Гугл сходу не помог… :(
            Могу просто html сохранять — пойдет?
            • 0
              Это просто отличные новости! Жаль, у меня не хватает кармы для голосования :(

              Меня бы устроило и в HTML. Но вот что выдал мне гугл, stackoverflow.com/questions/12021216/is-there-any-python-3-module-to-create-pdf-files вдруг вам это поможет, хотя я слегка далек от программирования вообще, и от Питона в частности (
              • 0
                Это я находил и читал. Некоторые решения там не кроссплатформенные. Некоторые уже померли…
                Посмотрим внимательнее, конечно.
            • 0
              html можно сохранить в pdf используя pyQt:
              import sys
              from PyQt4.QtCore import *
              from PyQt4.QtGui import *
              from PyQt4.QtWebKit import *
              app = QApplication(sys.argv)
              web = QWebView()
              web.load(QUrl("http://habrahabr.ru/post/208802"))
              #web.show() можно показать страницу
              printer = QPrinter()
              printer.setPageSize(QPrinter.A4)
              printer.setOutputFormat(QPrinter.PdfFormat)
              printer.setOutputFileName("file.pdf")
              def convertIt():
                  web.print_(printer)
                  print("Pdf generated")
                  QApplication.exit()
              QObject.connect(web, SIGNAL("loadFinished(bool)"), convertIt)
              sys.exit(app.exec_())
              
              

              Отсюда. Не знаю, поможет вам или нет.
              • 0
                О! А это мысль! Что-то я про кутю забыл совсем…
                Спасибо. Может и графический интерфейс нарисую тогда уж.
                • 0
                  Нашел такую штуку!
                  Думаю, будем пользовать её. Простая и работает с python3.
                  Будет время — напишу небольшую статейку про неё.
            • 0
              Я правильно понимаю, что fav2pdf.py — это другой парсер? Пыталась запустить, но проблема такая же как у Stvad — все «is locked»
              • +3
                Да. Я взял чужой парсер и сделал к нему обертку. Ну и доработал маленько кое-где.

                Сейчас я написал всё свое с нуля и на третьем питоне. Осталось немного.
                • +1
                  Ждем-ждем :)
                • 0
                  Есть какие-нибудь новости по новому парсеру?
                  • 0
                    Почти.
                    Парсер есть и работает. Но есть проблема. Не могу толком сохранить в pdf, а для сохранения в html требуется перерабатывать всё содержимое страницы.
                    Могу выложить сам парсер, кто сможет доработать или хотя бы подсказать что делать — буду рад.
  • 0
    Приветствую всех.
    Я опубликовал исходники парсера для Хабра.
    github.com/icoz/habrapasre
    Парсер работает вполне сносно.
    Проблемы:
    1) сохранение в pdf (то формат страницы такой, что часть текста обрезана, то картинок нет)
    2) сохранение в html требует глубокого анализа текста, чтобы подменять ссылки на картинки, например…

    Буду рад любой помощи.
  • 0
    Проведен ряд доработок. Скрипт работоспособен. Ограничена функциональность в части работы с комментариями.

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