開け閉め

力強く閉めると反動で数センチ開く

りょうくんグルメの文体を自動でもとに戻すやつを作りました

りょうくんグルメをご存知だろうか。知らなくても、本人のツイートの雰囲気は料理のレシピなんかで一度は見た文脈のはずだ。 こんなやつ。

「りょうくんグルメ」は文章が情報量に対してやたら長いので、pythonの練習も兼ねてアイデンティティである上から目線の構文を取り去ることにした。逆りょうくんグルメである。
手順は大雑把に分けて以下の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個のツイートをつぶやき終わるはず。 リンクはこちらなのでぜひ見てみてください。 設計が不十分で文章になってないツイートがたまにあるけど、初心者が頑張って書いたプログラムということで大目に見てほしい。

↓こんな感じのツイートができました

しかし作ってみて思ったけど、りょうくんグルメはある種のネットの「構文」を狙って生み出して、それを内容変えて何回もバズらせるというめちゃくちゃ難しいことを狙ってやってたんだなあ。
悪目立ちであっても目立てば「りょうくんグルメの構文」ってことが広まるし、インターネットで生きていくのが超絶上手いからぜひ全国のりょうくんグルメ好き、りょうくんグルメを愛する者たち、りょうくんグルメを憎む者たちに伝われ