Last active
August 29, 2015 14:17
-
-
Save kiyota-yoji/2b01c2ab4150769e0ebd to your computer and use it in GitHub Desktop.
QRコード付きカードの印刷
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
東京駅 http://ja.wikipedia.org/wiki/%E6%9D%B1%E4%BA%AC%E9%A7%85 東京駅(とうきょうえき)は、東京都千代田区丸の内一丁目にある、東日本旅客鉄道(JR東日本)・東海旅客鉄道(JR東海)・東京地下鉄(東京メトロ)の駅である。 http://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Tokyo_station_from_marunouchi_oazo.JPG/800px-Tokyo_station_from_marunouchi_oazo.JPG http://commons.wikimedia.org/wiki/File:Tokyo_station_from_marunouchi_oazo.JPG Toshinori baba, CC BY-SA 3.0 | |
簗場駅 http://ja.wikipedia.org/wiki/%E7%B0%97%E5%A0%B4%E9%A7%85 簗場駅(やなばえき)は、長野県大町市平中綱にある、東日本旅客鉄道(JR東日本)大糸線の駅である。 http://upload.wikimedia.org/wikipedia/ja/thumb/7/76/%2709.1.10_Yanaba-Sta.jpg/800px-%2709.1.10_Yanaba-Sta.jpg http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:%2709.1.10_Yanaba-Sta.jpg XT, CC BY 3.0 | |
東山駅 (北海道) http://ja.wikipedia.org/wiki/%E6%9D%B1%E5%B1%B1%E9%A7%85_(%E5%8C%97%E6%B5%B7%E9%81%93) 東山駅(ひがしやまえき)は、北海道(渡島総合振興局)茅部郡森町にある北海道旅客鉄道(JR北海道)函館本線(本線)の駅である。駅番号はH64。電報略号はヒヤ。 http://upload.wikimedia.org/wikipedia/ja/thumb/3/32/%2709.3.8_Higashiyama-Sta.JPG/800px-%2709.3.8_Higashiyama-Sta.JPG http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:%2709.3.8_Higashiyama-Sta.JPG XT, CC BY 3.0 | |
姫川駅 (北海道) http://ja.wikipedia.org/wiki/%E5%A7%AB%E5%B7%9D%E9%A7%85_(%E5%8C%97%E6%B5%B7%E9%81%93) 姫川駅(ひめかわえき)は、北海道茅部郡森町字姫川にある北海道旅客鉄道(JR北海道)函館本線(本線)の駅。駅番号はH63。電報略号はヒメ。 http://upload.wikimedia.org/wikipedia/ja/thumb/3/3d/%2709.3.8_Himekawa-Sta.JPG/800px-%2709.3.8_Himekawa-Sta.JPG http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:%2709.3.8_Himekawa-Sta.JPG XT, CC BY 3.0 | |
神城駅 http://ja.wikipedia.org/wiki/%E7%A5%9E%E5%9F%8E%E9%A7%85 神城駅(かみしろえき)は、長野県北安曇郡白馬村大字神城飯田にある、東日本旅客鉄道(JR東日本)大糸線の駅である。 http://upload.wikimedia.org/wikipedia/commons/thumb/5/57/Kamishiro-station_Oito-Line_JREast.jpg/800px-Kamishiro-station_Oito-Line_JREast.jpg http://commons.wikimedia.org/wiki/File:Kamishiro-station_Oito-Line_JREast.jpg Angus Chan, CC BY-SA 2.5 | |
油須原駅 http://ja.wikipedia.org/wiki/%E6%B2%B9%E9%A0%88%E5%8E%9F%E9%A7%85 油須原駅(ゆすばるえき)は、福岡県田川郡赤村大字赤にある平成筑豊鉄道田川線の駅である。ネーミングライツにより森商事 油須原駅(もりしょうじ ゆすばるえき)と呼ばれる。 http://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Heiseichikuho_Yusubaru_station01.jpg/800px-Heiseichikuho_Yusubaru_station01.jpg http://commons.wikimedia.org/wiki/File:Heiseichikuho_Yusubaru_station01.jpg Muyo, CC BY-SA 3.0 | |
三河一宮駅 http://ja.wikipedia.org/wiki/%E4%B8%89%E6%B2%B3%E4%B8%80%E5%AE%AE%E9%A7%85 三河一宮駅(みかわいちのみやえき)は、愛知県豊川市一宮町下新切にある、東海旅客鉄道(JR東海)飯田線の駅である。 http://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Mikawa-Ichinomiya_Station.jpg/800px-Mikawa-Ichinomiya_Station.jpg http://commons.wikimedia.org/wiki/File:Mikawa-Ichinomiya_Station.jpg Lombroso, Public Domain | |
トロッコ保津峡駅 http://ja.wikipedia.org/wiki/%E3%83%88%E3%83%AD%E3%83%83%E3%82%B3%E4%BF%9D%E6%B4%A5%E5%B3%A1%E9%A7%85 トロッコ保津峡駅(トロッコほづきょうえき)は、京都府京都市西京区嵐山北松尾山にある、嵯峨野観光鉄道嵯峨野観光線の駅。 http://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Truck_Hozukyo_station-201106.jpg/800px-Truck_Hozukyo_station-201106.jpg http://commons.wikimedia.org/wiki/File:Truck_Hozukyo_station-201106.jpg Rsa, CC BY-SA 3.0 | |
鞍馬駅 http://ja.wikipedia.org/wiki/%E9%9E%8D%E9%A6%AC%E9%A7%85 鞍馬駅(くらまえき)は、京都府京都市左京区鞍馬本町にある叡山電鉄鞍馬線の駅。終着駅である。駅ナンバリングはE17。 http://upload.wikimedia.org/wikipedia/ja/thumb/0/06/KuramaSt.JPG/799px-KuramaSt.JPG http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:KuramaSt.JPG Bergmann, GFDL | |
奥多摩駅 http://ja.wikipedia.org/wiki/%E5%A5%A5%E5%A4%9A%E6%91%A9%E9%A7%85 奥多摩駅(おくたまえき)は、東京都西多摩郡奥多摩町氷川にある、東日本旅客鉄道(JR東日本)青梅線の駅である。 http://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Okutama_Station_in_Okutama%2C_Tokyo_3.JPG/800px-Okutama_Station_in_Okutama%2C_Tokyo_3.JPG http://commons.wikimedia.org/wiki/File:Okutama_Station_in_Okutama,_Tokyo_3.JPG Tx-re, CC BY-SA 3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
QRコード付きカード作成用のHTMLファイルを生成する | |
License: MIT License | |
""" | |
__author__ = 'KIYOTA Yoji <kiyota.yoji@gmail.com>' | |
__status__ = 'production' | |
__version__ = '0.1' | |
__date__ = '2015-03-20' | |
""" | |
HTMLヘッダ文字列 | |
""" | |
HTML_HEADER = u"""\ | |
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
<title>QRコード付きカード印刷データ</title> | |
<style type="text/css"> | |
/* hrタグで改ページ */ | |
hr { | |
page-break-after: always; | |
visibility: hidden; | |
} | |
/* ヘッダは右上に配置 */ | |
div.header { | |
text-align: right; | |
font-size: 75%; | |
} | |
/* QRコードは左下に配置 */ | |
div.qrcode { | |
text-align: right; | |
} | |
/* 画像ファイルを中央に配置 */ | |
div.image { | |
text-align: center; | |
} | |
/* 画像の著作権表示 */ | |
div.author { | |
text-align: right; | |
font-size: 75%; | |
} | |
/* タイトルのフォント指定 */ | |
h2 { | |
font-family: "Hiragino Kaku Gothic ProN"; | |
} | |
</style> | |
</head> | |
<body> | |
""" | |
""" | |
HTMLフッタ文字列 | |
""" | |
HTML_FOOTER = u"""\ | |
</body> | |
</html> | |
""" | |
""" | |
カードのHTMLタグテンプレート | |
""" | |
CARD_TEMPLATE = u"""\ | |
<div class="header"><a href="%s">%d</a></div> | |
<div class="image"><img src="%s" %s /></div> | |
<div class="author"><a href="%s">%s</a></div> | |
<h2>%s</h2> | |
<p>%s</p> | |
<div class="qrcode"><img src="%s" width="50" /></div> | |
""" | |
# 画像の大きさの制限値 | |
IMAGE_WIDTH_LIMIT = 300 | |
IMAGE_HEIGHT_LIMIT = 180 | |
# タイトル、説明文の文字数の制限値 | |
TITLE_LIMIT = 20 | |
DESCRIPTION_LIMIT = 100 | |
import argparse, qrcode, sys, urllib, cStringIO, os, traceback | |
import PIL.Image as Image | |
class CardHtmlMaker(object): | |
""" | |
QRコード付きカード作成用のHTMLを生成するクラス | |
""" | |
def __init__(self, qrcode_dir): | |
""" | |
initialization: QRコード画像ファイル用のディレクトリ準備 | |
@param qrcode_dir QRコード画像を格納するディレクトリ | |
""" | |
self.qrcode_dir = os.path.normpath(qrcode_dir) | |
if not os.path.isdir(self.qrcode_dir): | |
os.mkdir(self.qrcode_dir) | |
def _get_image_size_tag(self, image_url): | |
""" | |
Web上の画像サイズをHTTPで取得し、制限サイズを計算 | |
@param image_url 画像のURL | |
@return imgタグのサイズ指定文字列 | |
""" | |
try: | |
res = urllib.urlopen(image_url) | |
except IOError, e: | |
raise Exception(u'画像ファイルの取得中にエラーが発生しました: %s: %s' % (image_url, e)) | |
if res.code != 200: | |
raise Exception(u'画像ファイルが取得できません: %s: status=%d' % (image_url, res.code)) | |
fp = cStringIO.StringIO(res.read()) | |
image = Image.open(fp) | |
(width, height) = image.size | |
if (float(width) / height) > (float(IMAGE_WIDTH_LIMIT) / IMAGE_HEIGHT_LIMIT): | |
# 制限サイズより横長 -> 幅でサイズ指定 | |
return 'width="%d"' % IMAGE_WIDTH_LIMIT | |
else: | |
# 制限サイズより縦長 -> 高さでサイズ指定 | |
return 'height="%d"' % IMAGE_HEIGHT_LIMIT | |
def _make_card(self, num, line, page_break=True): | |
""" | |
1枚のカードのHTML文字列を生成 | |
@param num カード番号(1から始まる) | |
@param line TSVファイルの1行 | |
@param page_break 改ページを行うか否か | |
""" | |
fields = line.rstrip().decode('utf-8').split('\t') | |
if len(fields) != 6: | |
raise Exception(u'入力ファイルのフィールド数が6個ではありません: %d行目: %s' % (num, repr(fields))) | |
(title, page_url, description, image_url, author_url, author_name) = fields | |
# QRコード生成 (page_urlをQRコード化) | |
qrcode.make(page_url).save('./qrcode/%08d.png' % (num)) | |
# 画像サイズを取得 | |
image_size_tag = self._get_image_size_tag(image_url) | |
# 文字数を詰める | |
if len(title) > TITLE_LIMIT: | |
title = title[:TITLE_LIMIT] + '...' | |
if len(description) > DESCRIPTION_LIMIT: | |
description = description[:DESCRIPTION_LIMIT] + '...' | |
# HTMLタグの生成 | |
card_body = CARD_TEMPLATE % (page_url, num, | |
image_url, image_size_tag, | |
author_url, author_name, | |
title, | |
description, | |
'./qrcode/%08d.png' % (num)) | |
if page_break: | |
return card_body + '<hr>\n\n' | |
else: | |
return card_body | |
def output(self, input_data, output_html): | |
""" | |
TSVファイルで入力されたデータから、HTMLファイルを生成する | |
@param input_data 入力ファイル(TSV)のファイルハンドル | |
@param output_html 出力ファイル(HTML)のファイルハンドル | |
""" | |
output_html.write(HTML_HEADER.encode('utf-8')) | |
lines = input_data.readlines() | |
input_data.close() | |
num_cards = len(lines) | |
num_pages = (num_cards - 1) / 4 + 1 | |
for page in range(num_pages): | |
# 1枚目(左上) | |
card_id = page | |
output_html.write(self._make_card(card_id+1, lines[card_id]).encode('utf-8')) | |
# 2枚目(左下) | |
card_id = page + num_pages * 1 | |
if card_id > num_cards - 1: | |
output_html.write('<hr>\n\n') | |
else: | |
output_html.write(self._make_card(card_id+1, lines[card_id]).encode('utf-8')) | |
# 3枚目(右上) | |
card_id = page + num_pages * 2 | |
if card_id > num_cards - 1: | |
output_html.write('<hr>\n\n') | |
else: | |
output_html.write(self._make_card(card_id+1, lines[card_id]).encode('utf-8')) | |
# 4枚目(右下) | |
card_id = page + num_pages * 3 | |
if card_id > num_cards - 1: | |
if page == num_pages - 1: | |
pass | |
else: | |
output_html.write('<hr>\n\n') | |
else: | |
if page == num_pages - 1: | |
output_html.write(self._make_card(card_id+1, lines[card_id], | |
page_break=False).encode('utf-8')) | |
else: | |
output_html.write(self._make_card(card_id+1, lines[card_id]).encode('utf-8')) | |
output_html.write(HTML_FOOTER.encode('utf-8')) | |
output_html.close() | |
def main(): | |
parser = argparse.ArgumentParser(description=u'QRコード付きカード印刷用のHTMLを生成') | |
parser.add_argument('input_data', type=argparse.FileType('r'), help=u'入力ファイル名 (TSV)') | |
parser.add_argument('output_html', type=argparse.FileType('w'), help=u'出力ファイル名 (HTML)') | |
parser.add_argument('--qrcode-dir', default='./qrcode', help=u'QRコードの画像ファイル用ディレクトリ') | |
args = parser.parse_args() | |
try: | |
maker = CardHtmlMaker(args.qrcode_dir) | |
maker.output(args.input_data, args.output_html) | |
except Exception, e: | |
print e.message.encode('utf-8') | |
traceback.print_exc() | |
os.remove(args.output_html.name) | |
sys.exit(1) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
target = card_printout.html card_printout.pdf | |
qrcode_dir = ./qrcode | |
default: $(target) | |
card_printout.html: card_data.txt | |
python make_html.py --qrcode-dir $(qrcode_dir) $^ $@ | |
card_printout.pdf: card_printout.html | |
wkhtmltopdf -s A6 $^ $@ | |
clean: | |
rm -fr $(target) $(qrcode_dir) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment