43
53

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.

ScrapyでWebサイトからデータ収集してみた

Posted at

Scrapyを使って基本的なクローリング&スクレイピングを行いました。

作ったもの

以下のアニメ情報まとめサイトから2016年冬のアニメのタイトルと総合得点を取得するScrapyプロジェクト
https://www.anikore.jp/chronicle/2016/winter/

作成手順

プロジェクト作成

https://doc.scrapy.org/en/1.2/intro/tutorial.html
こちらの本家チュートリアルにあるように

% scrapy startproject project_name

というコマンドを任意の場所で実行すればプロジェクトが作成されます。
今回はproject_nameanimeにしました。

Spider作成

続いてプロジェクトのspidersディレクトリにSpider(スクレイパーのこと)となるPythonファイルを作成します。
今回はanime_spider.pyという名前にしました。

完成物は以下のようになります。

anime_spider.py
import scrapy


class AnimeSpider(scrapy.Spider):
    name = "anime"
    start_urls = [
        'https://www.anikore.jp/chronicle/2016/winter/'
    ]

    def parse(self, response):
        for anime in response.css('div.animeSearchResultBody'):
            yield {
                'title': anime.css('span.animeTitle a::text').extract_first(),
                'score': anime.css('span.totalRank::text').extract_first()
            }

        next_page = response.css('a.next::attr(href)').extract_first()
        if next_page is not None:
            next_page = response.urljoin(next_page)
            yield scrapy.Request(next_page, callback=self.parse)

Spiderの名前

name = "anime"

これがSpiderの名前です。
スクレイピングを実行する際にここで宣言した名前を以下のようにして使います。

% scrapy crawl anime

クローリング始点URL

start_urls = [
    'https://www.anikore.jp/chronicle/2016/winter/'
]

これがクローリングの始点となるURLです。
今回は2016年冬アニメの一覧を取得したいので、2016年冬アニメのトップで宣言しています。

スクレイピング

parse( )という関数のなかでスクレイピングとクローリングを行っています。
以下がスクレイピングの部分です。

for anime in response.css('div.animeSearchResultBody'):
    yield {
        'title': anime.css('span.animeTitle a::text').extract_first(),
        'score': anime.css('span.totalRank::text').extract_first()
    }

Scrapyではcssとxpathでデータにアクセスできますが、今回はcssで書きました。

今回のサイトではアニメの説明ごとにanimeSearchResultBodyクラスのdivタグでわけられていたので、以下のようにしてページ内に表示されているすべてのアニメの情報を取得しています。

response.css('div.animeSearchResultBody')

取り出したアニメ情報から更にタイトルと総合評価だけがほしいので以下のように取り出します。

yield {
    'title': anime.css('span.animeTitle a::text').extract_first(),
    'score': anime.css('span.totalRank::text').extract_first()
}

extract_first()は最初の要素を取り出してくれます。

anime.css('span.animeTitle a::text')[0].extract()

として添字でもアクセスできますが、インデックスエラー防止とNoneを返してくれることからこちらを使っています。

クローリング

クローリングは以下の箇所で行っています。

next_page = response.css('a.next::attr(href)').extract_first()
if next_page is not None:
    next_page = response.urljoin(next_page)
    yield scrapy.Request(next_page, callback=self.parse)

次へボタンのhrefの文字列を指定して、次ページのURLを作成しています。
再帰的にparse( )関数を呼ぶことで、次ページがなくなるまで全ページをクローリングすることになります。

実行

最後にプログラムを実行しましょう。
「Spiderの名前」のところでも実行コマンドを紹介しましたが、オプションを加えてjson形式でファイル出力してみます。
プロジェクトディレクトリの下で以下のコマンドを打ちます。

% scrapy crawl anime -o anime.json

2016年冬のアニメのタイトルと総合評価が取得できました。

宣伝

Scrapyについて簡単に説明した動画を配信しました。
こちらではXPathを使ったスクレイピングを行っています。

「Scrapy:WEBページの情報を自動取集!!クローリング&スクレイピングフレームワーク」
https://www.youtube.com/watch?v=Zfcukqxvia0&t=3s

参考文献

https://doc.scrapy.org/en/1.2/intro/tutorial.html
https://ja.wikipedia.org/wiki/ウェブスクレイピング

43
53
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
43
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?