PythonでPDFを分割する (すべての自炊派バンドマンに捧げる)
やりかた
pyPdfっていうモジュールを使うとできる。
sudo easy_install pypdf
サンプルを参考に練習がてら書いた。
#!/usr/bin/env python # -*- coding: utf-8 -*- from pyPdf import PdfFileWriter, PdfFileReader def main(): """sample.pdf を 3ページごとに分割する""" src = 'sample.pdf' div = 3 src = PdfFileReader(file(src, 'rb')) items = [ range(i, min(i + div, src.numPages)) for i in xrange(0, src.numPages, div) ] for i, lst in enumerate(items): print i, lst dst = PdfFileWriter() for j in lst: dst.addPage(src.getPage(j)) out = file('%03d.pdf' % i, 'wb') dst.write(out) out.close() if __name__ == '__main__': main()
なにこれ超簡単。
ちゃんと書いた
分割用の目次(YAML)を定義して、それをつかって分割させる。こんな感じのやつ。
indexes: # 書式 # (a[,b]) filename # (a) filename => 'ページa のみ抽出' - ( 1 ) foo # p. 1 only # (a,b) filename => 'ページa から ページb までを抽出' - ( 5, 8) bar # from p. 5 to p. 8 # b を省略 => '次の項目まで抽出' - ( 9, ) baz # from p. 9 to p.11 # 最後の要素で b を省略 => '最後のページまで抽出' - ( 12, ) hoge # from p.12 to last # 分割対象の最後のページ(省略した場合はPDFの最後のページ) lastPage: 9999
他にファイル名の前後につける文字や、元のPDFが何ページから始まるかを指定できるようにしてあげる。
あとはコードを書く。
#!/usr/bin/env python # -*- coding: utf-8 -*- import os, re, optparse import yaml import pyPdf def getprofile(profile): profile = yaml.load(open(profile)) prefix = profile.get('prefix', '') suffix = profile.get('suffix', '') fnum = profile.get('fnum', 0) lastPage = profile.get('lastPage') indexes = profile.get('indexes', []) fname = ' '.join([prefix, '%(name)s', suffix]).strip() return indexes, lastPage, (fname, fnum) def makeindexes(indexes): x = re.compile(r'\(\s*([0-9]+)\s*(?:(,)\s*([0-9]+)?\s*)?\)\s*(.*)$') tmp = [] for i in xrange(len(indexes)): m = x.match(indexes[i]) if not m: print 'Syntax Error: line=%d\n - %s' % (i+1, indexes[i]) exit(1) start = stop = int(m.group(1)) if m.group(2): stop = int(m.group(3)) if m.group(3) else None name = m.group(4).strip() tmp.append((start, stop, name)) return tmp def main(): parser = optparse.OptionParser(usage='%prog [Options] src') parser.add_option("-o", "--offset", type="int", default=0) parser.add_option("-p", "--profile") (opts, args) = parser.parse_args() if not args: parser.print_help() exit(0) src = args[0] profile = opts.profile or src offset = opts.offset if not src.lower().endswith('pdf'): src += '.pdf' if not profile.lower().endswith('yaml'): profile += '.yaml' indexes, lastPage, (fname, fnum) = getprofile(profile) indexes = makeindexes(indexes) print 'Divide PDF: %s (using %s)' % (src, profile) src = pyPdf.PdfFileReader(file(src, 'rb')) if lastPage is None: lastPage = src.numPages else: lastPage = min(lastPage, src.numPages) for i, (start, stop, name) in enumerate(indexes): dst = pyPdf.PdfFileWriter() if stop is None: if i < len(indexes) -1: stop = indexes[i+1][0] - 1 else: stop = lastPage filename = fname % dict(fnum=(fnum+i), name=name) print ' page(%4d-%4d) => %s.pdf' % (start, stop, filename) for j in xrange(start, stop+1): if j + offset < lastPage: dst.addPage(src.getPage(j + offset - 1)) out = file('%s.pdf' % filename, 'wb') dst.write(out) out.close() if __name__ == '__main__': main()
prefix: 'The Beatles %(fnum)02d' fnum: 1 indexes: - ( 2,) LOVE ME DO - ( 8,) PLEASE PLEASE ME - ( 14,) FROM ME TO YOU - ( 19,) SHE LOVES YOU - ( 26,) I WANT TO HOLD YOUR HAND - ( 33,) ALL MY LOVING - ( 39,) CAN'T BUY ME LOVE - ( 48,) A HARD DAY'S NIGHT - ( 56,) AND I LOVE HER - ( 62,) EIGHT DAYS A WEEK - ( 67,) I FEEL FINE - ( 75,) TICKET TO RIDE - ( 82,) YESTERDAY - ( 84,) HELP - ( 91,) YOU'VE GOT TO HIDE YOUR LOVE AWAY - ( 95,) WE CAN WORK IT OUT - (101,) DAY TRIPPER - (111,) DRIVE MY CAR - (118,) NORWEGIAN WOOD - (122,) NOWHERE MAN - (128,) MICHELLE - (136,) IN MY LIFE - (143,) GIRL - (149,) PAPERBACK WRITER - (155,) ELEANOR RIGBY - (160,) YELLOW SUBMARINE
雑感
Pdfっていう書き方ダサいですよね?