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


                :)
              • +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
                                    Можно ли как-то переделать скрипт для Python 3.3? Может кто подскажет?
                                    • +2
                                      Думал над этим.
                                      Даже попробовал. Но у меня всё валится на необходимости порта на python3 пакета reportlab.
                                      Нашел на stackoverflow, говорят есть порт.
                                      Но это экспериментальное всё и не мейнстрим, то есть ее нет даже в PyPI, только для python2.

                                      К чему это я…
                                      Ах да! Даже если с такими костылями и сделать порт, то поставить его смогут немногие.
                                      Либо переписывать скрипт с использованием других библиотек.
                                  • 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
                                                                    Проведен ряд доработок. Скрипт работоспособен. Ограничена функциональность в части работы с комментариями.

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