トップ 追記

日々の破片

Subscribe with livedoor Reader
著作一覧

2018-04-17

_ ヘッドレスChromeでPDF

HTMLからPDFを生成する必要があって、以下の方法を考えた。

Edgeに該当URIを叩かせて、プリンタドライバにMS純正のPDF出力を設定しておいてJavaScriptでprintを呼び出す。

で、これが確実に動くのはわかっているのだが、実行環境がGNU/Linuxなのでどうにもならない。

Firefoxはapt-getで入れられるのでメンテナンスが楽そうだが、PDFに出力する簡単な方法が考え付かない。

しょうがないので、ヘッドレスChrome(頭があって手足がないが正解な気がするが本人がヘッドレスを名乗っているのだからまあ良いのだろう)を使うことにした。

Chromeはapt-getはできないが、debが用意されているから我慢する(のだが、今、あらためてみると、どうやってdebをダウンロードしたのかまったくわからない。どうあってもWindows版をダウンロードさせようとするのだが、キャンセルしまくると小さな文字のリンクがあって、Linuxを選択すると、またダイアログが出てくる……。しかし1週間くらい前にはまともなページにたどり着けて、そのURIをcurlしたんだよなぁ)。

説明を読もうとすると、なぜか頼みもしないのに日本語のページ(ヘッドレス Chrome ことはじめ)に飛ばされて、かつ情報が古い(Windowsでは待てとなっているが、Windowsでも--headlessで動作するので古い。書いてあるChromeは59についてだが、Windows版は65になっているし)が、まあ、このページからリンクされているところはそれっぽいから問題なかろう。

・このメモを書くためにあらためて「ヘッドレス Chrome ことはじめ」のページを眺めていたら、一番最後にドロップダウンリストで言語を選択できるようになっていて、US Englishにしたら、Windowsは60からのサポートとバージョン番号付きで書いてあった。なら65で動いて当然だ。というか、なんで先頭で言語を選択できるようにしていないのだろうか(または常に同期を取らないのだろうか)。なんか本当に面倒くさいベンダーだなぁ。

で、PDFの出力方法として chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/ というのが出ているのだが、これが全然だめだ。

コンテンツに重なって頼みもしないヘッダとフッタが出力される。どうしろと。

で、調べるとStack Overflowにやはり同じ問題で困った人たちが質問しているが、有効な解答が、マージンなしにして出力すればヘッダとフッタが下になって隠されるというやつで、なんだそれ。コンテンツとして印刷用のマージンを入れることになるわけだが、それだとWebとPDFでスタイルを変えなければならないし、しかも、PDF出力時のメディアタイプがわからないから話にならない(@media PDFかな? とか思ったがall、print、screen、speech以外に何が使えるか調べるのもあほらしくてやらなかった)。

が、DevTool(Chromeのデバッガインターフェイス)を眺めたら、Page#printToPDFというメソッドがあって、そのパラメータに、displayHeaderFooterというまさにおれが欲しいものがあるではないか。

この場合、Chromeを起動しておいて外部からWebSocketで操作することになる。WebSocketの口はhttpで/jsonから取得する、おお、こういうインターフェイスは大好きだ。こういうところは素晴らしい。

で、起動方法はリモートデバッグオプションを指定して、chrome --headless --disable-gpu --remote-debug-port=9222とすれば良いらしい(というか、これで動いた)。ポートの9222はデフォルトらしいので変えたければ別の値を指定すれば良いのだろうけど、いずれにしてもクライアントが最初にHTTPでアクセスするからウェルノウンにしておく必要はある。あと、disable-gpuは無くても動くようだが、バグを突くといやだから(バグ回避用の設定っぽい)指定する。これをnohupしておいて別口のクライアントからアクセスすることになる。

ぱっと見、DevToolを操作するためのnode用のライブラリがあるようだが、そんなもの使いたくないので、自分でopen-uriを使ってポート9222の/jsonを叩いてPageのURIを取ってWebSocketを使ってと書き始めたが、ふと、こんな程度の処理なら誰か作っているのではと気づいた。で、さらに探すと(しかしドキュメント性が低いのでやたらと時間が食われるのには閉口した)、chrome_remoteというGemがあることがわかったので、それを利用することした。

えらく簡単だ。

require 'chrome_remote'
require 'base64'
 
class PdfWriter
  def initialize()
    @chrome = ChromeRemote.client
    @chrome.send_cmd 'Network.enable'  # Navigateに必要
    @chrome.send_cmd 'Page.enable'     # Pageオブジェクトの操作に必要
    @chrome.send_cmd 'Runtime.enable'  # JavaScript実行に必要
  end
 
  def to_pdf(uri)
    @chrome.send_cmd 'Page.navigate', url:uri
    @chrome.wait_for 'Page.loadEventFired'
    # ロード後に数秒実行に必要なJavaScriptが動くとしたらここで待機するか、またはイベントをチェックする必要がある。
==begin
    JavaScriptの呼出しには、Runtime.evaluateを使う
    ret = @chrome.send_cmd 'Runtime.evaluate', expression: "document.getElementById("foobar').baz()"
==end
    ret = @chrome.send_cmd 'Page.printToPDF', 
                           dispalyHEaderFooter:false,  # これがやりたかったことだ
                           printBackground: false,
                           paperHeight: 11.7, paperWidth: 8.3 # A4: 11.7inch * 8.3inch
    ret['data']  # JSONが返されてdataプロパティにBase64エンコードされたPDFが格納されている
  end
 
  def to_pdf_file(file, uri)
    data = to_pdf(uri)
    File.open(file, 'wb') do |fout|
      fout.write(Base64.decode64(data))
    end
  end
end

実際は同じChromeのインスタンスを使いまわしたいので、Mutex使って排他制御したり他にもいろいろするが、単発ならこれでOK。


2018-04-12

_ ケビン・ミトニックの超監視社会で身をまもる方法を読了

なんとなくおもしろそうなので買って読んだ。

ら、想像よりも遥かにおもしろかった。

そりゃそうだと納得するのは、ケビン・ミトニックはハッカーはハッカーでもコンピュータハッカーというよりは、ソーシャルエンジニアリングのハッカーだった。この男は口車という車に乗って、世界中を飛び回る。まさに立て板に水のようにぺらぺらぺらぺらおもしろ話が出てくる出てくる(本人が執筆しているのではなく、ケビン・ミトニックの放談をロバート・バモシという人がまとめた本のようだ)。

パターンは決まっていて、大体以下のような組み立てになっている。

label:a

というわけで~すれば安全かというとそうではない。

~年、~のことだ。~という男が~から~した。彼は~することを忘れていたというわけだ。

すぐさまFBIが~へ急行したのは言うまでもない。

一体何がまずかったのか?

~には~という仕組みがあるため、~から居場所がわかってしまうのだ。

では、どうすれば良いか?

実は~には~というアクセス手段がある。

~年のことだが、わたしが~へ行ったときはこの方法を使った。

つまり最初に~してから~したというわけだ。

もちろん、なんの問題もない。

さて教訓だが、~のときに自分を秘匿するには~だけではだめだということだ。~の場合には~と~が欠かせない。

goto label:a

ためになるかどうかはともかく、おもしろい。

伝説のハッカーが教える超監視社会で身をまもる方法(ケビン・ミトニック/ロバート・バモシ/高取芳彦)

なお、内容紹介には

その中でミトニックが与えるヒントは、無法地帯とも言えるサイバー空間でプライバシーを守るための究極のサバイバルマニュアルとなっています。

と書いてあるが、相当違う。NSAやFBIやCIAが跋扈する無法地帯とも言える現実社会で自分自身のプライバシーを守りながらサバイバルする方法だ。

というわけで、ケビン・ミトニックのヒーローはスノーデンのようだ(スノーデンがリークするために行ったあれこれを相当細かく説明している)。というか、スノーデンが取った方法は公開されているからだろう。

なぜか読んでいる最中、なぜかビッグデータ・コネクトを思い出したりした。

ビッグデータ・コネクト (文春文庫)(藤井太洋)

これも、社会という無法地帯に跋扈する警察やらマスコミやらからプライバシーを守りながらサバイバルする話(でも)あった。


2018-04-11

_ 今日のバグ

あまりにもあほうなバグのために1~2時間ほど悩む。

最初、次のようなコードを書いていた。

class X
  def htov(a) #本当はjoinでは済まない程度に複雑
    s = "**begin**\n"
    a.each {|e| s << "#{e}\n" }
    s << "**end**\n"
  end
end

最初のと最後のマークを定数にしたほうが良いことに気づく(他のオブジェクトも利用するからだ)。

で、直す。

class X
  BEGIN_MARK = "**begin**\n"
  END_MARK = "**end**\n"
  def htov(a)
    s = BEGIN_MARK
    a.each {|e| s << "#{e}\n" }
    s << END_MARK
  end
end

で、1回動かして問題ないことを確認したわけだが、あとから動かしていると異常なデータが作られまくる。

4文字追加して修正。

追記:Stringを定数として扱いたければ積極的に例外にさせるためにfreezeしたものに定数名をつけるのが良いだろう。BEGIN_MARK = '**begin**¥n'.freeze


2018-03-27

_ ほうれん草とかき菜の炒め物ハムユイ味

今度は車ではなく歩いて青山墓地へ花見。えらく閑散としているが、良く見ると立て看で屋台禁止とか書いてある。4半世紀たってここも随分お行儀良くなってしまったようでつまらんが、酔っ払いがいないのは良い点だ。

キラー通りの陸橋のところで、さてどうしようかと考えて、適当に南青山方面へ向かい、予約していないから無理かと思ったら席が幾つか空いていたので結局エッセンスに入った。

で、青菜の炒め物でも食うかと見ると、本日のお皿はほうれん草とかき菜となっている。かき菜は家にもあると妻が言うが、かき菜ってなんだ? それはそれとして味付けはいくつもあって選べるのだが、最後にハムユイというのが書いてある。髪結いみたいだなと思うが、良くわからない。

店の人に聞くと、しばらく考えてから塩味だ、という。塩味にしては塩味は別にあるから、要領を得ない。したがって、それにした。

出てくると、どこかで知っているような香りがする。アンチョビだな。食べるとやはりアンチョビっぽい。

後で調べたらイシモチなどを発酵させた調味料だというようなことが書いてあって、アンチョビはヒシコイワシだからものは違うが、似たような香りと味になるのだな。

で、すさまじくおいしかったので、ピーコックへ寄ってハムユイを探すが、無い。イオン系列になってから品揃えが随分とつまらなくなったがしょうがない。そうはいってもアンチョビなんだから瓶詰めのアンチョビと、あとほうれん草を買った。一時に比べて随分と安くなった。

で、帰ってから早速作ってみる。

中華風に炒める場合はボイラープレートがあるので、それに従う。

まずフライパンにごま油を入れて煙りが出るまで熱する。

次に適当に切った長ネギを入れて香りを出す。

次に、茎のほうを根元から順に5mm、1cm、2cm、4cmと切った部分を入れる(太さ固さと長さを乗じた数が同じくらいになるようにするのだ)。少し炒まったところで味付け、この場合はここでアンチョビを入れる。

エッセンスでは形が見えないくらいに混ぜ込んでいたが素人料理だから、適当にかき混ぜるくらいでいいや。面倒だし。

最後に葉っぱを入れて、両面に油が馴染むくらいに炒める。というのをやっていると、あっという間にフライパンからあふれそうだった青菜が小さくなるのでできあがり。

で、食ったらおれが作ってもやっぱりうまかった。


2018-03-26

_ ピエール・パトラン先生

スリービルボーヅを観に渋谷の街へ出かけた時に文鳥堂で売っているのを目にして買ったピエール・パトラン先生を読了。

といっても、元から知っているわけではなく、岩波文庫のいきなり復刊シリーズは気づけば買うようにしているからだ。

小一時間程度で読了。

カバー裏からして読ませる。

金はない、客は来ない、服はボロボロ。この苦境を乗り越えるのが「口車」という乗り物なのだ……

張儀、蘇秦の輩か? と思いながらも、確かにそれは最高の車ではないか、と買ったのだった。

最初に訳者の長い解題と翻訳の苦心談がある。これがめっぽうおもしろい。1960年代初頭の翻訳だが、このころまでは、翻訳家は、どれだけカタカナを使わずに日本語にするかに苦心惨憺していて、おれは、大好きなうえにそのての訳業についてはこよなく尊敬している(こういう苦労でみんなが知っている例だとストライダーの馳夫とかカテドラルの伽藍とかになるわけだ。日本文化の教養重要)。

で、読み始めると、ピエール・パトラン先生とはどうも弁護士っぽい。

15世紀フランスの弁護士か。というか、弁護士というのが、いかに社会的にみて怪しい職業かが良くわかる(ということはそれから200年たっているとはいえ、ロベスピエールやダントンがどういう社会的地位にあったのかとかいろいろ考える)いっぽう、15世紀には弁護士を立てるという形式のまともな裁判があるということに感心する。だてにおフランスと呼ばれているわけではない。

詐欺がばれてさらし者にされたことがある凶状持ちのピエール・パトラン先生、どうにかして服を仕立てようと、布屋(翻訳では羅紗屋)から布を巻き上げるための算段をする。

この方法はちょっとばかり落語に近い。

さらには、布屋の強欲っぷりに腹を立てた羊飼いの弁護を引き受けることになる。

という、実に豪快にどうでも良い戯曲なのだが、言葉遊びが実に楽しく、それを翻訳家がくそまじめに格闘していて(脚注として原本ではこれこれこうだから日本語のこれこれこうに翻訳してみたというような説明がたくさんある)さらに楽しい。

最高だと思ったのが、Saint Leu(ルー聖人)のところで、この5世紀の聖人の名前の発音ルーがloup(狼)に通じるということで、15世紀にはすっかり、羊飼いの守護聖人として認められていたという、フランスでの言葉遊び(とはいえ守護聖人にしているのだから半分まじめではあるわけだが)にしびれると同時に、訳業は

狼上人様

で、さらにしびれる。

(日本語だけではなく、フランス語もある程度わかるほうがさらに楽しめる)

ピエール・パトラン先生 (岩波文庫)(渡辺 一夫)

楽しいひと時だった。

本日のツッコミ(全1件) [ツッコミを入れる]

_ 柴鳥次郎 [仏文出身で、何十年も前に買ってあったのに、『ピエール・パトラン先生』を読んでいませんでした。今日中に読みます。]


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|

ジェズイットを見習え