米津玄師を知らない
米津玄師を知っている。昔ハチだった人だ。
Lemonも、ゴーゴー幽霊船も、Flamingoも、パプリカも知っている。テレビやら店のBGMやらでそこかしこに流れてるやつ。
でも米津玄師を知らない。一曲たりとも、フルで聞いたことがない。サブスクのAmazon Music(Unlimited)に加入している僕にとっての「音楽」とはアマプラで聞ける曲を意味する。サブスクで聞けない米津玄師の曲は、僕にとって幻想上の存在なのだ。馬でも鹿でもなくて麒麟だ。
そりゃSoundCloudなんかを漁ればたぶんフルバージョンがアップロードされてるんだろうけど、絶対に聞きたくない。ネットに上がったフル音源を聞かないためにサブスクに入っているんだから。
サブスクの檻の中にいる限りは完全に安全。一歩でも外に出るとそこは地雷原だ。米津だ。米津が地雷原から笑っている。
Pythonで偶然短歌をやりたくてMecab使って頑張ったけど…
偶然短歌botというのがある。Wikipediaの記事の中から57577になっている部分を取り出し投稿するbotだ。 たとえばこういうの。
フクロウが鳴くと明日は晴れるので洗濯物を干せという意味 #tanka
— 偶然短歌bot (@g57577) December 31, 2014
ウィキペディア日本語版「フクロウ」より http://t.co/Dm1uHcQdzR
良い。 あるいはこういうの。
もしくはこういうの。彼らには襲われている人々を守れるだけの戦力はなく #tanka
— 偶然短歌bot (@g57577) July 8, 2019
ウィキペディア日本語版「ルワンダ虐殺における初期の出来事」より https://t.co/UKUKpcjZNe
研究で、ネコが砂糖に関心を持たないことは示されていた #tanka
— 偶然短歌bot (@g57577) June 21, 2019
ウィキペディア日本語版「ネコ」より https://t.co/L8b5HhUezs
良すぎる……。 こういうのもあった。
同様に、「普通免許」は普通でも免許でもなく、運転免許 #tanka
— 偶然短歌bot (@g57577) June 30, 2019
ウィキペディア日本語版「地学」より https://t.co/JkZWw4wOFn
最高……!Wikipediaのもつ無機質な文体が、短歌という形で取り出されることによって、荒涼とした侘び寂びのようなものを生み出していて心惹かれるかんじ、たまらん。
……同じことを、やりたい。任意のテキストから短歌を探すやつを、作りたい。
詳しくはわからないが、おそらく形態素解析を用いて単語の音数を抽出し、57577になる部分を抜き取っているのだろう。
形態素解析といえば、こないだの記事のはてブコメントで存在を知ったやつだ。日本語を品詞単位で分解するやつ。Pythonでも動くライブラリがあるらしい。
Pythonでできるなら、たぶん、いける。やってみよう。
必要なのはおそらく
のらへんだろう。
MeCabのセットアップ
文の分析には形態素解析エンジンの中で一番メジャーっぽいMeCabを使う。
MeCabの導入までにはこの記事をほぼまんま参考にした。
また、MeCab標準の辞書だと新語に対応できていないとの話だったので、追加辞書「mecab-ipadic-NEologd」を導入した。参考にしたのはこのサイト。これがかなりしんどかった。このためだけにgitとUbuntuを導入した。泣きそうになった。gitの使い方はこれから勉強します。 とりあえずテストでコードを動かしてみる。
import MeCab t = MeCab.Tagger("Ochasen -d neologd") print(t.parse(input(">>")))
こうなった。
なるほど確かに文章が分解できている。この分解の単位を「形態素」と呼ぶらしい。
あとは、各形態素ごとの文字数が取得できればいいわけだ。書くぞ!!!!!!!!
import MeCab import sys def ParseNode(text): p = MeCab.Tagger("-Ochasen -d neologd") p.parse("")#なんか消すとおかしくなるらしい node = p.parseToNode(text) Result = [] Sentence = [] while node: print(node.feature.split(",")) word = dict() word["text"] = node.surface detail = node.feature.split(",") word["hinshi"] = detail[0] if len(detail)>=9: word["Yomi"] = detail[8] word["Length"] = len(detail[8]) else: word["Yomi"] = "*" word["Length"] = 0 node = node.next if detail[0] == "BOS/EOS": if Sentence: Result.append(Sentence) elif word["Yomi"] == "。": Result.append(Sentence) Sentence = [] elif word["hinshi"] == "記号": pass else: Sentence.append(word) if word["Length"] == "*":word["Length"] = 0 print(type(node)) return Result if __name__ == "__main__": t = "".join(sys.stdin.readlines()) result = ParseNode(t) for sentence in result: print("\n".join([str(d) for d in sentence])) print("------------------------------")
書いた。parseToNodeメソッドの仕様がよくわからなかったので手探りで書いたが、どうも以下のようになっているらしい。
- 返り値はnodeというものが連結された状態
- node.surfaceには、単語(形態素)の文字列が入っている
- node.featureには、単語(形態素)の品詞/品詞の細分類(固有名詞など)/さらなる細分類(人名など)/謎の分類(おそらく細分類の備考)/活用形式/活用形/原型/読み仮名/読みの順にカンマ区切りでデータが入っている
- node.nextを代入することで、次の形態素に進める
このnodeデータからとりあえず、文字列/品詞/読み/読みの文字数 の4つを取得してリストにまとめた。上記のコードはそのリストを返す関数。
57577探し
形態素に分解したら、それらが5・7・5・7・7音でつながっている部分を探す。松尾芭蕉もこうやって俳句を作っていたのだと思うと、妙な親近感が湧く。 こういう系のアルゴリズムは色々思いつきそうだが、今回は単純な方法で解決しようと思う。すなわち、あらゆる名詞・動詞・連体詞・副詞から形態素の文字数を数えていき、ちょうどよく57577にマッチしたら短歌とみなす。
コードが汚くて恥ずかしい///
from split_node import ParseNode import MeCab import itertools import sys def FindTanka(text,neologd=False): """ テキストをぶちこむと短歌のリストを返してくれる風流な関数。 """ Nodes = ParseNode(text,neologd=neologd) TankaPoint = (5,12,17,24,31,32) Tankas = [] for sentence in Nodes: l = len(sentence) for n,StartWord in enumerate(sentence): if StartWord["Yomi"] =="*" or\ StartWord["Hinshi"] not in ("名詞","動詞","連体詞","副詞"):continue sound = 0 curpos = n tanka = "" tankalen = 0 while sound<=31 and curpos<l: w = sentence[curpos] #句の始まりが助詞や助動詞でないかどうか if sound in TankaPoint: if w["Hinshi"] not in ("名詞","動詞","連体詞","副詞"): break if w["Yomi"]!="*": tanka += w["Text"] sound += w["Length"] if sound ==TankaPoint[tankalen]: tankalen+=1 if tankalen == 5: Tankas.append(tanka) break curpos+=1 return(Tankas) if __name__ == "__main__": print(FindTanka(wikipedia(input("url:")),neologd = True))
コードは長いが、要するに単語をひとつずつ数えて短歌になっているかどうか調べている。Wikipediaからテキストを抽出する機能もつけた。 これで偶然短歌をぼくも作れるはずだ! とりあえずこのプログラムに青空文庫から「人間失格」をぶちこんだ結果がこれ。 「政党の有名人がこの町に演説に来て自分は下男」 「画家たちは人間という化け物に傷めつけられおびやかされた」あたりは短歌として成り立っていそうだが、その他はどうもしっくりこない。 俳句の終わり際が不自然なので、「体言止め」または「文節の切れ目」で終わっていれば良いはず。
というわけで魔改造した。
明らかに処理に無駄が多い気はするが…
from split_node import ParseNode from getAozora import aozora from getWikipedia import wikipedia import MeCab import itertools import sys import numpy as np import re def readlines(): return " ".join(sys.stdin.readlines()) JIRITSUGO = ( "動詞","形容詞","接続詞", "名詞","副詞","連体詞","感動詞","記号")#自立後のリスト FUZOKUGO = ("助詞","助動詞") def FindTanka(text,neologd=False): """ テキストをぶちこむと短歌のリストを返してくれる風流な関数。 """ text = re.sub(" "," ",re.sub(r"\r"," ",text)) Nodes = ParseNode(text,neologd=neologd) Tankalist = (5,7,5,7,7)#ここのタプルをいじると自由に検出が変更可能 TankaPoint = np.cumsum(Tankalist+(1,)) Tankas = [] for sentence in Nodes: l = len(sentence) for n,StartWord in enumerate(sentence): if StartWord["Yomi"] in("*","、") or StartWord["Hinshi"] in FUZOKUGO: continue sound = 0 curpos = n tanka = "" tankalen = 0 while sound<=TankaPoint[-1] and curpos<l: w = sentence[curpos] if w["Hinshi"]=="記号": tanka += w["Text"] curpos += 1 continue #句(57577)の始まりが助詞や助動詞でないかどうか if sound in TankaPoint and tankalen<=4: if w["Hinshi"] in FUZOKUGO: break if w["Yomi"]!="*": tanka += w["Text"] sound += w["Length"] if sound ==TankaPoint[tankalen]: tankalen+=1 if tankalen == len(TankaPoint)-1:#短歌が完成した場合 if (w["Hinshi"] in JIRITSUGO and "連用" not in w["Katsuyo"]) or (curpos<l-1 and sentence[curpos+1]["Hinshi"] in JIRITSUGO): Tankas.append(tanka) break if tankalen == len(TankaPoint):#31文字でうまく終わらなかった場合の安全策 Tankas.append(tanka) break curpos+=1 return(Tankas) if __name__ == "__main__": print(FindTanka(wikipedia(input()),neologd=True))
用言の場合は連用形で終わっているものと、直後にまだ助詞/助動詞が続くものを結果から外した。と同時に、字余りの「57578」を許可した。本当はすべての字余りのパターンを許容したかったのだが、コーディングが地獄すぎるので、違和感が少なそうな最後の字余りだけ対応した。 その結果がこちら。
だいぶ改善した気がする。とりあえず、短歌を抽出する部分はこのアルゴリズムで良さそうだ。
ちなみに、必死こいてインストールしたipadic-neologd(最新辞書)だが、使うと逆に精度が落ちる場合があるらしい。 たとえば本家の
これ。撮影を手掛けたことをきっかけに、氷室京介、布袋寅泰 #tanka
— 偶然短歌bot (@g57577) February 28, 2015
ウィキペディア日本語版「加藤正憲」より http://t.co/MjrgUrgJQr
80年代にBOØWYのプロモーションの写真撮影を手掛けたことをきっかけに、氷室京介、布袋寅泰、吉川晃司、Gackt、スピッツなど多くのアーティスト写真を撮影する
という文章からの抽出なのだが、neologd辞書を採用すると短歌として認識してくれない。原因を調べたところ、neologd辞書は「写真撮影」を1語とみなしているため短歌にしてくれなかった事が判明。検出精度がよすぎても短歌的にはマイナスになることがあるんだなあ。 ただ、追加辞書を使わずプリセットの辞書でやると本家のクローンになっちゃうので、neologdは採用することとした。neologdにしか検出できない単語もあるしね。
Wikipediaのデータ注入
本家よろしく、Wikipediaのデータをコイツに流し込む。Wikipediaはサーバーへの負荷を減らすためにクローリングを禁止しているが、そのかわり全テキストデータをまとめたファイルを公開している。そのサイズじつに10GB。もっと重いかと思ったが、画像がないとこんなもんらしい。
これを展開するプログラムがあったのでこれを入手、ちょっと手を加えてさっきのプログラムに放り込む。
オラ!!!!!!!!!!!!!!!
……
……
……
おわびとおわり
プログラムの効率が悪すぎた上にPythonなどという激遅言語で10GBのデータを処理しようとした結果、何時間立っても終わりませんでした…。とりあえず数時間で打ち切ったやつをここにおいておきます。
数時間動かしたけど、10メガのファイルサイズは余裕でオーバー。
ざっと目を通した限りだけれども、よさげな短歌はこんな感じか。
もう同じ趣旨のボットがあるからね、Twtiterには流しませんよ。
ここまでの4文全部短歌です、あえて言うなら必然短歌?
でも辞世の句が 偶然短歌だったら やだな (自由律俳句)
騎空士もそれ以外もいい加減Yuzu Browserを使ってくれ
みなさん、グラブル、してますか?
僕は3年くらいやってるのにもかかわらず先日やっと十天衆のソーンを取得したばっかり。これは「グラブルをしている」のうちには入らない気がする。1000倍に薄めたカルピスが、もはや水であるのと同じように。
そんなエセ騎空士だが、ソーンの獲得に向けてヘイローやキャンペーンクエストをガン回ししていた時に「Yuzu Browser」という最高のブラウザを見つけた。
これが設定項目が非常に多くて自分の好きなようにカスタマイズできて超絶便利で1、グラブル用・普段遣いともに非常に便利なのだが、あまりにもカスタマイズ性が高すぎて設定が相当難しい。そのためかネット上にユーザーがほっっっとんど見当たらないので、もう自分で記事を書くことにした。
今ではグラブル用ブラウザとしてはSmoozが有名だが、それより使い勝手は良いんじゃないかと思う。
※私はグラブルの運営ではないので、Yuzu BrowserやSmooz等のブラウザの利用がBANの原因になるかどうかはわかりません。指定URLへの遷移や再読込みなど、ブラウザとしてごく一般的な機能しか使っていないのでBANされる理由はないと勝手に思っていますが、もし何らかの被害を負っても当方責任を負えません!!というか僕だってBANが怖い!!!!
Yuzu Browser
Smoozでも同じだが、グラブルを遊ぶにあたって欲しい機能は
- 戻る/進む
- 再読み込み
- (マルチ参戦画面やサポ石選択画面など)指定ページへの移動
の3つだろうか。グラブルだけならこれ以外要らない気もする。 この辺の機能の追加も含めて、使いやすいように改造していこう。
ここからYuzu Browserをインストールして起動したら、以下の画面が出ているはず。
この状態から、快適に使うための初期設定が始まる。設定にあるまじき長さなので、心してついてきてほしい。
URLバーの非表示
グラブルやるなら画面はでっかいほうが良いので、上部にあるURLとかがあるバーを非表示にする。
右下のメニューから
[設定]→
[表示設定]→
[ツールバー設定]→
[URLバー]→
[表示設定]
の、一番上の「表示」のチェックを外す。
おさらい。
[*設定]→[表示設定]→[ツールバー設定]→[URLバー]→[表示設定]→[表示**]のチェックボックスをオフ、だ。
これで画面上部のURLバーが非表示になる。画面はこんな感じ。
広々していて使いやすい。
次は画面下の、戻るとか進むとかのボタンの部分を改造する。ここは完全に自由なので、個人的なオススメの設定を紹介するかたちで。
ちなみに、[ツールバー設定]画面から[カスタムバー]→[位置(縦画面)]をタップして「下部バー(常時表示)」にしておけば、スクロール時に画面下のバーが隠れず、操作が楽になるので是非お試しを。
ツールバーのカスタマイズ
ツールバーと言っておいてアレだが、下部のバーは「カスタムバー」と呼ばれている。ボタンやバーの名前を勘違いすると目的の設定項目へ永遠にたどり着けないスリルがある。バカでかい家電量販店を探索している時みたいな感情を設定画面で得られるブラウザは多分これだけだろう。
さきほど同様右下のメニューから\
[設定]→
[アクション設定]→
[ツールバーボタン設定]→
[カスタムバーボタン]
]
を開くと、こんな設定画面が出る。
おさらい。
[設定]→[アクション設定]→[ツールバーボタン設定]→[カスタムバーボタン]だ。
さっきも書いたけど、これはあくまで僕が使っている設定。可能性は本当に無限大なので、僕の設定をベースにして自分が一番ストレスなく操作できるボタン配置を模索していければそれに越したことはない。
なお今回はやらないが、右下の+ボタンを押せば新しいボタンを追加でき、ボタンの名前の部分を長押しすればボタンを削除できる。右上のそれっぽいマークを押すと並び替えも可能だ。
Smoozっぽい検索ボタン
Smoozの検索ボタンは、タップするだけで新しいタブが開き、入力画面に遷移できる。もちろんYuzuでも同じことができる。
「メインメニューを開く」ボタンの[上スワイプ]に、「検索バーの表示」を割り当てる(とんでもない数の選択項目があるが慌ててはいけない)。さらに歯車のマークを押して「新しいタブで開く」にチェックを入れて[OK]。
この状態で右下のメニューバーを上にフリックすると…
こんなふうに検索画面に推移する。検索結果は新しいタブで開かれるので、衝動的に検索しても「あれ!?今まで開いてたページどこいった!?」とならずに済む。便利。
指定URLを開くボタン
グラブルやるならこのボタンがないとね。
ブックマーク機能をあまり使わないので、ブックマークボタンをマルチの参戦ページへ遷移できるボタンに変える。
マルチバトル募集など、好きなURLをコピーしておいてから設定を始めよう。
[ブックマーク]ボタンから[タップ]を選び、現在設定されている「ブックマーク」からチェックを外したあと「URLを開く」にチェック。入力画面が出るので、好きなURLを入力して[OK]。
これで、ツールバーのボタンをタップするだけで好きなページを開けるようになった。この機能、実際に使ってみるとめっっちゃくちゃ便利なので一度体験してみてほしい。
Smoozにも似た機能はあるが、Yuzu Browserの強みは、動作が軽快なことは勿論、タップ・ロングタップに加えて4方向へのフリックの計6動作にそれぞれ別の操作を割り当てられること。
グラブルやるなら、ヘイロー・キャンペーン・共闘あたりのページが全部一発で開けるのでめちゃくちゃ便利になる。
初期設定でボタンが5つあるので、5×6=30通りもの動作を割り当てられるので、日常でよく使う操作やページはほぼ全部割り当てられるはずだ。
ちなみに僕は「進む」を上フリックで再読み込み、「タブ一覧」を上フリックで新規タブの追加ができるようにしてある。ご参考までに。
ユーザーが増えてほしい
最低限グラブルやブラウジングができるだけの操作方法は紹介したが、Yuzu Browserの深奥はこんなものじゃない。主流ブラウザの条件である広告ブロックやジェスチャーでの操作にももちろん対応しているし、ツールバーを上部に表示したり2段にしたりできる。あとなんか、画面左の方から半円状にバーってメニューを出したりできるらしい。バーって。 この辺はまだ僕も理解しきれていない。
とにかくできることが多いブラウザで、Wikiなんかもあるので自分なりの使い方を編み出してみてほしい。
そしてグラブルに限らず、色々なユーザーに最適な設定方法を見つけ出して共有してほしい。
このブラウザは「ちょっとマイナーなブラウザ」とかで済ませてはいけない代物だと思う。みんなで使い倒して、いい感じの設定を集合知で見つけ出そう。
-
本質:Yuzu Browserは設定項目が多い↩
栄光落札オークションで最高を落札で優勝しよう
謎解き公演「栄光落札オークション」が開催一週間前ということで、テストプレイに行ってきました。端的に感想を書こうと思います。
謎解きの非日常体験を「日常の延長の非日常」と、「現実から切り離された非日常」の2つに
分類するならば、これは120%後者でした。すべてが狂っていました。というか体験通り越して「
Nova1とUnlimited2の2つのレーベルを背負っている以上は難しいんだろうなと思っていましたが、それにしてもぶっ飛んだ難易度でした。それなのに1mmも理不尽じゃないからすごいですよね。
詳しい内容は当日体験してほしいので言いません(し、そのせいでタイトルが抽象的になりました)が、その場にいる全員の「目」が凄かったです。謎を解きまくるプレイヤーはもちろん、過剰な仕事量をひたすらさばくスタッフの方々、そしてそれを部屋のすみっこから見ていたディレクター3のどやさん…。部屋の中にいる全員が、殺気とも絶望とも異なる、ある種の興奮を含んだ狂気に包まれていました。
チケットを入手できた方は期待をマックスまで高めても絶対に裏切らないと思うし、取れなかった方はいつか来るかもしれない再演まで待つ価値があります。そういう公演でした。僕の中では今まで参加した謎解き公演の中で圧倒的満足度ナンバーワンでした。
ちなみにチームメンバーがガチすぎた結果、テストプレイ唯一のクリアチームになりました。いぇいぴーす。
ヒルナンデスが好きだ
最近嫌なニュースが多い。Twitterやネットニュースで嫌という程見ている情報なのに、テレビを付けるとそれをおさらいする羽目になる。誰が好きこのんで殺人犯のプロフィールを知りたがるというんだ。見たところで心に擦り傷がひとつ増えるだけだ。
その点ヒルナンデスはいい。12時から2時までずっと、決して中身のない話が流れ続けている。しかも決して飽きさせないように、小刻みにコーナーを変えながら。
かの番組は視聴者に「視聴」という概念だけを植え付けて跡を一切残さない。
どうかその虚無感を共有させてほしい。
たとえば料理コーナー。「料理の超キホン検定」という題のコーナーで、以下のようなクイズが出される。
お料理をしていても「そう言われるとどうだっけ?」と思う 基本中の基本知識を楽しくクイズで学ぶコーナー! Q1【片栗粉と小麦粉】 ①鶏の唐揚げを、カリッとした食感に揚げたいとき使うのは、 片栗粉である。○か×か? 答え:○ ②あんかけのあんを作るとき、片栗粉がないとき代わりに 水溶き片栗粉でも代用できる。○か×か? 答え:× ③春巻きの皮を巻くとき、ノリ代わりとして使う小麦粉がないとき代わりに 水溶き片栗粉でも代用できる。○か×か? 答え:○ Q2【天ぷら】 アク抜きに関する問題 ①サクサクの衣を作るには・・・Aぬるま湯 B氷水 C常温の水 答え:B.氷水 ②エビに切り込みを入れる場所は・・・A背中 B脇 Cお腹 答え:C.お腹 ③衣をつける前にやると剥がれにくくなるのは・・・ A塩をふる B軽くもむ C小麦粉をまぶす 答え:C.小麦粉をまぶす Q3【家庭の定番料理、何を作っているか答えなさい】 答え:茶碗蒸し Q4【ある食材の調理の様子、何をしているのか答えなさい】 答え:アボカド Q5【ロールキャベツ】 ①肉を包むキャベツは・・・A生のもの B加熱したもの 答え:B.加熱したもの ②タネを包むとき、キャベツの向きは・・・A芯のほうから B葉のほうから 答え:A.芯のほうから ③ロールキャベツの鍋の入れ方は・・・A隙間がないように B間隔を空けて並べる 答え:A.隙間がないように Q6 【煮干しのダシ】 ①3つの間違っている工程は? 行程① 煮干しは頭だけ取り除く 行程②水を沸騰させたところで煮干しを入れる 行程③煮立つとアクが浮いてくるが取り除かずにそのまま煮立ててよい 行程④2分ほど煮立てて、厚めのペーパータオルを敷いたザルなどでダシをこす 答え:①・②・③
以上の6問だ。難易度や、正解/不正解はこの際どうでもいい。クイズとしての価値など、月曜ゲストの藤田ニコルの前には些事だ。僕の心を掴んだのは、このコーナーに30分かけているという事実だ。これ以外の情報は、なにもない。ただ淡々と、キッチンでの収録の様子が放映されている。
たいていのワイドショーの中心企画であるグルメレポも、ヒルナンデスの手にかかればあっという間に虚無に早変わりだ。普通の番組ならVTRでタレントが食レポをして、その中の1つか2つをスタジオにお持ちしました……といった流れだが、ヒルナンデス1は一味違う。
食レポされたスイーツがスタジオに持ち込まれるところまでは同じだが、南原の一行は唐突にあみだくじを始める。なんと「一人だけスイーツの断面を見られない」というルールが存在し、しかもその見られない人物をその場で決めているのだ。
平日の真昼間。裏番組ではニュースに対する行き場のない議論がなされているそのときに、日本テレビは、貴重な貴重な地デジの電波を使ってスイーツを見られない人物を決めている。そこに報道はない。そこに怒りはない。そこに苦しみはない。
ただ、目隠しされる南原清隆とほんの少しのお得情報だけがある。
そういう、味がなくて食感だけがあるような、瞑想にも似た奇妙な浮遊感を伴う情報を目から取り入れているときに、僕の思考は止まり、雑念が消え、自分の心がゆっくり癒やされていくのを感じてしまう。
ヒールナンデスってか。
りょうくんグルメの文体を自動でもとに戻すやつを作りました
りょうくんグルメをご存知だろうか。知らなくても、本人のツイートの雰囲気は料理のレシピなんかで一度は見た文脈のはずだ。
こんなやつ。
「りょうくんグルメ」は文章が情報量に対してやたら長いので、pythonの練習も兼ねてアイデンティティである上から目線の構文を取り去ることにした。逆りょうくんグルメである。まじでこの世の全てのタピオカ好きに教えてあげたいんだが新宿三丁目のceleb縁味には全ての人間を虜にする禁断のオレオミルクフォームがある。
— りょうくんグルメ (@uryo1112) 2019年6月15日
これが濃厚黒糖で超絶美味いからぜひ全国のタピオカ好き、タピオカを愛する者たち、タピオカを憎む者たち、全てのタピオカ関係者に伝われ pic.twitter.com/wnnPvkJ2pr
手順は大雑把に分けて以下の3ステップ。
1. Twitterからりょうくんグルメのツイートをスクレイピングする
2. 取得したツイート文から本質を抽出する
3. 生成した文をTwitterに投稿する
とりあえず、実装が簡単そうな2から作ってみる。
取得したツイート文から本質を抽出
りょうくんグルメのツイートは、そのアイデンティティとも言える独特な言い回しが特徴的。実際のツイートはこんな感じ。
りょうくんグルメ🥞🍽🍓@uryo1112
まじでこの世の全てのお肉好きに教えてあげたいんだが 神保町のグリルグリラーグリレストのランチには全ての人間を虜にする 禁断のローストポークステーキ(¥950)がある。
これが分厚い肉塊で超絶美味いからぜひ全国のお肉好き、 お肉を愛する者たち、お肉を憎む者たち、全てのお肉関係者に伝われ
まじでこの世の全てのプリン好きに教えてあげたいんだが 渋谷のWHITE GLASS COFFEEには全ての人間を虜にする 禁断の濃厚プリンがある。
これがかためのぶるんぶるんで超絶美味いからぜひ全国のプリン好き、 プリンを愛する者たち、プリンを憎む者たち、全てのプリン関係者に伝われ
まじでこの世の全てのタピオカ好きに教えてあげたいんだが浅草の桜っ茶には全ての人間を虜にする禁断のさくらラテがある。
これが優しい甘さで超絶美味いからぜひ全国のタピオカ好き、タピオカを愛する者たち、タピオカを憎む者たち、全てのタピオカ関係者に伝われ
……想像以上にワンパターンだった。たとえば真ん中のプリンの文から要らない情報を消してみよう。
あらら、全部消えちゃった。
……みたいなトンチはともかく、共通と思しき箇所をすべて取り除くと
- プリン(食べ物の種類)
- 渋谷
- WHITE GLASS COFFEE
- 濃厚プリン(商品名)
- かためのぶるんぶるん
だけが残る。なんと「禁断の」は全ツイートで共通であった。禁じすぎである。寛政の改革か?
ちなみに後半の
「全国の〇〇好き、〇〇を愛する者たち…」という部分の〇〇は、最初の文の
「まじでこの世のすべての〇〇好き…」の〇〇と一致している。
というわけで以上の情報を盛り込むと
渋谷のWHITE GLASS COFFEEにある濃厚パフェがかためのぶるんぶるんである
となろう。こういう文章を生成するプログラムを作る。 なお、「美味い」や「オススメ」等の文言は盛り込まず、事実を述べるに留めることとした。 捨象したツイートに釣られて実際に店行って被害を被っても責任は取れないので。
さて、実際にpythonへ起こしていく…といっても、これは正規表現で一発なんじゃないか?
import re import sys def ParseRyoukun(Text): Ryou = re.compile( r"まじでこの世の全ての(.+)好きに教えてあげたいんだが(.+)の(.+)には全ての人間を虜にする\s*禁断の(.+)がある。\s*これが(.+?)[がで(くて)]*超絶美味いからぜひ全国の(.+)好き、(.+)を愛する者たち、(.+)を憎む者たち、全ての(.+)関係者に伝われ(.*)$" )#最後の(.*)はurl等を拾うため m = Ryou.match(Text) if m is None: return("NotGourmet") food,shop_loc,shop_name,menu,reason,*others = [ m.group(i) for i in range(1,9) ] if food in menu: return(f"{shop_loc}の{shop_name}にある{menu}は{reason}である") else: return(f"{shop_loc}の{shop_name}にある{menu}({food})は{reason}である")#商品名から食べ物の種類が分かりづらい時 if __name__ == "__main__": T = "".join(sys.stdin.readlines())#りょうくんグルメのテキスト print(ParseRyoukun(T))
一発だった。
先にあげた例からわかるように、りょうくんグルメには「パフェ」と「濃厚パフェ」のように食べ物の種類と商品名がカブっているツイートと、「タピオカ」と「さくらラテ」のように商品名から食べ物の種類を判断しづらいツイートとがある。そこで、後者の場合は両方を併記するように条件分岐をつけた。
のちにスクレイピングした情報を入力することを踏まえて、抽象化の処理は入出力の処理と切り分けて関数に分ける。ここにりょうくんグルメのツイート文を入力すれば概念を生成してくれるはず。
りょうくんグルメのツイートをスクレイピング
次は1のスクレイピング(webサイトからデータを取ってくること)だ。とはいえ、Twitterのサーバーから直接ツイートを取得しようとすると全ての人間を虜にする禁断の審査を10日以上かけてパスしないといけなくて超絶まずいらしいので、りょうくんグルメのTwilogからデータを取得することにする。Twilogのアカウントがあるわけではないので最新100件のツイートになるが、まあ十分だろう。
探したらBeautifulSoupとかいう良さげなツールがあったので、ツイログからツイートとurlをぶっこ抜いてテキストファイルに保存するプログラムを組んでみる。
import requests from bs4 import BeautifulSoup def GetTwilog(AccountName): url= "https://twilog.org/"+AccountName Twiloghtml = requests.get(url) soup = BeautifulSoup(Twiloghtml.text,"html.parser") Tweets = soup.find_all("article",class_ = "tl-tweet") with open(f"{AccountName}_Tweet.txt",encoding = "utf-8" ,mode = "w") as f: for i in Tweets: url = i.find("p",class_ = "tl-time").find("a").get("href") text = i.find("p",class_ = "tl-text").text f.write(url+"\t"+text+"\n") print("Done") if __name__ == "__main__": GetTwilog(input())
案外普通にできた。IDを入力すれば、こんな感じに任意のユーザーのツイートがurlとともに取得できる。 なお、さっき作ったParseRyoukun関数はライブラリとして利用する都合上、多少手を加えている(ターミナルに出力するのではなく、関数の戻り値でテキストを返すようにした)。
このプログラムを使って、りょうくんグルメのツイート情報をテキストファイルにまとめた。
Twitterへの投稿
あとは作ったファイルから本質を抽出して、それを投稿するだけだ。
…とここで、Twitterにテキストを投稿する方法を探したところ、結局API取得のための審査を通過しなければいけないらしい。しぶしぶ必要事項を色々記入したところ、すぐに通過し、APIの使用許可が降りた。10日かかるとは何だったのか。
無事Twitterへアクセスできるようになったので、こんなコードを書く。
import GetTwilog import Ryoukun import twitter import config import time def main(): ConK,ConSK,AccT,AccST = ( config.CONSUMER_KEY, config.CONSUMER_SECRET, config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET) t = twitter.Twitter( auth=twitter.OAuth( AccT,AccST,ConK,ConSK )) with open("uryo1112_Tweet.txt",encoding = "utf-8",mode = "r") as f: for row in f: url,text = row.split("\t") Essence = Ryoukun.ParseRyoukun(text) print(Essence) if Essence != "NotGourmet": TweetText = (Essence +" " + url) t.statuses.update(status=TweetText) time.sleep(300) print("Done") if __name__=="__main__": main()
完成
あとはコイツを走らせれば、りょうくんグルメからアイデンティティをすべて奪い去った残骸を得ることができるはずだ。楽しみだ。というか実は6時半くらいからもう動かしていて、5分ごとにつぶやく設定にしたので夜2時頃には100個のツイートをつぶやき終わるはず。 リンクはこちらなのでぜひ見てみてください。 設計が不十分で文章になってないツイートがたまにあるけど、初心者が頑張って書いたプログラムということで大目に見てほしい。
↓こんな感じのツイートができました
しかし作ってみて思ったけど、りょうくんグルメはある種のネットの「構文」を狙って生み出して、それを内容変えて何回もバズらせるというめちゃくちゃ難しいことを狙ってやってたんだなあ。
悪目立ちであっても目立てば「りょうくんグルメの構文」ってことが広まるし、インターネットで生きていくのが超絶上手いからぜひ全国のりょうくんグルメ好き、りょうくんグルメを愛する者たち、りょうくんグルメを憎む者たちに伝われ
池の底から金閣寺が浮いてきて、鼻水が伸びて月まで行くという記憶を未知の勢力に植え付けられています
あ、待って閉じないで。ちょっとだけ事情を聞いてほしい。
本を読まなくなって久しい。高校時代までは授業中にスマホをいじるのは流石にヤバかったから、電子辞書に入ってた青空文庫で日本文学を読んだりしていたが、今になってしまえばそんな制約もない。青空文庫じゃなくて現代の小説は何年間読んでないだろうか。というかそもそも140文字以上のまとまった文章を読んでない気がする。
昔は本が好きだった。小学生の頃なんか、年100冊ペースで小説を読んでたんじゃないだろうか。その頃の自分はスマホなんて当然持ってなかったから、本*1くらいしか娯楽がなかったんだろう。あの頃の、穢れのない自分が恋しい。ただ10年も前のことになると、どんな本を読んでたのかは全く思い出せない。人間の記憶ってそんなもんか。
星新一のショートショートとか東野圭吾のミステリー、重松清の少年野球がどうとかいう本を読んだことはぼんやりと覚えているけど、それ以上思い出そうとすると思考に変なノイズが入る。タイトルの通り、「池の底から金閣寺が浮いてきて、鼻水が伸びて月まで行く」本があったような気がして仕方ないのだ。
もっと詳しく言うと、
・たぶんSF
・地元の悪ガキが数十年前に池に金閣を沈め、その起動スイッチを電柱の一番上に取り付ける
・それを起動すると金閣寺が池の底から浮いてくる
・金閣寺の中に入ると、天井には星空が広がっている
・ある一地点に立つと天井の星から汽車が走ってきて出られる
という趣旨。自分で書いていてもマジで意味がわからないが、僕の中の小学生は「これを読んだ」と力説している。金閣を沈めるって何なんだ。冗談じゃない。こんな小説あってたまるか、と思いながらも内なる小学生は更にこんなあらすじの断片を語る。ちなみに内なる小学生はクラスで一番スマブラが強い。ただし街一番とかでは決してない。あくまでそのくらいのスケール感の人生である。
・上記のイベントを経て、主人公とその友達は鼻水が無限に伸びる力を得る
・鼻水を伸ばして月まで行こうとする(動機は不明)が、鼻水が足りないのでホースで水を飲みながら鼻水を伸ばす
・ずっとヘルメットをかぶっていた村長の娘が、実はウサギ型宇宙人だった
以上である。ずっと脳内にこんな詳細不明の記憶がこびりついている側の気持ちになってほしい。迷惑しています。
どうにかこの記憶の正体を明らかにしたいので、ダメ元でググってみる。
三島由紀夫の金閣寺が出てきた。鼻水を無視するとはいい度胸だな
他にも「金閣 鼻水」や「児童SF 鼻水」で検索をかけてみても一向にヒットせず。やっぱり記憶は捏造なのか…?
良さげな掲示板を見つけたが…
この有様。もう30分くらい探してる気がする。
そういえば、あの頃の自分って新しい
ことが大好きだったんだな。小説も映画も「なんか疲れる」っつって敬遠してる今の自分は、小学生時代の僕が羨ましいのかもしれない……
小学生の頃の自分に思いを馳せながらGoogleと格闘することおよそ1時間…
ついに
見つけた!!!!!!!!!!*2
タイトルは『夏休みは、銀河!』。うさぎ星人じゃなくてパンダだったらしい。
少々時間がかかったものの、案外あっさり決着がついてしまった。こんなもんか。
とはいえ本の名前がわかればやることは1つ。
今度図書館行こう。