ストックドッグ

KatoTakahiro。金融系の会社で働くSEが株やPython、その他諸々について書いています。サービスも運営してます→http://fmbrain.work

Yahooファイナンスの株価予想ページをScrapyでクローリング・スクレイピング

目次

本日やること

Yahooファイナンスでは、毎日アナリスト的な人たちが株価予想を行っています。
今回は、そのページをScrapyでクローリングしながら、各アナリストたちの予想をスクレイピングして、ファイルに保存します。

info.finance.yahoo.co.jp


完成予定ファイル

こんな感じのページを…

f:id:doz13189:20170321184350p:plain

こんな感じのファイルにまとめます!

f:id:doz13189:20170321184425p:plain

必要な環境

python3
scrapy
jq
ubuntu(OSは自由)

なぜscrapy?

scrapyはクローリング・スクレイピングを行うためのライブラリです。
ライブラリの記述ルールを覚えてしまえば、とてもシンプルにクローリング・スクレイピングを行うことができます。

分析等を行うには大前提としてデータが必要です。
データは様々なサイトから集めてくると思うのですが、個々のサイトごとにコードを書いていては大変ですし、また管理の手間も増えます。

scrapyでスクレイピングを行えば、トータル的に無駄が省けてハッピーということです。

Python以外にはあまりスクレイピングのためのライブラリはないようなので、scrapyをバンバン使って、無駄という無駄を省きパイソニストのメリットを最大限に活かしましょう!笑

スクレイピングの流れ

スクレイピング対象のサイトのHTML構成を確認。
scrapyでサイトからスクレイピング
以上!!!(めっちゃ簡単)

Scrapyのインストール

pip install scrapy

Scrapyプロジェクトの作成

scrapy startproject mypredict

Ubuntuで言う端末、Macで言うターミナル、Windowsで言うコマンドプロンプトに上記のコードを打ちましょう。

これでScrapyのプロジェクトが作成されます。
このコマンドを打つと、mypredictというファイルが作成されます。
以降、このフォルダの中で作業を行います。

念の為、ファイル構成を確認しておきましょう。

f:id:doz13189:20170321185616p:plain

中には、Scrapyの設定を記述してあるファイルやスクレイピングした内容を検証するためのファイルがありますが、今回は使用しません。

では、mypredictに移動します

cd mypredict

基本的には、作業はこの階層で行います。

Spiderの作成

scrapyでは、スクレイピングをするためのルールをこのspiderに記述します。
そのため、スクレイピングを行うサイトごとにspiderを作成するイメージです。

スクレイピングをするにはサイトごとに異なるページ構成を考慮する必要があります。
class名やid名などサイトによって使用しているものが異なるので、そういったサイトの個別のルールをこのspiderに記述します。
※ページ内容のダウンロード等は他のファイル(すでに用意されている)

まず、spidersフォルダの中にpredict.pyというファイルを作成します。
このファイルがクローリング・スクレイピングするファイルとなります。

今回作成するファイルはこれだけです。
このファイルで全ての処理を行います。
記述するコードも30行にもいきません。

※注意、ファイルを作成するのはspidersの中ですが、作業をするのはあくまでもmypredict直下です。scrapy.cfgがある階層です。

とりあえず、predict.pyというファイルだけ作成して、そのままにしておきます。

スクレイピングするサイトを確認

先ほど貼った画像と同じです。

f:id:doz13189:20170321184350p:plain


この予想一覧を上から順にクローリングしていき、URLをたどっていきます。

最終的には、このページ内にある全ての個別の予想ページの中身の文章をスクレイピングしていきます。

f:id:doz13189:20170321190701p:plain


ここでクローリングとスクレイピングの意味を確認しておきます。

私もそこまではっきりと認識しているわけではなくて、ニュアンスで使っていますが...

クローリングはサイトの情報を閲覧する

スクレイピングは、閲覧している情報をダウンロードしてくること

こんな感じだと思います、以降このような意味でクローリング・スクレイピングという言葉を使っていきます。

スクレイピングはじまるよー

ではまず、予想トップページをスクレイピングしてみましょう。
この予想トップページから個別ページに繋がるURLを拾ってくるのが目的です。
以下のコードを、ちょっと前に作成してほったらかしにしているpredict.pyに記述します。

import scrapy


class PredictSpider(scrapy.Spider):
	#predictはSpiderの名前。spider実行時に入力する。
	name = "predict"

        #必ず必要なコードです
     #相手サーバーに配慮するために、スクレイピングの間隔に1秒入れます
        custom_settings = {
            "DOWNLOAD_DELAY": 1,
        }

	#スクレイピングを行う際に一番最初にクローリングするページ
	start_urls = ["http://info.finance.yahoo.co.jp/kabuyoso/article/"]
	
	def parse(self, response):

		#Google Chromeの検証等でページの構成を確認すると。
		#URLはHTMLのh3タグのクラス st02の下に格納されていることがわかる。
		for href in response.css("h3.st02 a::attr('href')"):
			
			#相対URLから絶対URLに変換
			url = response.urljoin(href.extract())

			#スクレイピングした内容を確認
			print(url)

ちなみに、ページ構成のスクショは以下。

こればっかりはページのHTMLを確認しながら自分で地道にたどっていくしかないです。

f:id:doz13189:20170321190913p:plain


先ほどのコードを実行してみます。

mypredict直下で以下のコードを打ちます。

scrapy crawl predict

こんな感じでURLがリスト形式で表示されれば成功です。

f:id:doz13189:20170321191206p:plain


さて、これでたどるURLを入手することができました。
次にこのURLを辿って、ページの中身をスクレイピングします。
先ほどのコードを少し変更し、さらに個別ページをたどるコードを追加しています。

import scrapy


class PredictSpider(scrapy.Spider):
	name = "predict"

        custom_settings = {
            "DOWNLOAD_DELAY": 1,
        }

	start_urls = ["http://info.finance.yahoo.co.jp/kabuyoso/article/"]

	def parse(self, response):
		for href in response.css("h3.st02 a::attr('href')"):
			url = response.urljoin(href.extract())
			
			#ここから下が追加分
			#スクレイピングしたURLをたどるためにparse_topicsに投げる
			yield scrapy.Request(url, self.parse_topics)


	def parse_topics(self, response):
		#個別ページのHTML構造を確認する
		#h3タグのクラスst02にタイトルが格納されていることがわかる
		title = response.css("h3.st02 ::text").extract_first()

		#本文はdlタグのクラスmarB20に格納されていることがわかる
		#これを::textで抽出するとbrタグも含めまれて上手くスクレイピングできない
		#xpathのstring()を使用すると、うまい具合にスクレイピングすることができる
		body = response.css("dl.marB20").xpath("string()").extract()

		#辞書形式で格納する
		yield {
			"title" : title,
			"body" : body
		}

先ほどと同じように、たどるページ先のHTML構成を確認しておきます。

f:id:doz13189:20170321191511p:plain


さて実行してみます。

Scrapy crawl predict

実行結果はこちらです。

f:id:doz13189:20170321191620p:plain

スクレイピングが成功していたら、何かしらの文字列が表示されると思います。

スクレイピング内容をファイルに保存

とても簡単です。

#-oはファイルに保存する
#predict.json、ここは自由
#保存したいファイル名とファイル形式を指定するだけです
scrapy crawl predict -o predict.json

これだけです。

中身を見てみましょう。

#jqを事前にインストールする必要あり
cat predict.json | jq


実行結果です。

f:id:doz13189:20170321192042p:plain


まとめ
上手くできましたか?
思いの外簡単にスクレイピング出来たと思います。
なんせ、書いたコードは30行に満たない程度ですから。

今回はファイルに保存しましたが、これをデータベースに保存してもOKですし、実際には管理のしやすさ等を考えるとそちらのほうがベターかと思います。

私もまだまだscrapyを触り始めたばかりなので、これから色々と使っていきたいと思います。