第32回シェル芸勉強会 Q6 の解答

前置き

今日は第32回シェル芸勉強会のQ6です。

第32回シェル芸勉強会の問題は次のURLにあります。
【問題のみ】jus共催 第32回全くインスタ映えしないシェル芸勉強会 | 上田ブログ

思考を忠実にアウトプットすることを目標にしています。

Q6 問題(上記URLからコピー)

ツイッターの特定のアカウントについて、つぶやきがあるたびに「んほぉ!」と端末に表示するワンライナーを書いてください。

問題を見た感想・補足

ひどい。

解答1

yes 'curl -s https://twitter.com/nogiro_iota | grep nogiro_iota/status | sed 3\!d' | sh | awk 'NR!=1&&p!=$0{print "んほぉ!";fflush()}{p=$0}'

解説

まずツイッターを見たらどうなるか知らないと話にならないので、curlwgetで雑に取得します。(結果は長すぎるのでここには記載しません。)

curl -s https://twitter.com/nogiro_iota | less

眺めていると、 <user id>/status/grepすると、ツイートのIDを含む文字列が拾って来れそうです。

$ curl -s https://twitter.com/nogiro_iota  | grep nogiro_iota/status | head -n 3
data-permalink-path="/nogiro_iota/status/873701498311516160"
  <a href="/nogiro_iota/status/873701498311516160" class="tweet-timestamp js-permalink js-nav js-tooltip" title="17:40 - 2017年6月10日"  data-conversation-id="873701498311516160"><span class="_timestamp js-short-timestamp " data-aria-label-part="last" data-time="1497141644" data-time-ms="1497141644000" data-long-form="true">6月11日</span></a>
data-permalink-path="/nogiro_iota/status/939747564152168450"

上記は、3行だけ抜き出していますが、data-permalink-pathで始まる行と、ツイート時刻を表示する行との2列になっています。

最新のツイートIDがわかれば、ツイートがあったかはわかるので3行目を抜き出します。
なぜ3行目かと言うと、ツイートを固定していると、1つ目のツイートは新規ツイートがあっても更新されないからです。
現にツイートを固定している私のアカウントだと、(先程から気になっている方もおられるかも知れませんが、)1行目のIDは873701498311516160で、2行目は939747564152168450になっていて、最初に表示されるツイートはだいぶ前のものです。

$ curl -s https://twitter.com/nogiro_iota | grep nogiro_iota/status | sed 3\!d
data-permalink-path="/nogiro_iota/status/939747564152168450"

あとは、定期的にアクセスして、取得されたものが変わったときに出力します。

yes 'curl -s https://twitter.com/nogiro_iota | grep nogiro_iota/status | sed 3\!d' | sh | awk 'NR!=1&&p!=$0{print "んほぉ!";fflush()}{p=$0}'

f:id:nogiro_iota:20171211010331p:plain

上記は、これまでのコマンドを伝家の宝刀yesで大量に作って実行(sh)し、awkで結果が異なっているかを判定しています。
(結果が異なっていることの判定にuniqが使えるか昔試しましたが、パイプを繋ぐとバッファリングされて、無効化する方法がわからなかったです。。。)

まとめ

HTMLを拾ってきて、変更を検知するワンライナーを作りました。
変更検知はワンライナーでは難しいとなんとなく思っていますが、yes 'commend' | sh | awk 'p!=$0{print}{p=$0}' で検知できます(最近のマイブーム)。

感想

簡易Webスクレイピング
たぶんリツイートには反応しない。