Scrapy入門（２）

# Scrapy入門（２）

## はじめに

[Scrapy入門（１）](http://qiita.com/checkpoint/items/038b59b29df8e1e384a2)

前回の記事では、Scrapyのはじめの一歩として、簡単なSpiderを作成し、URLの抽出処理を試しました。ScrapyはWebページだけではなく、WebAPIの結果を取得したり、画像のダウンロード処理なども行うことができます。今回はWebAPIを呼び出して結果を保存するSpiderを作成してみましょう。

## Spiderの作成

郵便番号のリストを元に、駅の情報を取得するSpiderを作成します。郵便番号の取得には、HeartRails様の提供しているAPI( http://geoapi.heartrails.com/api.html )を使用します。Spiderは次のようになります。

```get_station_spider.py
# -*- encoding:utf-8 -*-

import json

from scrapy import Spider
from scrapy.http import Request


class GetStationSpider(Spider):
    name = "get_station_spider"
    allowed_domains = ["express.heartrails.com"]
    end_point = "http://geoapi.heartrails.com/api/json?method=getStations&postal=%s"

    custom_settings = {
        "DOWNLOAD_DELAY": 1.5,
    }

    # 郵便番号のリスト（本来はDBなどから取得する）
    postal_list = [
        1080072,
        1050013,
        1350063,
        1020072,
        9012206,
    ]

    # Spiderが起動したら、このメソッドが呼ばれる。APIをコールするためのリクエストを作成する。
    def start_requests(self):
        for postal in self.postal_list:
            url = self.end_point % postal
            yield Request(url, self.parse)

    # ダウンロード完了後に呼ばれるメソッド。レスポンスから情報を抽出し辞書形式で返す
    def parse(self, response):
        response = json.loads(response.body)
        result = response['response']['station'][0]

        yield {
            'postal': result["postal"],
            'name': result["name"],
            'line': result["line"],
            'latitude': result["y"],
            'longitude': result["x"],
            'prev': result['prev'],
            'next': result['next'],
        }
```


## 実行

前回同様、Scrapy付属のコマンドを利用してクロールを実行します。
-oオプションを使用し、stations.jsonにクロール結果を出力します。

```shell
scrapy runspider get_station_spider.py -o stations.json
```

## 結果

```json
[
  {
    "prev": "\u767d\u91d1\u53f0",
    "name": "\u767d\u91d1\u9ad8\u8f2a",
    "longitude": 139.734286,
    "next": "\u4e09\u7530",
    "latitude": 35.643147,
    "line": "\u90fd\u55b6\u4e09\u7530\u7dda",
    "postal": "1080072"
  },
  {
    "prev": null,
    "name": "\u30e2\u30ce\u30ec\u30fc\u30eb\u6d5c\u677e\u753a",
    "longitude": 139.75667,
    "next": "\u5929\u738b\u6d32\u30a2\u30a4\u30eb",
    "latitude": 35.655746,
    "line": "\u6771\u4eac\u30e2\u30ce\u30ec\u30fc\u30eb\u7fbd\u7530\u7dda",
    "postal": "1050013"
  },
  {
    "prev": "\u9752\u6d77",
    "name": "\u56fd\u969b\u5c55\u793a\u5834\u6b63\u9580",
    "longitude": 139.7913,
    "next": "\u6709\u660e",
    "latitude": 35.630212,
    "line": "\u65b0\u4ea4\u901a\u3086\u308a\u304b\u3082\u3081",
    "postal": "1350063"
  },
  {
    "prev": "\u795e\u697d\u5742",
    "name": "\u98ef\u7530\u6a4b",
    "longitude": 139.746657,
    "next": "\u4e5d\u6bb5\u4e0b",
    "latitude": 35.701332,
    "line": "\u6771\u4eac\u30e1\u30c8\u30ed\u6771\u897f\u7dda",
    "postal": "1020072"
  },
  {
    "prev": "\u5e02\u7acb\u75c5\u9662\u524d",
    "name": "\u5100\u4fdd",
    "longitude": 127.719295,
    "next": "\u9996\u91cc",
    "latitude": 26.224491,
    "line": "\u6c96\u7e04\u3086\u3044\u30ec\u30fc\u30eb",
    "postal": "9030821"
  }
]
```

## 終わりに

Scrapyを使用すれば、WebAPIの呼び出しから実行結果の保存まで、とても簡単に記述することができます。開発者はフレームワーク側から呼び出されるクラス、関数を作成していけば良いのでより本質的な部分に集中して開発する事が可能です。次回は画像ファイルのダウンロード処理を取り上げます。お楽しみに！