#自己紹介
どうもこんにちは、ネプソンこと杉山航です。
N高等学校通学コースプログラミングクラス所属の2年生(N高3期生)です
各種リンク貼っておきます。
普段は機械学習を使った自然言語処理を主に開発しています
#まえがき
#作ったもの(制作途中)
タイトルの通り、TwitterのTweetをスクレイピングで取得し、人工知能に学習させ、青空文庫に掲載されている作家との類似度を出力するプログラムです。
##実行環境
Mac OS High Sierra
Python==3.6
gensim==3.5.0
beautifulsoup4==4.6.3
requests==2.19.1
mecab-python3==0.996.1
記入漏れがあった場合コメントをくださいると幸いです。
##Tweetを取得
Tweetの取得にはBeautifulSoup4
とRepuests
いうPythonの外部ライブラリを使用し、スクレイピングを行いました。
GitHubに載っているコードでは、同時に分かち書きを行い、のちに学習しやすいようcorpusというtxtファイルの一行目に追加してくれています。
こちらがツイートを取得し、テキストファイルに書き込むだけの単純なコードです。
import requests
import bs4
import re
import MeCab #学習させるための魔法
import sys
userurl = 'https://twitter.com/TWITTERID'#ツイートを取得したいユーザーのID
html = requests.get(userurl)
if html.status_code == 404:
print('ユーザーがいません')
exit()
soup = bs4.BeautifulSoup(html.text, 'html.parser')
tweets = soup.select('.js-stream-item')
result = ""
for n,l in enumerate(tweets):
print(l.p.text)
result += str(l.p.text)
result = re.sub(r'\r','',result) #のちに説明(Doc2Vecの仕様上)
result = re.sub(r'\n','',result) #のちに説明(Doc2Vecの仕様上)
corpus = m.parse(result) #学習させるための魔法
with open("tweet.txt", "w") as f:
f.write(result)
変数userurl
を変えなきゃいけないのが億劫なので
userurl = 'https://twitter.com/%s' % input('input user id => ')
こんな感じにしても良いでしょう。
###コードの説明
変数html
にはTwitterのユーザーページのhtmlが入っています。
次の行のif文
では、ユーザーが存在していない時の処理をしています(ここではそのまま処理を終了させています)
変数soup
に関してはこれを呼んでみたら良いかも知れません。
あとはツイートを取得して変数に代入しています。
##テキストマイニング(もどき)とファイル管理
ツイートの取得が終わったら、青空文庫のtxtファイルを持ってきて、学習させられる状態にしましょう。
import os
import shutil
import MeCab
import sys
import re
m = MeCab.Tagger("-Owakati")
sys.path.append("/.pyenv/versions/anaconda3-4.3.1/envs/word2vec/lib/python3.6/site-packages")
path = os.getcwd()
path += "/data"#あらかじめ"data"という名前のディレクトリが必要
files = os.listdir(path)
print(files)
files.pop(0) #.DS_Storeを削除
corpus = ""
for i in files:
print(str(i))
if str(i[-4:]) == ".txt":
with open("data/"+str(i)+"","rb") as f:
binarydata = f.read()
text = binarydata.decode('shift_jis')
# ルビ、注釈などの除去
text = re.split(r'\-{5,}', text)[2]
text = re.split(r'底本:', text)[0]
text = re.sub(r'《.+?》', '', text)
text = re.sub(r'[#.+?]', '', text)
text = re.sub(r'「','',text)
text = re.sub(r'」','',text)
text = re.sub(r'、','',text)
text = re.sub(r'。','',text)
text = re.sub(r'?','',text)
text = re.sub(r'!','',text)
text = re.sub(r'…','',text)
text = re.sub(r'(','',text)
text = re.sub(r')','',text)
text = re.sub(r'\n','',text)
text = re.sub(r'\r','',text)
newpath = path + "/" + re.sub(r'.txt','',str(i))
if os.path.exists(newpath) == False:
os.mkdir(newpath)
if os.path.exists(newpath+".txt") == True:
print("dataディレクトリを整理します")
shutil.move(newpath+".txt", newpath)
result = ""
with open(""+str(newpath) + "/wakachi.txt", "w") as g:
text1 = text.splitlines()
for t in text1:
result += m.parse(t)
print("nowrodding... "+str(i)+"")
g.write(str(result)) # skip first \s
corpus += result
if corpus != "":
with open("corpus.txt","a") as f:
f.write(corpus)
else :
print("新しいデータはありません")#新しく読み込んだファイルがなければそのまま終了
あらかじめdata
ディレクトリにtxtファイルを入れておき、正規表現を使ってtxtファイルのみを検出し記号などを除外して新しいファイルを作る+全体コーパスファイルへの書き込みをしています。
改行文字を除外しているのは、Doc2Vecの仕様らしいです。
##いよいよ学習
gensim
というライブラリを使うと本当に簡単に実装できます!
#coding: UTF-8
from gensim.models.doc2vec import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
f = open('corpus.txt','r')
trainings = [TaggedDocument(words = data.split(),tags = [i]) for i,data in enumerate(f)]
#print(trainings)
print("学習中")
m = Doc2Vec(documents= trainings, dm = 1, vector_size=300, window=8, min_count=10, workers=4)
print("保存中")
m.save("model/doc2vec.model")
print(m.docvecs.most_similar(0))
これだけです!
最初に文章毎(行毎)にリストへ格納し、それぞれをベクトル上に配置している感じです。
#これから
今あるコードに関しては、まだまだ自動化できるところがありそうなので人の手がほとんど触れなくてもenterキーを押したら結果まで出力してくれるレベルまで行こうと思っています。
そして今後はwebアプリ化をしてリリースを目指します。
#まとめ
期日ギリギリになってしまいましたが、このアドベントカレンダーがなかったら僕のような人間だと絶対的に今回のこのプロジェクトの技術的アウトプットをしなかったと思っています。
Qiitaさんと、N高等学校さんに感謝しています。
僕自身もっとポエムろうとか、細かく書きたかったのかも知れませんが、明日もお楽しみに。