ロシアW杯 日本代表について雑談ができる対話エージェントを作る(データ収集編)①

Twitterでは日々幅広い話題に関するやり取りが行われています。

今回、日本代表の試合が行われた日の対話データを手に入れることができたので、このデータを使って日本代表についてのみ雑談ができる対話エージェントを作ってみます。

この記事ではどうやってデータを収集したのかを書いていきます。

環境

MeCabWindowsにインストールするには

https://www.pytry3g.com/entry/2018/04/24/143934#Windows

データを集める

今回、Twitterの対話データを集めるにあたって、こちらをー>(GitHub - higepon/twitter_conversation_crawler: Twitter Conversation Crawler)使わせて頂きました。

TwitterAPIを利用するので、Twitter Application Managementでconsumer_key, consumer_secret, access_token, access_token_secretを取得します。これらの詳細について今回は割愛します。一応説明しているリンクを載せておきます。->(http://www.nltk.org/howto/twitter.html)英語で書かれていますが……

 

APIキーを用意し設定した後、crawler.pyを実行するとツイートを集めることができます。

データの前処理

crawler.pyで日本代表の試合が行われた6/19, 24, 28, 7/2のツイートを集めました。その後、textify.pyを使って対話データに成形しました。その際にURLやハッシュタグを含む対話データは取り除くようにします。

手に入れた対話データは以下のような3つのツイートから構成されています。

  •    ユーザAによるツイート -(1)
  • (1)に対するユーザBのリプライ -(2)
  • (2)に対するユーザAのリプライ -(3)

手に入れた対話データのほとんどはワールドカップとは関係のないものです

そのため、ワールドカップに関するキーワードを含むツイートを探してきます。今回はワールドカップに関するキーワードが2つ以上のツイートに含まれていた場合、それらを対話データとして使うようにします。

そのために、textify.pyを少しいじります。

__init__の変更

import MeCab
import argparse
import re
import sqlite3
import sys


# class to dump conversation as text from db.
class Dumper:
    def __init__(self, db):
        self.db = db
        self.url_regexp = re.compile(r"https?://")
        self.name_regexp = re.compile(r"@([A-Za-z0-9_]+)")
        self.tag_regexp = re.compile(r"#(\w+)") #ハッシュタグを取り除く
        self.cnt = 0 #対話データをカウントする
        self.tagger = MeCab.Tagger("-Owakati") #分かち書き
        # キーワードの設定
        self.keyword = ["本田", "香川", "川島", "大迫", "長友", "長谷部", "乾", "原口",
                        "昌子", "酒井", "柴崎", "西野", "ワールドカップ",
                        "日本", "コロンビア", "セネガル", "ポーランド", "ベルギー"]

is_valid_conversation

ハッシュタグを取り除くところを追加

    def is_valid_conversation(self, text1, text2, text3):
        if text1 is None or text2 is None or text3 is None:
            return False
        # URLを含むツイートは取り除く
        for text in [text1, text2, text3]:
            if re.search(self.url_regexp, text):
                return False
        # ハッシュタグを含むツイートは取り除く
        for text in [text1, text2, text3]:
            if re.search(self.tag_regexp, text):
                return False

        return True

dump

キーワードを含むかどうかを調べるところを追加。

    def dump(self):
        conn = sqlite3.connect(self.db)
        cursor = conn.cursor()

        cursor.execute(
            "select count(*) from conversation")
        total_conversation = cursor.fetchall()[0][0]

        cursor.execute(
            "select sid1, sid2, sid3 from conversation")
        for row in cursor:
            sid1, sid2, sid3 = row
            text1 = self.tweet_text(conn, sid1)
            text2 = self.tweet_text(conn, sid2)
            text3 = self.tweet_text(conn, sid3)
            if self.is_valid_conversation(text1, text2, text3):
                text1, text2, text3 = self.mapper(text1, text2, text3)

                # キーワードを含むか調べる
                if self.is_valid_statement(text1, text2, text3):
                    self.cnt += 1

        conn.close()
        print("Number of total conversation: {}".format(total_conversation))
        print("Number of valid conversation related to World Cup: {}".format(self.cnt))

mapperの変更

    def mapper(self, text1, text2, text3):
        text1 = text1.replace("&gt;", ">").replace("&lt;", "<")
        text2 = text2.replace("&gt;", ">").replace("&lt;", "<")
        text3 = text3.replace("&gt;", ">").replace("&lt;", "<")
        #text2 = re.sub(self.name_regexp, '@john', text2)
        text2 = re.sub(self.name_regexp, '', text2)[1:]
        #text3 = re.sub(self.name_regexp, '@paul', text3)
        text3 = re.sub(self.name_regexp, '', text3)[1:]
        return text1, text2, text3

is_valid_statement

新しく追加。

ワールドカップに関するキーワードが2つ以上のツイートに含まれる場合Trueを返す。

    def tokenizer(self, text):
        return self.tagger.parse(text).strip()

    def is_valid_statement(self, text1, text2, text3):
        text1 = self.tokenizer(text1)
        text2 = self.tokenizer(text2)
        text3 = self.tokenizer(text3)
        flags = [0, 0, 0]
        for word in self.keyword:
            if word in text1.split():
                flags[0] = 1
            elif word in text2.split():
                flags[1] = 1
            elif word in text3.split():
                flags[2] = 1
        #return any(flags)
        return 1 if sum(flags) >= 2 else 0

前処理の結果

3つのツイートから構成する対話データを1としてカウントします。

6/19 日本xコロンビア

手に入れた対話データは全部で11923。

前処理をすると、92。

6/24 日本xセネガル

手に入れた対話データは全部で13672。

前処理をすると、62。

6/28 日本xポーランド

手に入れた対話データは全部で12679。

前処理をすると、122。

7/2 日本xベルギー

手に入れた対話データは全部で8841。

前処理をすると、55。

サンプル

手に入れた対話データのサンプル

ユーザA:セネガルつええ、ボルト三体くらいいるわ笑笑
ユーザB:しょーみコロンビアより強い
ユーザA:それなまちがいないわ

続き

次回、PyTorchを使って対話エージェントを作る予定。