Scrapy でページングをクローリングする

前回は Scrapy の簡単な機能、最低限の実装方法をご紹介しました。

sfujimoto.hatenablog.com

今回はページングへの対応方法をご紹介したいと思います。

前回は当ブログのトップページからエントリタイトルを取得し、表示するという Scrapy の実装をご紹介しました。ただし、あくまでトップページのみでトップページの 6件以外は表示されませんでした。今回はトップページからスクレピングした結果が次のページへのリンクがあり続ける限り、次のページのエントリタイトル一覧を取得し続ける実装方法をご紹介します。この実装方法を覚えることで、次のページに限らず、一覧ページから詳細ページへの深掘りなども実装できることとなります。

今回の目的

  • スクレイピング結果の URL からページを取得することで、動的な複数ページへのクローリング方法を学ぶ
  • 次のページや、一覧ページから詳細ページへのクローリングに対応できるようにする

概要

前回の記事で説明した通り、ページへのアクセスや、アクセス結果の引き渡しは scrapy 側で実装されています。start_urls に URL を書いたら、その URL へアクセスされ、アクセスした結果のレスポンスが parse メソッドの引数に渡されて、実行されます。start_urls に全ての URL を記載しても可能ですが、そんなのはサイトに変更がある度に手動で URL を追加、削除する必要があるため、現実的ではありません。

追加のリクエストは簡単です。parse メソッドから scrapy.Request を返すことで、引き続き リクエストを実行することができます。

試してみた

環境

実装

まずは次のページの URL を取得する XPATH を考えます。はてなブログの次のページの URL は以下となりました。

//div[@id="main-inner"]/div/span/a/@href

この XPATH から取得した URL を scrapy.Request で追加するだけです。

# -*- coding: utf-8 -*-
import scrapy


class TechSpider(scrapy.Spider):
    name = "tech"
    allowed_domains = ["sfujimoto.hatenablog.com"]
    start_urls = ['http://sfujimoto.hatenablog.com/']

    def parse(self, response):
        titles = response.xpath('//article/div/header/h1/a/text()')
        [ print(title) for title in titles.extract() ]
        
        for url in response.xpath('//div[@id="main-inner"]/div/span/a/@href').extract():
            yield scrapy.Request(url)

前回の説明から下2行を追加しただけです。print がリスト内包表記に変わっていることは気にしないでください。

指定した XPATH から次のページの URL を取得し、scrapy.Request の引数に URL を渡すことで、URL へアクセスし、その結果を同じく parse メソッドへ渡してくれます。これにより、次のページのリンクがあり続ける限りはページの取得を続けます。

動作確認

# scrapy runspider --nolog first_scrapy/spiders/tech.py
Elasticsearch をインストールして起動する
Scrapy でクローリング、スクレイピングする
Elasticsearch の概要を調べてみた
AWS CloudFormation
AWS S3
AWS ElasticCache
AWS ELB
「Amazon Web Services徹底活用ガイド」を読みました
脱vSphereClient (Apple信者向け)
AWS AMI
AWS RDS
AWS EC2
Webアプリケーション on EC2 and RDS
Fluentd(インストール編)
CentOS7(ネットワーク編)
Techブログをはじます

まとめ

Scrapy は多機能でクローリング、スクレイピングで想定される実装の多くを Scrapy で吸収してくれるため、実装が少なく済んで助かります。