Watirを使う際にChromeDriverを自動的にインストールさせるrubygem webdrivers

自動化したいよね

ChromeDriver は Chrome のバージョンと合わせておく必要があり、合わないとエラーが出ます。しかし Chrome はしょっちゅう更新されていきますし、しかもタイミングによっては(なぜか)ChromeDriver のほうが先に更新されてしまって結果としてバージョンずれが生じてしまうこともあります。ChromeDriver を使いたいときは SeleniumWatir などで自動ブラウジングがしたいのであって、ChromeDriver のバージョンなどという些末な問題にとらわれて時間が取られるなんてイヤですよね。

(以前に ChromeDriver を手動で入れたときの記事:WatirでHeadless Chromeを使うまでのメモ - 別館 子子子子子子(ねこのここねこ)はてブロ部 つまり Homebrew で入れてました。)

Chrome に合った ChromeDriver を自動的にインストールさせる rubygem として chromedriver-helper gem があったのですが、2019年3月末で期限切れになり、別の gem である webdrivers gem が新しく提供されています。

webdrivers gem の紹介記事:サポートが終了したchromedriver-helperからwebdrivers gemに移行する手順 - Qiita

使い方

Watir 利用時の webdrivers gem の使い方ですが、Gemfile を使っている場合には

gem "webdrivers"
gem 'watir'

そしてスクリプト本体で

require 'webdrivers/chromedriver'
require 'watir'

と宣言しましょう。require 'webdrivers/chromedriver' なのは、この gem が ChromeDriver 以外もインストールできるためです。しかし他のドライバを入れる必要は無いので ChromeDriver に限定しておきましょう。

なお heroku で headless Chrome と共に使う場合には Heroku buildpack google chrome の手順を確認しましょう。

Watir関係記事

引用したいWebサイトのURLとタイトルをはてな記法にするbookmarkletを改善した

未だにはてな記法が好き

この別館では Markdown で書いてますが本館では未だはてな記法を使っている @riocampos です。だって十年以上はてな記法はてなダイアリー書いてきたんだし。 で、引用したいサイトのURLとタイトルを取るブックマークレット(旧版)

javascript:window.prompt('','['+%20location.href%20+':title='+%20document.title%20+']');void(0);

を使っておりました。

面倒なタイトルが時々ある

「面倒な」というのは、タイトルのなかに「|(パイプ)」が入っているサイト。はてな記法では「|」が表組みを意味するので、これが入っているとレイアウトが崩れてしまうのです。

いつも書いている「見にいきたい展覧会リスト」のサイトでは、基本的に表組みにリンクを入れているので「|」が入ると表が思いっきり崩れてしまうので、手動で直しておりました。

でもそれって馬鹿げてる。だって正規表現で見つけられるような問題をいちいち手で直してるんだし。なので改善したかったのだけど JavaScript が苦手なので手を付けられずにいました。

が、思い立って今日改善してみました。

ブックマークレットを改善

javascript:void(function(d,w){t=d.title;tr=t.replace(/[ ]*\|[ ]*/g,'%EF%BD%9C');w.prompt('','['+%20location.href%20+':title='+%20tr%20+']')})(document,window);

つまり「|(パイプ)」及びその前後の空白を「%EF%BD%9C(全角のパイプ|)」に置き換えています。

今後は安心

これでいちいち「|」を手動置換するよう気遣ったり、投稿した後にレイアウト崩れに気付いて修正し直したりするストレスから解放される、はずw

HT Recorderの録音ファイルのCompressはどの程度の圧縮か

iPhoneを録音機器として用いるのに必需品となるアプリHT Recorder

iPhone をしばしば録音機器として用いている @riocampos です。といっても音楽のためではなく、会議や講演会などの記録用として使用しています。もちろん Apple 提供のアプリである「ボイスメモ」もあるのですが、私はずーっと HT Recorder を使用しています。というのは、iPhone を使い始めた頃*1にいろいろ試した結果として HT Recorder を使い始め、それからずっと使ってるわけです。特に講演会などのホールでの録音だと、録音レベルが低くなりがちなのですが、 HT Recorder であればそのような心配もなく(ある程度)充分な音量とクリアな音質で聞き返すことができるのです。

開発者サイト:HT Recorder | Applied Voices LLC

App Store リンク:「HT Professional Recorder」をApp Storeで

現時点での価格は1200円*2であり、気軽に買える値段ではありません。ですがそれだけの価値があるアプリです。弱点は使い勝手がさほど良くないこと。でも音質には換えられません。

録音形式はWAVファイル

さて。 HT Recorder の録音形式は昔から変わらず WAV ファイルです。コンピュータでの音楽ファイルとして基本となるファイル形式ですので安心なのですが、いかんせんファイルサイズがとても大きくなります。とはいえモノラルなので20MB/10分ぐらいですが。

なので、録音したまま iPhone に保存したままにしておくと、iPhone の容量をとっても食います。対策としてはもちろん Mac/PC へ iTunes を使って移動させるのが一番です。ただ、聞き直したい場合にはやはり iPhone に残しておく必要があります。

で。HT Recorder には Compress という機能があります。名称通り圧縮機能です。というかやたらデカイWAV形式からm4a形式に変換するだけなんですけどね。圧縮するとファイルサイズ表示の右側に「!」が付きます。なお、復元するための Expand 機能もあります。

どの程度の音質のm4aにしてるのかな?

Compress した後の状況を今回確認してみたので記録しておきます。

FFprobe を使って確認した結果

  • 今年8/31に HT Recorder を使って某所で録音した WAV ファイル(185MB)を FFProbe で確認しました。
    PCM録音で 16KHz、ビットレートは 256kbit/s なので音声用としてはまあまあなのでは(音楽用のアプリじゃないですから)。
Input #0, wav, from '/Users/riocampos/Downloads/HT/Rec_Aug 31, 2019 13_52_01.WAV':
  Duration: 01:36:20.30, bitrate: 256 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, 1 channels, s16, 256 kb/s
  • HT Recorder の Compress で圧縮させた m4a ファイル(18.0MB)を同じく FFProbe で確認しました。WAV に比べてファイルサイズが1/10ぐらいになってます。
    ビットレートは 24kbit/s。
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/riocampos/Downloads/Rec_Aug 31, 2019 13_52_01.m4a':
  Duration: 01:36:20.61, start: 0.132000, bitrate: 24 kb/s
    Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 24 kb/s (default)
  • FFmpeg で何もオプションを付けずに WAV から m4a に変換しました。ファイルサイズは 50.4MB、1/4よりも大きいので、さほど圧縮できた気分になりませんね。
    ビットレートは 69kbit/s。HT Recorder の設定より3倍くらい高め。
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/riocampos/Downloads/HT/Rec_Aug 31, 2019 13_52_01.m4a':
  Duration: 01:36:20.37, start: 0.000000, bitrate: 69 kb/s
    Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 69 kb/s (default)
  • FFmpegビットレートを 24kbit/s に指定して変換しました。つまり ffmpeg -i file.WAV -ab 24k file.m4a としたわけです。その結果、Compress とほぼ同程度の 17.8MB にまで抑えられました。
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/riocampos/Downloads/HT/Rec_Aug 31, 2019 13_52_01__24k.m4a':
  Duration: 01:36:20.37, start: 0.000000, bitrate: 24 kb/s
    Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 24 kb/s (default)

結論:ビットレート 24kbit/s 設定でファイルサイズが 1/10

音質が違うかどうかはあとで確認します(いま聞けない状況なのでw)

*1:iPhone 3GS のころw

*2:昔でも1000円前後してたはず

はてなブログにpdfをobjectタグで埋め込む

原三溪展@横浜美術館の出品リスト(の魚拓)を埋め込む。

<object type="application/pdf" width="600" height="800" data="PDF_URL"></object>

iOS 内蔵ブラウザ( Safari ベース)ではプレビューとしてしか表示されない。のでページがめくれないのが残念。

.oO(ところで。HTML5では(4にあったような)空タグを避ける <ほにゃらら /> 的な記法は無くなったのかねえ)

参考

ffmpegやffprobeの出力にコピーライトやライブラリ情報を含ませない

-hide_banner オプションを追加すればおk。

$ ffmpeg -hide_banner ...
$ ffprobe -hide_banner ...

典拠

-hide_banner

Suppress printing banner.

All FFmpeg tools will normally show a copyright notice, build options and library versions. This option can be used to suppress printing this information.

aliasしておけばいいんじゃね

~/.bashrc に書いておきましょう。私は ffprobe にだけ設定しました。

alias ffmpeg='ffmpeg -hide_banner'
alias ffprobe='ffprobe -hide_banner'

Rubyで末尾に=が付くメソッドは「属性参照」と呼ぶらしい(英語だとAssignment Methods)

のコメントを書いたときに Ruby のリファレンスマニュアルを見直していました。Ruby 的にはどうやら「属性参照」と呼ぶらしいです(仮称のようにも感じますが)。ちなみに英語マニュアルだと Assignment Methods (代入メソッド)でした1

代入

例:

foo.bar = baz

文法:

式`.'識別子 '=' 式

(中略)

属性参照

式1 `.' 識別子 '=' 式2

式 1 を評価して得られるオブジェクトに対して、 識別子= というメソッドを、式 2 を引数にして呼び出します。

例:

class C
  def foo
    @foo
  end
  def foo=( v )
    @foo = v
  end
end
c = C.new
c.foo = 5   # c.foo=( 5 ) のように変換される
p c.foo     # => 5

属性は Module#attr を使って同じように定義できます。

例:

class C
  attr :foo, true
end
c = C.new
c.foo = 5   # c.foo=( 5 ) のように変換される
p c.foo     # => 5

「気になる展覧会」記事の表部分に使ったJavaScriptのメモ

ブログ本館では、3か月毎に以下のような展覧会リストを(自分のために)作っています。

このブログで次のようなことが出来るように JavaScript を書いてみました。

  • 展覧会期間が過ぎた行は非表示にする。
  • 展覧会開始4週間(28日)前及び12週間(96日)前の行は表示を薄くする。
  • 開催中の展覧会の期間部分をボールド且つ背景色をグレーに。
  • 展覧会開始後1週間及び終了前1週間は展覧会名の色を変更して目立たせる。

いままで書いていたはてなダイアリーでは JS が使えなかったので、やりたくても出来なかったのです。

JS を一から書いたのは初めてに近いので、下手くそなのは見逃してください。

const trs = document.querySelectorAll('table > tbody > tr');
const re = /^([\d\/]+)-([\d\/]+)/;
const yyyy = "2019" // 該当する記事の年に変更する
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // 当日真夜中
for (let i=1; i < trs.length; i++) { // i=0 は項目名なので排除
  let tr = trs[i]
  let titleElem = tr.childNodes[1];
  let scheduleElem = tr.childNodes[3];
  let text = scheduleElem.innerText;
  let dates = text.match(re); // dates[1]が期間開始日、dates[2]が期間終了日
  
  // 終了日関係
  let endDateArray = dates[2].split("/");
  let endDate;
  if (endDateArray.length === 2) {
    endDate = new Date(yyyy + "/" + endDateArray.join("/"));
  } else {
    endDate = new Date(endDateArray.join("/"));
  }
  
  let endDateCountFromToday = (endDate - today)/86400/1000
  // 展覧会終了日を過ぎていたら表示しない(visibility:collapse;)
  if (endDateCountFromToday < 0) {
    tr.setAttribute('style', 'display:none;');
    continue;
  } else if (endDateCountFromToday < 7) {
    titleElem.setAttribute('style', 'color:#39f;'); // 終了日7日以内ならばタイトルtitleElemを青色に
  }
  
  // 開始日関係
  let startDateArray = dates[1].split("/");
  let startDate;
  if (startDateArray.length === 2) {
    startDate = new Date(yyyy + "/" + startDateArray.join("/"));
  } else {
    startDate = new Date(startDateArray.join("/"));
  }
  
  let startDateCountFromToday = (startDate - today)/86400/1000
  // 展覧会開始日が96日前よりも前だったらopacityをかなり小さくする
  if (startDateCountFromToday > 96) {
    tr.setAttribute('style', 'opacity:0.25;');
    continue;
  }
  // 展覧会開始日が28日前よりも前だったらopacityを小さくする
  if (startDateCountFromToday > 28) {
    tr.setAttribute('style', 'opacity:0.6;');
    continue;
  }
  // 展覧会開始日を過ぎていたら日程部分scheduleElemをボールドに
  if (startDateCountFromToday <= 0) {
    scheduleElem.setAttribute('style', 'background:#eee;font-weight:bold;');
  // 展覧会開始日を過ぎて7日以内ならばタイトルtitleElemを赤色に
    if (startDateCountFromToday > -7 && endDateCountFromToday >= 7) {
      titleElem.setAttribute('style', 'color:#f63;');
    }
    continue;
  }
  // 展覧会開始前3日以内だったらタイトルtitleElemを赤茶色に
  if (startDateCountFromToday <= 3) {
    titleElem.setAttribute('style', 'color:#c42;');
  }
}

もちろんこの JavaScript<script> タグに挟んで記事末尾に入れておくわけです。

参考:HTMLのテーブルの要素を消したり薄くしたりするCSSは(Safari除く) - 別館 子子子子子子(ねこのここねこ)はてブロ部

備忘録なので、誰の参考にもならなくてもいいのです(イイワケ

DRY じゃない部分をそのうち関数にしてみたりしよう(ひとりごと