土日の間、止まっていましたスクレイピングの話を続けていきます。
Beautifulsoupを使って本文の取得には成功しましたが、どうも手間が多く便利そうじゃないですね。
調べてみましたが、Scrapyというスクレイピング用フレームワークがあるそうなので、こっちも勉強していきたいと思います。 まずはいつも通り公式のチュートリアルから始めてみます。
Scrapy チュートリアル — Scrapy 1.2.2 ドキュメント
まずはpip installから。
pip install scrapy
インストールしたらバージョンの確認をしてみます。
scrapy --version Scrapy 1.5.1 - no active project
no active projectって出てきました。何も動いてないってことですね。 scarapyはどうやらprojecというもので管理するらしいです。
プロジェクトの作成
プロジェクトはこのコマンドで作るらしいです。
scrapy startproject project_name
実行結果。
New Scrapy project 'tutorial', using template directory '/anaconda/lib/python3.6/site-packages/scrapy/templates/project', created in: /Users/py_sql/tutorial You can start your first spider with: cd tutorial scrapy genspider example example.com
いろいろフォルダができました。tutorialというプロジェクト名で作成すると、tutorialフォルダーの中にもう1つtutorialフォルダーができるので、そこに移動します。それで、さらにspidersというフォルダがあるので、そこに移動します。ここが作業フォルダになるらしいです。
チュートリアルを読んでいくと、ここにサンプルとして[quotes_spider.py]を作成しろっと書いてあるので、そのままコピペします。
import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" def start_requests(self): urls = [ 'http://quotes.toscrape.com/page/1/', 'http://quotes.toscrape.com/page/2/', ] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): page = response.url.split("/")[-2] filename = 'quotes-%s.html' % page with open(filename, 'wb') as f: f.write(response.body) self.log('Saved file %s' % filename)
サンプルコードを上から見ていきます。
- nameというのが、このスパイダーの名前らしいです。nameは必ず一意にしなければならないとのこと。
- start_requestsという関数にスクレイピングしたいurlを記述していくみたいですね。
- paraseは何回か出ていますが、Webページの構成を解析する関数ですね。
サンプルができたら実行してみます。
scrapy crawl quotes #spiderのname
実行結果。
2018-07-30 12:26:58 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', (以下、省略)
tutorialの結果と全然違いますが、ミドルウェアをダウンロードしたみたいですね。 下の方にスクロールしていくと、ファイルらしきものがあります。
2018-07-30 12:30:28 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://quotes.toscrape.com/robots.txt> (referer: None) 2018-07-30 12:30:29 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/2/> (referer: None) 2018-07-30 12:30:29 [quotes] DEBUG: Saved file quotes-2.html 2018-07-30 12:30:29 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
このあたりでスクレイピングしているようです。
一番簡単なデータの取得方法
一番簡単な取得の方法はshell上で行うようです。
scrapy shell 'http://quotes.toscrape.com'
上のコマンドをターミナルに入力すると、シェルが起動します。
実行結果。
[s] view(response) View response in a browser In [1]: In [1]: response.css('title') Out[1]: [<Selector xpath='descendant-or-self::title' data='<title>Quotes to Scrape</title>'>]
ipythonのようなシェルが立ち上がりました。
In [3]: title = quote.css("span.text::text").extract_first() In [4]: title Out[4]: “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”
テキストが取得できました。 この辺りの使い心地はJupyter Notebookとそんなに変わらないですね。
スクレイピングした情報をログに出す方法
今のところそんなに便利そうでもないですが、とりあえず進めていきます。
スクレイピングした情報をログの中に出すには、yieldというものを使うらしいです。 サンプルコードをそのまま貼り付けます。
import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" def start_requests(self): urls = [ 'http://quotes.toscrape.com/page/1/', 'http://quotes.toscrape.com/page/2/', ] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): for quote in response.css('div.quote'): yield { 'text': quote.css('span.text::text').extract_first(), 'author': quote.css('span small::text').extract_first(), 'tags': quote.css('div.tags a.tag::text').extract(), }
parse関数の中に記述されているのが、yieldですね。 次のようにログの中に出ていることが確認できました。
{'text': '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”', 'author': 'Albert Einstein', 'tags': ['change', 'deep-thoughts', 'thinking', 'world']} 2018-07-30 23:27:57 [scrapy.core.scraper] DEBUG: Scraped from <200 http://quotes.toscrape.com/page/1/> {'text': '“It is our choices, Harry, that show what we truly are, far more than our abilities.”', 'author': 'J.K. Rowling', 'tags': ['abilities', 'choices']}
なるほどですね。
json形式で保存する
一番簡単なデータの保存方法がjson形式で保存することらしいです。json形式とは簡単にいうとJavaScriptにある書き方を真似た読みやすいテキストだそうですね。
例を示すとこんな感じだそうです。
{ “AKB”:{ “岡田奈々”:”5位”, "横山由依”:”6位” } }
それで、この形式で保存するのは楽らしく、コマンドだけでいけるらしいです。
scrapy crawl quotes -o quotes.json
実行結果。
[ {"text": "\u201cThe world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.\u201d", "author": "Albert Einstein", "tags": ["change", "deep-thoughts", "thinking", "world"]}, (以下、省略)
このようなjson形式のテキストデータのファイルができました。 長くなってきましたので、明日に続きます。
今日の結果
今日のAKBメンバーによる呟きは32件でした。
画像を見るとやたらと「から」が大きいですね。朝から、台風から、明日から、結構「から」を使う機会が多いんですね。