python: แปลง html เป็น epub

เป็นโปรแกรมเล็ก ๆ ในการช่วยแปลงไฟล์ HTML เป็น EPUB ทำงานได้ในไฟล์เดียว แต่ยังทำงานได้จำกัด ไม่ได้รองรับข้อกำหนดทุกอย่างของ EPUB โดยเฉพาะ HTML5

ดาวน์โหลด

การปรับปรุง

  • 57-01-26: เพิ่มการรองรับ footnote โดยโปรแกรมจะค้นหา footnote ที่มีอยู่ และสอดกลับเข้าไปในบทที่เป็นลิงก์ต้นทาง มีข้อแม้ว่า ต้องขึ้นต้นด้วย <p class="footnote" หรือ <div class="footnote" เท่านั้น

สมบัติและข้อกำหนด

  • แปลง HTML ไฟล์เดี่ยว
  • ต้องเตรียมไฟล์ต้นฉบับ HTML มาก่อน เช่น
    • บังคับแบ่งบทด้วยแท็ก <!--section_break--> หรือ <!--page_break-->
    • หากไม่มีแท็กแบ่งบทข้างต้น โปรแกรมจะแบ่งด้วยแท็ก <h1> หรือ <h2>
    • อาจแบ่งคำด้วย SWATH ซึ่งต้องแบ่งมาก่อน
    • ปรับแต่ง css มาแล้ว ซึ่งอาจเป็นภายในไฟล์ HTML เอง หรือระบุไฟล์ภายใต้ไฟล์ลูก INC_FILE.py ด้วยพารามิเตอร์ -i ก็ได้ (EPUB รองรับ css ไม่ครบทุกคำสั่ง) โดยอันหลังสำคัญกว่าอันแรก คือจะแทนที่ css ในไฟล์ HTML ด้วย css ที่ระบุไว้
    • ถ้ามีบทสารบัญภายในไฟล์ HTML โปรแกรมจะสร้างบทสารบัญไว้ด้วย แต่จะสร้างโค้ด HTML ขึ้นมาใหม่เพื่อให้สอดคล้องกับ EPUB หากไม่ต้องการให้มีสารบัญอยู่ภายในบท ต้องลบบทสารบัญออกจากไฟล์ต้นฉบับ HTML ออกก่อน
  • แปลงเป็น EPUB ได้ 3 รุ่น คือ 2.0, 2.0.1 และ 3.0 ระบุด้วยพารามิเตอร์ -ver ค่าปริยายคือ 2.0.1
  • ระบุจำนวนชั้นของสารบัญได้ ด้วยพารามิเตอร์ -toclevel N ค่าปริยายคือ 3
  • ไฟล์ประกอบ เช่น ไฟล์ภาพ,ไฟล์ฟอนต์ และอื่น ๆ ต้องเตรียมด้วยมือเอง โดยใส่ไว้ภายใต้ไดเรกทอรีที่ระบุในพารามิเตอร์ -incdir DIR ทุกไฟล์และไดเรกทอรีภายใต้ DIR/ จะถูกคัดลอกไปยังไดเรกทอรีของ EPUB ชื่อ OEBPS/ ซึ่งถือเป็นไดเรกทอรีรากของ EPUB เวลาเราอ้างถึงไฟล์จากคำสั่งใน css หรือคำสั่งใน HTML จะอิงกับไดเรกทอรีรากนี้เสมอ
  • เมื่อโปรแกรมทำงานเสร็จ จะทิ้งไดเรกทอรีงานเอาไว้ ชื่อ epubdir เพื่อประโยชน์ในการดีบั๊ก เมื่อเสร็จงานแล้ว สามารถลบทิ้งด้วยมือ และในการสั่งงานโปรแกรมแต่ละครั้ง ทุกอย่างภายใต้ไดเรกทอรีนี้ จะถูกลบทิ้งและสร้างขึ้นใหม่ ดังนั้นหากมีการแก้ไขเพื่อทดสอบ ควรแบคอัพไว้ก่อน และหากไม่ต้องการรันโปรแกรมใหม่ แต่เป็นการแก้ไขเพื่อทดสอบ ให้ใช้คำสั่งเชลล์ในการสร้าง EPUB ดังนี้
    $ cd epubdir
    $ zip -qX0 ../FILE.epub mimetype
    $ zip -qrX9 ../FILE.epub * -x mimetype
    $ cd -
    
  • เขียนแบบ quick & dirty ค่อย ๆ คลำไป บั๊กเยอะแน่นอน

หมายเหตุในการทดสอบ

  • เลือกใช้รุ่น 2.0.1 เป็นค่าปริยาย เพราะ Google Play Books แสดงผลสารบัญแบบหลายชั้นได้ไม่ครบถ้วน และความรู้ยังไม่พอศึกษาและทดสอบ HTML5
  • ใช้โปรแกรม epubcheck ในการตรวจสอบความถูกต้องของไฟล์ epub ที่ได้
  • การฝังฟอนต์ ยังไม่ได้ทดสอบ เพราะโปรแกรมอ่านอีบุ๊คในท้องตลาดยังรองรับภาษาไทยและ opentype ไม่เต็มที่
  • การทดสอบการแสดงผล ส่วนใหญ่ทดสอบใน EPUBReader Extensions ในไฟร์ฟอกซ์, Google Play Books บน Desktop/Android และ iBooks บน Mac/iOS ก็แสดงผลได้ดีพอควร มีข้อสังเกตุคือ
    • EPUBReader Extensions แสดงขนาดฟอนต์ได้ไม่คงที่นัก
    • Google Play Books บน Desktop แสดงผลได้ค่อนข้างดี สารบัญแสดงครบ
    • Google Play Books บน Android แสดงได้พอใช้ มีการแสดงผลตัวเอียงผิดสลับมาบ้าง สารบัญหลายชั้นของรุ่น 3.0 แสดงผิดเป็นบรรทัดว่าง และของรุ่น 2.0 แสดงแค่ชั้นเดียว
    • iBooks ทั้งบน Mac และ iOS แสดงผลได้ดีเลิศ รองรับ CSS กว้างที่สุด แต่บน iOS7 ทำงานกับภาษาไทยได้ช้ามาก

การใช้งาน

ลองใช้งานด้วยคำสั่ง

$ ./html_2epub.py

ได้ผลเป็น

Usage: html_2epub.py [-showvar] [-ver EPUB_VER] [-ctl] [-toclevel N] [-i INC_FILE.py] [-c COVERIMG] [-incdir INC_DIR] FILE.html [FILE.epub]

Convert one html file to epub.

Parameters:
    -showvar: show internal variables that can modify for properly convert.
        example: html_2epub.py -showvar > INC_FILE.py.
    -ver: EPUB version ['2.0', '2.0.1', '3.0'], default '2.0.1'.
    -ctl: convert html tag to lowercase, not necessary if tag is already lower.
    -toclevel N: max level of TOC (default is 3).
    -i: include additional variables from INC_FILE.py.
    -c: cover image (jpg,png,gif).
    -incdir: include directory (will copy all files/dir in this dir into OEBPS/).

To do:
    - ISBN supported, currently just use UUID.

ลองสร้างไฟล์ลูก

$ ./html_2epub.py -showvar > INC_FILE.py
$ cat INC_FILE.py

ได้เป็น

#!/usr/bin/env python
# coding=utf-8
# ---------- html_2epub.py SECTION ----------
#
# variable that can be overriden.

#VARIABLE ORDER: no order required.


#-----type: STRING, will REPLACE default variable of same name-----
#style_file : stylesheet file to replace original in html file.
style_file = ""

#language : language to be used, ('ENGLISH','THAI' : default THAI).
language = "THAI"

#book_uuid : UUID book identifier.
book_uuid = "7a27330a-ebec-4fe9-9eb3-d8f09a75e789"

#book_isbn : ISBN book identifier.
book_isbn = ""


#-----type: STRING, will APPEND default variable of same name-----

#-----type: LIST, will APPEND default variable of same name-----
#add_toc_brk_list : additional tags to be use for breaking chapter: [ [TAG,LEVEL],...].
add_toc_brk_list = []

#mod_toc_title_list : text to override default toc header and toc level: [ [CHAP_FILE#ID,LABEL,LEVEL],...] (use LEVEL=0 is no modified).
mod_toc_title_list = []

หลังจากปรับแต่งไฟล์ INC_FILE.py แล้ว ลองใช้งานจริงด้วยคำสั่ง

$ ./html_2epub.py -i INC_FILE.py INFILE.html OUTFILE.epub
Topic: 
Creative Commons License ลิขสิทธิ์ของบทความเป็นของเจ้าของบทความแต่ละชิ้น
ผลงานนี้ ใช้สัญญาอนุญาตของครีเอทีฟคอมมอนส์แบบ แสดงที่มา-อนุญาตแบบเดียวกัน 3.0 ที่ยังไม่ได้ปรับแก้