嘘ニュースジェネレーターを作った話

M2の@marutakuです。この記事は[MYJLab Advent Calendar](https://qiita.com/advent-calendar/2020/myjlab) 23 日目の記事です。前回の記事は、@kanekomによる[Twitch配信アーカイブのコメント流量を可視化してみた](https://qiita.com/kanekom/items/42ed3cd079fa5409ae58)でした。

今回の記事ではgolangでクソアプリを作って発表する予定だったのですが、修論が大炎上してしまったので断念しました。知ってた。
そこで、過去に作った嘘ニュースジェネレーターを紹介したいと思います!

## どんなアプリか
[虚構新聞](https://kyoko-np.net/)がとても面白いので、自動生成してみたい！という安易なモチベーションから作りました。使用するデータは、虚構新聞は時事ネタなどを使ってパロディ(?)記事を書いているので、Yahooニュースに掲載されている現実に起こったニュースを基に嘘ニュースを生成しようと思いました。
文章の生成には、マルコフ連鎖を使用しています。マルコフ連鎖の詳しい解説は、他に詳しい記事がたくさんあるので省略します。マルコフ連鎖を採用した理由としては、意味自体はわけわからないけど、全くもって理解不能な内容ではない文章が生成できるからです。今だったらBERTを使ってみても面白いかもしれないですね。

## クローラ
Yahooニュースから2018年12月のニュースを集めました。作ったのがいかに昔かがわかりますね。
Crawlerのフレームワークには[Scrapy](https://scrapy.org/)を使用しました。Scrapyを使うとスクラッチでクローラのコードを書くのと比較して、面倒臭い処理を書かなくていいというメリットがあり使用しました。
詳しくは[過去に書いた記事](https://qiita.com/marutaku0131/items/3da0b0870cb0a2bd4244)を参考にしていただけると嬉しいです。

以下は、実際に作成したクローラの一部です。

```python
import scrapy
from news.items import NewsIndexItem, NewsDetailItem
from bs4 import BeautifulSoup


class YahooSpider(scrapy.Spider):
    name = 'yahoo'
    allowed_domains = ['yahoo.co.jp']
    start_urls = [
        'https://news.yahoo.co.jp/hl?c=dom',
        'https://news.yahoo.co.jp/hl?c=c_int',
        'https://news.yahoo.co.jp/hl?c=bus',
        'https://news.yahoo.co.jp/hl?c=c_ent',
        'https://news.yahoo.co.jp/hl?c=c_spo',
        'https://news.yahoo.co.jp/hl?c=c_sci',
        'https://news.yahoo.co.jp/hl?c=c_life',
        'https://news.yahoo.co.jp/hl?c=loc'
    ]

    def parse(self, response):
        response = BeautifulSoup(response.text, 'html.parser')
        next_urls = response.select('.epConMore > a')
        for next_url in next_urls:
            yield scrapy.Request(next_url['href'], callback=self.parse_sub_topic_index)

    def parse_sub_topic_index(self, response):
        for content in response.css('li.listFeedWrap'):
            href = content.css('a::attr(href)').extract_first()
            if href:
                yield scrapy.Request(href, callback=self.parse_detail)
        next_page_url = BeautifulSoup(response.text, 'html.parser').select_one('li.next > a')
        if next_page_url:
            print('='*10, next_page_url, '='*30)
            yield scrapy.Request(next_page_url['href'], callback=self.parse_sub_topic_index)

    def parse_detail(self, response):
        response = BeautifulSoup(response.text, 'html.parser')
        content_dom = response.select_one('div#ym_newsarticle')
        title = content_dom.select_one('h1').text
        text = content_dom.select_one('p.ynDetailText').text
        item = NewsDetailItem(
            title=title,
            content=text
        )
        yield item

```

yahoo newsからは、タイトルと本文を取得してきました。

## 実際に生成された文章
マルコフ連鎖のコードはあまりに汚かったので割愛します。許してください。今やるなら[markovify](https://github.com/jsvine/markovify)のような便利なライブラリが存在しているので、そちらを使うと良いと思います。

実際に生成された文章の一例です

**※以下で生成された文章は、現実の人物・事件・団体とは関係ありません。また、書いている人には誰かを中傷するような意図もありません。**

### 例文①
```text
た神奈川に2つ）といったが、24回（ひじあり）で開かれた日は応募者は推定された『この町で開かれた」とコメントでは、こうしたヤンゴン出身の4Kに対応。 <br>
1年の第65回マカオグランプリ連覇を誇った三沢光晴の必殺技クロスアームレインボーにご臨席されるホンダCBR1000RR、CBR1000RR SPは、利便性というところは見物客を集める中、シカゴレッド、ブラック、ホワイトの2人は神社の関係者は「爆破でハッピー」。 <br>
■医薬品不足の改善で高めたという長崎の3Gに変わった変化では他のデバイスへの委託料も増えるだろう。 <br>
入れ歯をお読みいただくには、尖った部分はデモが始まった、醸造所併設のブリューインバーを紹介する「超」の開発に当たった感触が自分にとっても挑戦を受ける意味、僕は常に動いて見せたら、作業療法士が訓練してみようか？花王の担当者はＥＶＩＬのＥＶＩＬ、ＳＡＮＡＤＡ（３）が29日、北朝鮮の田実渉（わたる）頭取だった時期でした。 <br>
最高裁2部作の創作物に替えます」（205 Bleecker店」。 <br>
今平周吾と、環境に来ることに成功した『ボーイフレンド』（邦題未定・日本語版）が取り組んできて、いざ初の頂点を下げた。 <br>
合計で約3週間ぶり。 <br>
第1次官や各国の短編小説「まんぷく」で販売する。 <br>
事務所側に引き渡す予定だ。 <br>
気温はマイナス8・船橋・ダートを問われ死刑を求刑し、薄赤い炎が押し寄せている。 <br>
```

`神社の関係者は「爆破でハッピー」`,
`気温はマイナス8・船橋・ダートを問われ死刑を求刑し、薄赤い炎が押し寄せている。`

神社の関係者が世紀末。何もわからない。

### 例文②

```text
直接呼び出すことが起きる前に、2級牛肉（1）方式の第1四半期には、発症の危険があります。 <br>
46人となりそうだ。 <br>
補助電源は入っており、大阪市内で会見した。 <br>
当初は9月13日に大邱で初めて頒布されたので、日本円で約237GBが5年はそのパワーを与えてくれるだけで、若い男性の印象は「私はお昼寝の時間」（IS）のソウル答礼訪問の機会があまり残っている。 <br>
しかし、今季1番27号（18）は1年目を喫している。 <br>
この際に利用される。 <br>
明らかにしたことだ」と述べた。 <br>
ソンモの思いから企画。 <br>
2010年：憲法裁判所が新しく作ったシエルターで過ごすよ。 <br>
僕は誰も想像できる。 <br>
```

`2010年：憲法裁判所が新しく作ったシエルターで過ごすよ。僕は誰も想像できる`
一体何があったんだ…

### 例文③

```
理由については、その翌朝に計測していた70周年、同29日◇千葉・市原ＧＣ市原Ｃでプロデビューすることでグローバルな旬の新鮮なスタートだった。 <br>
ジョッキーも言って笑わせた。 <br>
2018年9月に対して伸びたが、1分け3敗としたが、実際に行っている。 <br>
リヤタイヤをストップさせること。 <br>
会長業に身を守ってほしい」とアピールしたモデルとして水平対向6気筒が復活できるのだ。 <br>
南側のアンダー部分を担う。 <br>
他の人が占拠する建物では、「HPライフサイクルサービス」といいのでしょうか？ 」などと話した。 <br>
OCRでは、空港と同じ“奉仕者”ことベッキー・リンチ（３）が交通事故総合分析センター（CDC）が出場し、「道」の頭蓋骨が前後にずらす「月経移動」とコメントしないことや、本当は怖い病気ではクルマがあるとの日程で開催された。 <br>
```

`本当は怖い病気ではクルマがある`
?????

## 終わりに
ひとまずマルコフ連鎖で文章を作ることができました。括弧が閉じないなどの問題は多々ありますが、個人的には結構面白い文章が生成されるので満足しています。
暇があれば別の手法で文章の生成をする記事をあげたいと思います。暇があれば。