Scrapyチュートリアル

## はじめに
今回はウェブスクレイピングフレームワークであるScrapyのチュートリアルを実施してみました。
この記事では、Scrapyの基本的な使い方から、実際にデータを抽出するまでの手順を紹介します。

## 概要
ScrapyはPythonでウェブスクレイピングを実現するためのフレームワークです。高速で効率的なウェブクローラーを簡単に作成できるのが特徴です。

本記事では、Scrapyチュートリアルに沿って、ウェブスクレイピングを行います。
https://doc-ja-scrapy.readthedocs.io/ja/latest/intro/tutorial.html#scrapy-tutorial

おおまかな手順は以下の通りです。
1. 環境構築：仮想環境（venv）の作成とScrapyのインストール
1. プロジェクト作成：Scrapyプロジェクトの作成
1. スパイダー（Spider）の作成：データを収集するクローラーの実装
1. クロールの実行：スパイダーを実行してデータを取得

## 前提条件

- Pythonのインストール：仮想環境構築のため

## 環境構築
Pythonの仮想環境を作成します。
```bash
$ python3 -m venv scrapy-env
```

仮想環境を有効化します。

```bash
$ source scrapy-env/bin/activate
```

Scrapyをインストールします。

```bash
(scrapy-env) $ pip install scrapy
```

Scrapyのドキュメントにも、詳細な記載あります。
https://doc-ja-scrapy.readthedocs.io/ja/latest/intro/install.html

## プロジェクト作成

Scrapyのプロジェクトを作成します。

```bash
(scrapy-env) $ scrapy startproject tutorial
```
以下のようにディレクトリが生成されます。
```
tutorial/
    scrapy.cfg            
    tutorial/             
        __init__.py
        items.py          
        middlewares.py    
        pipelines.py      
        settings.py       
        spiders/          
            __init__.py

```

## スパイダー（Spider）の作成
次に、ウェブサイトからデータを抽出するためのスパイダーを作成します。
今回は、名言を集めたサイト「[quotes.toscrape.com](https://quotes.toscrape.com/)」からデータを取得していきます。

`tutorial/spiders/quotes_spider.py`というファイルを作成し、以下のコードを記述します。

```python
import scrapy

class QuotesSpider(scrapy.Spider):
    name = "quotes"

    start_urls = ['http://quotes.toscrape.com/page/1/']

    def parse(self, response):
        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').get(),
                'author': quote.css('span small::text').get(),
                'tags': quote.css('div.tags a.tag::text').getall(),
            }

        next_page = response.css('li.next a::attr(href)').get()
        if next_page is not None:
            yield response.follow(next_page, self.parse)
```
- `name`: スパイダーの識別名。プロジェクト内で一意である必要があります
- `start_urls`: クロールを開始するURLのリスト
- `parse()`: レスポンスを処理するコールバック関数。今回の実装では、一覧ページからデータの抽出と次ページへのリクエストの生成を行っています
- `response.css()`: CSSセレクターを使用してHTML要素を選択します
- `yield`: データやリクエストを返します
- `response.follow()`: 次のページへのリンクをたどるためのリクエストを生成します

Scrapyでは、HTMLから要素を抽出する方法としてCSSセレクター、XPathを使用できます。
本記事では、全体の手順を紹介したいと思い、CSSセレクター、XPathの使い方については紹介しません。
チュートリアルに基本的な書き方の記載がありますので、そちらをご参照いただければと思います。
https://doc-ja-scrapy.readthedocs.io/ja/latest/intro/tutorial.html#extracting-data

## クロールの実行

スパイダーを実行して、データを抽出してみます。
scrapy.cfgがあるルートディレクトリで以下のコマンドを実行します。

```bash
(scrapy-env) $ scrapy crawl quotes -o quotes.json
```

- `-o quotes.json`オプションで、抽出したデータをJSON形式で保存します

### 実行結果
実行後、ルートディレクトリに`quotes.json`というファイルが生成されます。
名言、著者、タグの情報がJSON形式で抽出できました。

```json
[
  {
    "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"]
  },
  {
    "text": "“It is our choices, Harry, that show what we truly are, far more than our abilities.”",
    "author": "J.K. Rowling",
    "tags": ["abilities", "choices"]
  },
  // 以下省略
]
```

## 最後に

今回は、想像していたよりも手軽にウェブスクレイピングを実現できたことに感動したので、Scrapyのチュートリアルについて記事にしました。

スクレイピングをするにあたり、最低限気をつけなければいけないことは以下動画が参考になりました。
https://www.youtube.com/watch?v=bXBa-88BiYA&t=75s

CSSセレクターやXPathの使い方はChatGPTが良い先生になってくれました。