Избранное Хабра в PDF

:

Всех с наступившими!

image

Так как я люблю все упорядочивать и каталогизировать, давно вертелась мысль завернуть избранные топики с хабра в PDF и отсортировать по датам.
Собственно выделилось немного свободного времени в праздники, решил задуманное осуществить и поделиться с хабром

UPD:
— Исправлена ошибка «too large on page» (подробнее на github) Спасибо Bifidokk и StreetAngel
— Авторы топиков сделаны ссылкой
— Добавлена возможность сохранять избранное только из указанных блогов

Для работы скрипта требуется python-pisa
Работу под windows к сожалению не тестировал, нет поблизости

Порядок запуска:

Редактируем fav2pdf.py под ваши нужды

user = 'vrtx' - имя пользователя
site = user + '.habrahabr.ru'
from_date = '1 января 2011' - дата, с которой брать топики
to_date = '' - дата, по которую брать топики

Запускаем

python fav2pdf.py

Вывод будет приблизительно следующий

Processed page 1 of 25:
----------------------
1 Topic: Переводы->50 цитат о программировании всех времён
2 Topic: Android->[Программирование] Работа со строкой состояния в Android
3 Topic: Mobile Development->Пошаговое описание создания простого приложения для Samsung Bada
4 Topic: Ненормальное программирование->Brainfuck и счастливые билеты
Topic: ХабраЮмор->Трое В Серверной, Версия 1.0, Новогодняя Редакция is locked!
----------------------

Prepare PDF...

В итоге рядом со скриптом получим файлик с названием вашего ника в формате pdf

Особенности:

  • Заглавная страница с содержанием
  • Заголовок топика ведет на топик на хабре
  • Страницы вытягиваются из мобильной версии хабра
  • Возможность ограничивать выборку по датам, можно вести например личный хабражурнал :)
  • Возможность вытаскивать избранное любого пользователя

К сожалению, топики в избранном отсортированы по дате добавления туда, а не по дате публикации, поэтому пришлось перебирать полностью все избранное,
что хоть и не сильно сказывается на скорости (чтение при 256k порядка 230 топиков ~ за 3 мин), но неприятно.

Минусы:

  • Не читает закрытые блоги (требуется логин)
  • Надеюсь из временных минусов — глюки с отображением содержимого тега pre (нативная подсветка синтаксиса), редко кто ей пользуется из авторов, но все же
  • Также могут быть другие огрехи в отображении из-за ограниченной поддержки CSS в PISA
  • pisa-parser не видит ссылки на изображения, содержащие кириллицу
  • Не делал никаких «защит от дурака»

Пока минусов больше не нашел, но любом случае, те что упомянул, встретились в моих избранных, а это не много не мало 230 топиков + тестировал на нескольких пользоватеях

image

Кому все еще интересно, ссылка на github

Инструкция для запуска скрипта под Windows, спасибо desiderata:

1. Ставим Python 2.7.1 x86 (под версией 3.0 и выше скрипт не работает, под x64 проблемы с _imaging)
2. Ставим pisa 3.0.31 и необходимые для неё модули:
Часть модулей устанавливается через Windows Installer,
часть командой C:\python27\python.exe setup.py install
ReportLab Toolkit 2.5, html5lib 0.9, PyPdf 1.13, PIL 1.1.7, setuptools 0.6c11, pisa 3.0.33.
3. Патчим C:\Python27\Lib\site-packages\PIL\Image.py согласно комментарию.
4. Редактируем fav2pdf.py по инструкции в посте.
5. C:\Python27\python.exe fav2pdf.py
6. PROFIT и спасибо Автору.

P.S. По окончанию работы скрипт всётаки выдал ошибку в pisa_document.py", line 229, in pisaDocument
Тем не менее PDF файл успешно создался и содержит все статьи из избранного.

PS
Если при работе скрипта вылезет похожая ошибка, лечится патчем PIL:
File "/usr/lib/python2.6/dist-packages/PIL/Image.py", line 1498, in split
if self.im.bands == 1:
AttributeError: 'NoneType' object has no attribute 'bands'

Решение:
# HG changeset patch -- Bitbucket.org
# Project pil-2009-raclette
# URL bitbucket.org/effbot/pil-2009-raclette/overview
# User Fredrik Lundh <fredrik@effbot.org>
# Date 1272193085 -7200
# Node ID fb7ce579f5f96f7d9008f72ab03eef4f1c6db609
# Parent 45c2debe0fc3d9632372a15826b1b64a35ff43c4
Fixed split after open bug (regression in 1.1.7).

--- a/PIL/Image.py
+++ b/PIL/Image.py
@@ -1494,11 +1494,11 @@ class Image:
def split(self):
"Split image into bands"

+ self.load()
if self.im.bands == 1:
ims = [self.copy()]
else:
ims = []
- self.load()
for i in range(self.im.bands):
ims.append(self._new(self.im.getband(i)))
return tuple(ims)

PS2
Совсем не силен в регулярках, если кто-то подскажет более оптимальные выражения, буду благодарен.