17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NucoAdvent Calendar 2017

Day 5

scrapyを使用してyahoo知恵袋からデータを収集してみた

Last updated at Posted at 2017-12-05

Nuco Advent Calendar 5日目の記事です。

今回はDeepLearningの自然言語処理において、会話応答できるものを作成した際の、会話データ収集方法を記事にしました。

#概要
まず、会話応答するものを作ろうとすると、大量の会話データが必要です。
どのくらいのデータが必要かというと最低限100万程度の会話データセットが必要かと思います。
(もちろん多ければ多いほど良)
ただ、会話データって探しても全然ないんですね。
友達とのLINE会話を使おうともしましたが、全然足らず。。。

ということでyahoo知恵袋から「質問」と「ベストアンサー」のセットをクローリングして収集することにしました。
これを一問一答の会話として学習させてみようとなったわけです。

#scrapyを使ってみる
###pipでインストール

$ pip install scrapy

###プロジェクト作成

$ scrapy startproject scrapy(任意のプロジェクト名)

そうすると下記のようなフォルダ、ファイルが自動で生成されます。

scrapy/
    scrapy.cfg            
    scrapy/             
        __init__.py
        items.py          
        pipelines.py      
        settings.py       
        spiders/          
            __init__.py

###抽出するものの定義
items.pyで何のデータを抽出するかを決めます。
私の場合は下記のようになります。

items.py
import scrapy


class ScrapySchItem(scrapy.Item):
    question = scrapy.Field()
    answer = scrapy.Field()
    url = scrapy.Field()

###スパイダーの作成
スパイダーを作成します。
scrapy genspider [name] [サイトのdomein]

$ scrapy genspider yahoo chiebukuro.yahoo.co.jp

ファイルが生成されます。

scrapy/spiders/yahoo.py
# -*- coding: utf-8 -*-
import scrapy

class YahooSpider(scrapy.Spider):
    name = "yahoo"   
    allowed_domains = ["chiebukuro.yahoo.co.jp"] 
    start_urls = (
        'https://chiebukuro.yahoo.co.jp/'
    )

    def parse(self, response): 
        pass

これを編集していきます。

scrapy/spiders/yahoo.py
# -*- coding: utf-8 -*-
import scrapy
import logging
from scrapy_sch.items import ScrapySchItem


class YahooSpider(scrapy.Spider):
    name = 'yahoo'
    allowed_domains = ['chiebukuro.yahoo.co.jp']
    start_urls = ['https://chiebukuro.yahoo.co.jp/']

    def parse(self, response):
        domein = "https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/" # yahoo知恵袋のトップ画面ではなく、質問、回答があるページの共通URL
        for url in response.css("a::attr('href')").extract():
            if not url.startswith('https://'):
                continue
            if domein not in url:
                yield scrapy.Request(url, callback=self.parse)
            yield scrapy.Request(url, callback=self.parse_dir_contents)

    
    def parse_dir_contents(self, response): # response に、ウェブサイトの情報が入っている
        items = ScrapySchItem() # items.pyで指定したクラス
        items["question"] = ''.join(response.css('div.sttsRslvd div.ptsQes p::text').extract()) # responseのHTMLを辿って欲しい情報を取得する
        items["answer"] = ''.join(response.css('div.mdPstdBA div.ptsQes p::text').extract())
        items['url'] = response.url
        return items
    

#pipelines.pyを編集
yahoo.pyで取得したデータを整え、conversation.txtファイルに書き出します。
今見返すとかなり冗長ですね。

piplines.py
import logging

class ScrapySchPipeline(object):
    def process_item(self, item, spider): #itemに値が入ってます。
        if item['answer'] is None or item['answer'] == '':
            return item
        with open("conversation.txt", "a") as f:
            question = ''.join(item['question'].split('\r\n'))
            question = ''.join(question.split('\n'))
            question = question.replace(' ', '')
            question = question.replace(' ', '')
            question = question.replace('\t', '')

            answer = ''.join(item['answer'].split('\r\n'))
            answer = answer.replace(' ', '')
            answer = answer.replace(' ', '')
            answer = answer.replace('\n', '')
            answer = answer.replace('\t', '')
            logging.debug('hoge %s', answer)
            f.write(question)
            f.write('\n')
            f.write(answer)
            f.write('\n')
            f.write('\n')

            f.close
        return item

#実行
実行してみましょう!

$ scrapy crawl YahooSpider

conversation.txtを見てみましょう。
===
質問
回答
改行
===
で1セットとなってます。

conversation.txt
新潟ジャンプステークス2017に登録しているグッドスカイには、誰が騎乗する予定なのでしょうか。
もりかずまきしゅ。

早速新潟2R、⑮クルクルミラクルの複勝的中しました!武藤は怖いですね(^-^;
馬の仕上がりも良かったですね(ФωФ)ヒモには入れましたが…(꒦໊ྀʚ꒦໊ི)

横山義行はもう復帰は厳しいでしょうか?かれこれ3~4年は騎乗してません。
たまに気になって調べますが音沙汰なし…厳しいでしょうねただ引退したところで何もないし、少ない可能性に賭けるしかないでしょうね…

今日の藤田の勝った後の、戸崎どうですか?教育上とか世知辛いこと言わずに平気でやるのがJRAの太っ腹ですよね!もちろん取りました。Histoirfemme(六枠九番)
その通りですね。JRAは、太っ腹ですね。

トラジさんにリクエストでドスル!アトサキ勝者プレゼント貴方の中での最強馬は何ですか?(日本の馬限定で)私の中での最強馬はシンボリルドルフです良く言われているディープやオルフェは2004年から移住した関係で競馬から離れていたのでタイムリーにレースを見ていませんし生でレースを見たことが無いので評価する事ができないのですこの質問は、さんに回答をリクエストしました。
強いのはディープ二度と現れないのがオルフェのような気がします。=(^.^)=

今週の武豊はどうでしょうか?先週は惨々な結果でしたが。
今回は人気薄の馬ばかりですね。3着以内→3頭で1勝出来ればいいと思います。m(._.)m

例のリクエスト(100%忘れてた甲子園分)リーディング・ジョッキー争い(200勝は微妙)3名が170~180勝のライン辺りでしょうか①戸崎圭太114-81-56-328勝率.197連対率.3373連複率.434②デムーロ104-66-58-202勝率.242連対率.3953連複率.530③ルメール99-81-68-245勝率.201連対率.3653連複率.503大嫌いな戸崎GⅢ4勝のみですねん(笑)デムーロGⅠ2勝GⅡ5勝GⅢ3勝ルメールGⅠ3勝GⅡ3勝GⅢ2勝外国人に捲ってほしい気分・・・この質問は、さんに回答をリクエストしました。
リクエストどうもです。リーディングジョッキー争い極予想1位→戸崎2位→ルメール3位→ミルコミルコはルメールに抜かれると思います。メイン以外の戸崎は強すぎます。(^^;

松田大作はもう燃え尽きてしまいましたか?一時期の勢いが完全に無くなった感があります。
一般企業なら懲戒解雇処分だよね。馬主さんは皆さん企業の代表者だったりするから、企業倫理を重んじる馬主さん主導では騎乗依頼は難しい。ファンも各馬主さん&各陣営も呆れてるから、メインだった西山氏(ニシノ)がどの程度手を差し伸べてくれるか?、、燃え尽き以前に、まず再点火しないとね。

実はこっそりというかなんというか札幌記念の123.13のワイドボックスだけ参考にさせていただきました!ありがとうございます!来週の競馬も予想お願いします!この質問は、さんに回答をリクエストしました。
お疲れ様てす、リクエストありがとうございます。ワイド的中、おめでとうございました。(^^)予想はしますが…来週はハズレますよ(笑)来週の競馬もお互いに頑張りましょう〜!(__).。o○

本日の競馬成績は?
撃沈でした。。_(:3」∠)_

上記のようなもので200万行程書き込むことができました。

使えるのかコレ。。。

#感想
結果的には長すぎる文章も多々あり、うまく学習はできませんでしたが、良い経験になりました。

良い日本語会話データセットどこかにないかな。。。

以上、ありがとうございました。

17
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?