Apify + GPTでのノーコードスクレイピングが最高すぎた

## Apifyとは

Webサイトのスクレイピングを行うSaaSです。
スクレイピングをするSaaSというと、[Octparse](https://www.octoparse.jp)などのGUIでスクレイピングの指示を設定するサービスを思い浮かべる方もいらっしゃるかと思いますが、ApifyはスクレイピングするコードをApifyのプラットフォーム上にデプロイして実行する方式という点で他のサービスとは一線を画します。

詳しくは[公式ページ](https://apify.com/)をご覧ください。

## 何が最高なのか

### GPTの力でノーコードでスクレイピングが可能

ApifyではスクレイピングをするコードをActorと呼びますが、ActorはStoreに公開することができ、公開されたActorを利用することも可能です。
Storeには特定の目的に沿ったActorや汎用的に使えるActorが公開されており、それらをうまく利用すれば、**なんと自分でコードを書かなくても設定値を変更するだけでノーコードでスクレイピングが実行できてしまいます。**

特に個人的に刺さったのは[GPT Scraper](https://apify.com/drobnikj/extended-gpt-scraper) というOpenAIのGPTを利用してスクレイピングするActorで、どういう情報を取得しどんなフォーマットで保存するかを文章で設定するだけでスクレイピングできてしまいます。
これを使うと**もはやCSSセレクターすら要らないスクレイピングの世界線になってくるので、大変重宝しそうです。**(ただし、OpenAIのAPI使用料金がかかります。)

### 無料プランでも利用可能

Apifyは従量課金制で毎月\\$5まで無料で利用可能です。(2023年7月時点)
課金はCPUやメモリーなどのコンピューティングリソースをどれくらい利用したかで変動するため、一概にどれくらいまで無料で利用可能かを言うことはできませんが、自分が試したところだと大体1ページのスクレイピングに\\$0.005 ~ \\$0.01ほどの使用量でしたので、500~1000ページ程度は無料でスクレイピングできるのではないかと思います。

有料プランも最低で$49(月課金)からなので、他サービスと比べても非常に安いです。
https://apify.com/pricing

### スケジューリング機能なども無料プランで利用可能

無料プランと有料プランの間に機能的な差がほとんどなく、スケジューリング機能やチーム管理、通知、監視機能などが無料プランでも利用可能です。

スクレイピングのスケジューリングが無料プランでできるサービスは私の知る限り他になかったので、これはかなり大きいと感じています。

## [GPT Scraper](https://apify.com/drobnikj/extended-gpt-scraper)のチュートリアル

Apifyスゴイと言いたいだけの記事なので言いたいことは言い終わってしまいましたが、せっかくなのでGPT Scraperでノーコードでのスクレイピング例を一つ説明します。
他社様のWebページを大っぴらにスクレイピングするのも忍びないので、自社サービスのサイトをスクレイピングするとします。

https://tour.bushikaku.net/

以下の画像の箇所の情報を抽出してみます。
![](https://storage.googleapis.com/zenn-user-upload/81dadac04edf-20230725.png)

### 事前準備

1. Apifyにアカウント登録
2. OpenAIのAPI Keyを取得 (**OpenAIのAPIは無料枠なしの従量課金なのでご注意ください。**)

### Apifyコンソール画面でActorを設定

#### 1. Storeから Extended GPT Scraper を選択

GPT Scraperでもいいですが、こちらはOpenAIの料金もバンドルされたものですので、こちらを選んだ場合はOpenAIのAPI Keyは不要になります。

![](https://storage.googleapis.com/zenn-user-upload/8c33f6824389-20230725.png)

#### 2. Start URLs、OpenAI API key、Instructions for GPTを設定

Start URLsはスクレイピング対象のURLです。(複数指定可能)

Instructions for GPTはスクレイピングの指示を文章で入力します。今回は後述のように指定したJSON schemaに従って情報を抽出して欲しいので、ここでは概要のみ入力しています。

GPT Modelは当たり前ですがGPT-4の方が精度高いです。(コストは上がります)

![](https://storage.googleapis.com/zenn-user-upload/f6ee5528925f-20230725.png)

#### 3. Formatted Outputを入力

JSON Schemaで抽出したい項目と出力のフォーマットを指定します。

![](https://storage.googleapis.com/zenn-user-upload/129592414d31-20230725.png)

- 全体のJSON Schema
```json
{
  "type": "object",
  "properties": {
    "tour_title": {
      "type": "string",
      "description": "ツアーのタイトル"
    },
    "price": {
      "type": "string",
      "description": "大人１名あたりの価格(料金に幅がある場合は最低価格と最高価格それぞれ"
    },
    "number_of_nights": {
      "type": "string",
      "description": "旅行日数(n泊m日のフォーマットで)。日帰りの場合は「0泊1日」"
    },
    "departure_prefecture": {
      "type": "string",
      "description": "出発地の都道府県"
    },
    "departure_area": {
      "type": "string",
      "description": "出発地の地域名"
    },
    "destination_prefecture": {
      "type": "string",
      "description": "目的地の都道府県"
    },
    "breakfast_count": {
      "type": "string",
      "description": "朝食回数"
    },
    "lunch_count": {
      "type": "string",
      "description": "昼食回数"
    },
    "dinner_count": {
      "type": "string",
      "description": "夕食回数"
    },
    "has_guide": {
      "type": "boolean",
      "description": "添乗員同行か否か (表示がない場合はfalse)"
    },
    "no_registration": {
      "type": "boolean",
      "description": "会員登録不要か否か (表示がない場合はfalse)"
    },
    "single_participation": {
      "type": "boolean",
      "description": "1人参加可能か否か (表示がない場合はfalse)"
    },
    "card_payment": {
      "type": "boolean",
      "description": "カード決済可能か否か (表示がない場合はfalse)"
    }
  },
  "required": [
    "tour_title",
    "price",
    "number_of_nights",
    "departure_prefecture",
    "departure_area",
    "destination_prefecture",
    "breakfast_count",
    "lunch_count",
    "dinner_count"
  ]
}
```


### スクレイピング開始して結果を確認

「Start」を押せば早速スクレイピングが開始されます。
「Runs」の画面で出力結果やかかったコストを確認できます。

![](https://storage.googleapis.com/zenn-user-upload/ab18b525bd4a-20230725.png)

- 出力結果
```json
{
  "tour_title": "【新宿発★好評につき全日程催行確定（8/25から9/30まで毎日設定）】高級ぶどうの王様「シャインマスカット」狩り食べ放題に標高2400mの絶景「富士山五合目」を散策♪幻想的な天然記念物「鳴沢氷穴」も体験できる日帰りバスツアー",
  "price": "6,500円〜7,980円",
  "number_of_nights": "0泊1日",
  "departure_prefecture": "東京",
  "departure_area": "新宿",
  "destination_prefecture": "山梨",
  "breakfast_count": "0回",
  "lunch_count": "0回",
  "dinner_count": "0回",
  "has_guide": true,
  "no_registration": true,
  "single_participation": true,
  "card_payment": true
}
```

ちゃんと取れていそうですね。

## その他

今回は1ページのみのスクレイピング例だけですが、複数ページのURLを指定することもできますし、指定した階層まで自動でクローリングさせることもできてしまいます。

また、既存のActorがニーズに合わない場合はカスタマイズしたり自前のActorを作成することもできます。

他にもIPローテーションしたり、データストアに保存した前回のスクレイピング結果を参照したりなど、語りきれないほどの機能がAll in Oneになっているサービスなので今後ぜひ活用していきたいと思います。