Экспорт избранного Хабра в FB2 — скоростная PHP-версия

    В своё время я уже видел такой конвертер здесь же на Хабре, написанный на питоне, но он на моей машинке сжирал много-много-много ресурсов и ни разу не смог моё избранное (а это 400+ постов) до конца сохранить, падая то на некорректном файле, то на «кривой» статье. Пришлось переписать, результаты трудов под катом.

    • Уже было (в pdf, на питоне), причем дважды (в fb2, на питоне)!
      • pdf на телефоне требует больше ресурсов для просмотра.
      • питоновский скрипт сохранения в fb2 съедал у меня около 3 Гб оперативной памяти (а на старом ноутбуке ровно 3 и было), и ни разу не смог успешно завершить процесс успешно.

    • Комментарии к постам сохраняются?
      В библиотеку парсера соответствующую функцию я добавил, но сохранение в файл не сделал. Если будут идеи, как красиво отобразить комментарии ограниченными возможностями fb2-разметки — поделитесь идеей, с удовольствием доделаю следующим патчем.
    • Валидация, работоспособность файла, известные проблемы?
      В CoolReader под android открывается 100%, windows-версия FBReader может падать на некоторых статьях.
      Не всё корректно отображается — тэги таблицы удаляются, код не оборачивается в соответствующий тэг (будет в следующем патче).
      Все некорретные статьи или картинки молча отбрасываются, никакого логгирования ошибок.
    • Как запустить?
      Качаем, распаковываем в любой виртуальный хост, правим config.php под себя и открываем в браузере.
      Все нужные библиотеки или в комплекте, или докачиваются сабмодулями.
    • Где взять то?
      На github'е, вестимо.
    • Настройки?
      В файле config.php, всё подписано русским utf'ом. Можно, например, отключить сохранение картинок или сменить папки для сохранения данных.
    • Что интересного в реализации?
      • парсинг ведётся силами библиотеки phpquery
      • все действия разнесены в отдельные файлы (скачивание списка, скачивание статьи, сохранение картинки)
      • за один шаг выполняется одно атомарное действие (скачивание одной статьи, скачивание одного вложенного файла и т.п.). Таким образом памяти каждый скрипт ест мало, а работает относительно быстро.

    • Я нашел ошибку/баг/кривой код/у меня есть идея!
      Делитесь здесь, в личку, на github'е — в свободное время могу заняться.


    Пример файла (вторая версия). ~150 статей, размер 22мб., в сжатом виде 14 мб. Картинки в комплекте, комментарии — нет.

    Update. Пример fb2-файла. 400+ статей, общий размер ~53мб., картинки сжаты до 400 пикселей, размер архив 33.8 мб. Выше — свежая версия файла.
    Update 2. Для работы скрипта на сервере должны быть включены short tags. Не актуально для новой версии скрипта.
    Update 3. Скриншот скрипта в процессе выполнения:

    Update 4 (27.02.2013). Обновил скрипт. Теперь не выкидываются тэги и (в последней не работает сложное форматирование, но тем не менее). Добавлено логгирование (включается в config.php). Короткие тэги заменены на длинные.
    Update 5 (27.02.2013). Обновил скрипт. Теперь он поддерживает сохранение комментариев, подробности - чуть ниже, тут.
    Update 6 (28.02.2013). Обновление скрипта. Теперь файл более корректен (с токи зрения XML). Правда, FBreader на всех платформах его не принимает, так же как и одна из аппаратных книг, но большинство читалок файл всё-таки одолеет. Заменен демонстрационный файл.
    Update 7 (28.02.2013). Обновил скрипт. По совету в комментариях - добавил возможность включить скачивание картинок параллельно, в несколько потоков.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

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

    Комментарии 59

      +1
      А не могли бы вы добавить пример экспортированной статьи?
        0
        Могу целиком выложить мой fb2 (~50мб. в несжатом виде).
          0
          Выложил в обновлении к статье.
            0
            Спасибо, сегодня гляну на читалке.
            Из предложений: добавьте настройку чтобы можно было сохранять отдельную статью в отдельный файл.
              0
              Добавлю, как будет время — благо доделывать немного)
              +1
              Скачал ваш файл, но открыть не могу — пишет о повреждении. Использую STDUViewer, другие файлы fb2 открывает мгновенно.
                0
                Да, файл конвертируется не валидный, увы. Если отключить опцию «превращать тэг br в P», то файл станет более валидным, но читаемость упадёт в разы. Телефонные читалки мягче относятся к стандарту.

                Если встретите какой-нибудь приличный метод гарантированно превратить HTML текст в FB2 (ну кроме как вычищать все тэги совсем )) ) — с удовольствием его реализую. Мне покуда не удалось :(
                  +1
                  Простите, а тогда чем в принципе просматривать генерируемый вашим конвертером fb2?
                    0
                    Просмотр на компьютере я не предполагал (хотя, опять же, см. пункт про второй режим генерации), а на телефоне под андроидом — CoolReader и [тут забытое мной название читалки, надо будет уточнить у девушки, чем она открывала] просматривает идеально.
                      +1
                      Да, попробовал на ZXReader на Symbian — тоже читает, спасибо.
                    +1
                    Вместо <br> (хотя это xml, правильнее <br />) попробуйте использовать <empty-line/>.
                      0
                      Ёлки-палки, действительно, как я про этот тег забыл! Как доберусь до домашнего компьютера, попробую и сравню.
                        0
                        Вспомнил, в чем проблема. Не сработает.
                        Дело в том, что <empty-line/> нельзя применять внутри — формат станет невалидным. fb2 — формат с жесткой структурой.

                        Т.е, есть у нас например
                        <p>
                            <b>
                                    [текст]
                                    <br>
                                    [текст]
                            </b>
                        </p>
                        

                        И как тут красиво заменить BR? Нужно
                        1. либо закрыть B, закрыть P, поставить emtpyline, открыть P, открыть B
                        2. либо заменить BR на </P><P> — некорректно, но некоторая часть читалок переживет
                        3. совсем удалить BR и не вспоминать о нем.

                        Если выбирать первый вариант — нужная очень хитрая регулярка как минимум, либо столь же хитрый код. У меня пока нет столько свободного времени, готового решения не знаю, альтернативные в голову не пришли :(

                        У меня в конвертере можно переключаться между вторым и третьим вариантом.
                          0
                          Вот поэтому надо было использовать не php, а языки с богатыми библиотеками, которые использовать проще, чем регулярки :-)
                          ps интересная тема… На выходных гляну и постараюсь на java что-нибудь наваять… есть подозрение что и быстрее и не хуже будет работать :-)
                            0
                            В php тоже есть и библиотеки, и биндинги к библиотекам на других языках… но я пока не могу сформулировать задачу, которую нужно решить. Если точнее, формулировка то простая — «как очистить HTML, что бы он стал корректным XML (как выкинуть или корректно открыть-закрыть недостающие теги)». Уверен, что решение есть, но пока что не у меня.
                              0
                              Сильно подозреваю, что существуют различные dom-парсеры html, а из этого самого dom`а можно выдернуть всё что захочется ;-)
                                +1
                                При парсинге используется обертка над системной библиотекой, которая именно строит dom дерево. Но проблемы «br внутри p» она не решает. Ведь с точки зрения xml конструкция корректна, но fb2 её не переваривает.
                            0
                            Написал тест и проверил в доступных мне редакторах и читалках, <empty-line/> вполне валидно вписывается в сам файл, но вот не все смогли переварить (точнее FBreader на всех платформах, и одна аппаратная книга).

                            Очень жаль… как будет свободное время, посмотрю ваш код, может что придумаю (тема заинтересовала).

                            Но четвертый вариант возможен: заменить BR на <empty-line/> — корректно, но некоторая часть читалок не переживет.
                              0
                              Подтверждаю этот опыт. Так что сегодня вечером постараюсь найти время и поменять вставку везде </p><p> на кошерный <empty-line/>.
                +1
                Спасибо, попробуем!

                Мысль конвертации в epub поддерживаю.
                  +3
                  Да, благо переписывать придется немного. Осталось разобраться с форматом и/или найти готовый класс для генерации epub (что-то видел такое на гитхабе).

                  P.S.так и хочется выдать нечто вроде «если этот пост наберет XXX плюсов, то в течении двух недель реализую, но как-то боязно )))»
                  +3
                  Одного понять не могу, почему сам хабр не добавит корректный и столь желанный функционал.
                    0
                    а много ли пользователей этого функционала будет?
                      +1
                      Есть предложение, что непосредственно экспорт может и не так уж много кому нужен, но наличие какого-либо «habra-API» было бы очень кстати. Парсить было бы проще, например :)

                      Сейчас же API никакого нет, кроме, разве что, просмотра уровня кармы/рейтинга отдельного пользователя (может что упустил?).
                        +1
                        Я смотрю, народ часто просит API для своих приложений типа хабра-читалок, но что-то без успеха.
                          0
                          Не трудно реализовать сервис-посредник с API, только вот

                          1) легальность (я в наших законах уже совсем не ориентируюсь)
                          2) мощность серверов может понадобиться нешуточная
                          3) нулевая монетизация (по моему скромному мнению)
                          4) если затея будет пользоваться успехом — чую, авторы хабра через некоторое время уже самостоятельно реализуют идею.

                          Хотя можно и попробовать на досуге.
                    0
                    Я тут пытаюсь на локальном апаче прогнать скрипт, но ничего не выходит: браузер отображает пустую страницу. Файлик .fb2 так же не появляется.

                    Логов не предусмотрено? PHP 5.3.15.
                      +1
                      Логов не предусмотрено, и видимо вечером я буду их прикручивать… Единственное, что приходит в голову
                      1) скачали сабмодули?
                      2) error.log сервера что нибудь говорит?
                        0
                        1) Скачал
                        2) pastebin.com/AcxCb4ij — есть траблы в скрипте
                          0
                          Любопытно.
                          «HP Notice: Undefined variable: step in /Users/silvansky/Projects/habr_to_fb2/index.php on line 3»

                          А объект «step» создается в файле config.php. Хмм… Буду думать, доберусь до дома, отвечу подробнее.
                            0
                            Проблема была в отключенных шорт-тегах в php.ini. Теперь вроде бы работает =)
                              0
                              Блин, второй раз уже на это натыкаюсь — привык, что у себя везде по-умолчанию их включаю. Уточню в инструкции и учту на будущее…
                                0
                                шорты как бы теперь по стандарту являются рекомендуемыми, однако до сих пор пишу <?php echo $var;?> вместо <?=$var?>. Сохраняется версиянезависимость!
                                  0
                                  С обратной совместимостью согласен, так что убрал требование коротких тэгов — заменил на длинные :)
                      0
                      А зачем парсить страницы полного Хабра, есть же мобильная версия, достаточно вместо habrahabr.ru обращаться к m.habrahabr.ru, там и мусора меньше в исходнике, да и комменты в упрощенном виде.
                        0
                        Согласен, мобильная версия могла бы обрабатываться быстрее. Будет время — потестирую и сравню результаты.
                        +2
                        «Качаем, распаковываем в любой виртуальный хост, правим config.php под себя и открываем в браузере.»
                        Да вы что, шутите что ли? Откройте для себя php-cli — как раз для таких случаев.
                          0
                          Мне хотелось так же протестировать один из методов создания пошагово выполняющегося скрипта с интерфейсом в браузере. :) Но cli-версию тоже сделаю, чуть позже — открывать для себя ничего не надо, ни раз этим пользовался.
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Добавил.
                            +1
                            почему не в несколько потоков идет парсеринг? почему бы не использовать code.google.com/p/phpmulticurl/?
                              +2
                              Не подумал, не учел, не знал о таком готовом классе, но спасибо за совет — вполне возможно, переделаю. В свободное время. :)
                                0
                                Кстати, тут упоминается, что
                                habrahabr.ru/post/170801/#comment_5928889

                                когда я краулил хабр пол года назад — третий параллельный коннекшен ломал весь процесс загрузки. Как только хабр видит что с одного ip адреса кто-то делает больше 2-ух запросов — дропает все.


                                Так что создание параллельно работающей версии оставлю тем, кому это надо и у кого есть на это время… :)
                                  0
                                  Спасибо за наводку на этот класс и возможность. Добавил в скрипт возможность качать в несколько потоков, но только для картинок ;-)
                                  –1
                                  Юзать short tags в проектах которые публикуются — не круто.
                                    +1
                                    Учту этот момент на будущее, в текущей версии поправил ;)
                                    0
                                    Добавлена возможность сохранять комментарии! По-умолчанию выключена, и вот почему:

                                    • (+) в статье комментарии могу быть не менее ценны, чем сам пост, а то ценнее
                                    • (+) сильнее, чем уже есть верстку не ломает
                                    • (-) не сохраняет картинки из комментариев
                                    • (-) выводит комментарии линейно
                                    • (-) увеличивает время конвертации и размер получающегося файла. Для сравнения — моё избранное без картинок и без комментариев весило 5-6 мб., с комментариями, но без картинок — под 50 мб. При таком количестве текста телефон еле ворочается, по несколько секунд перелистывая страницы...
                                      0
                                      php на дескопе, естесственно, у меня нет. что делать?
                                        0
                                        Поставить?
                                          0
                                          Я заметил, в вашем примере XML не валидный:
                                          Скрин1
                                          Скрин2
                                            0
                                            Да-да, там чуть выше и упоминания, и пояснения к этому решению указаны. И ближайший патч это поправит, замена будет на тэг emptyline. Если хотите, можете выправить, я пулл реквесты быстро принимаю :)
                                            0
                                            Обновление скрипта.
                                            Теперь файл более корректен (с токи зрения XML). Правда, FBreader на всех платформах его не принимает, так же как и одна из аппаратных книг, но большинство читалок файл всё-таки одолеет. Заменен демонстрационный файл.
                                            По совету в комментариях — добавил возможность включить скачивание картинок параллельно, в несколько потоков.
                                              0
                                              Не знаю в чем трабла но у меня постоянно стопорится на этом этапе «картинка номер 3 из 1867»
                                                0
                                                Самый простой способ отладить — запустить firebug и посмотреть в консоли, что отвечает при запросе 3й картинки (скачивании или записывании в файл?). По идее, некорректные или не скачавшиеся файлы должно просто отбрасываться. Плюс можете включить в конфиге логгирование.

                                                Вечером посмотрю скачивание вашего избранного с домашнего компьютера, и потом отпишусь.
                                                0
                                                Залейте кто-нибудь это на беспланый хостинк с php и перед генерацией спрашивайте ник пользователся, чтобы все могли пользоваться — цены вам не будет!
                                                  0
                                                  Знаете… готов сделать :) Только подскажите, я никакие правила сайта этим действом не нарушу?
                                                    0
                                                    там придется скрипт немного расширять, дабы хостинг не уронить от наплыва )) И код оптимизировать.
                                                      0
                                                      Вот как раз и проверили бы. Насчет правил — если автор статьи разрешит, то думаю все будет по правилам
                                                        0
                                                        Ну собственно я и есть автор статья, и я не против ))) Найдется время — сам займусь :)

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

                                                  Самое читаемое