ChatGPTで雑にスクレイピングスクリプトを作る

# はじめに
この記事は、「静岡 Advent Calendar 2023」の12/6の記事です。

ChatGPTで「こんな活用をしています」みたいなものを紹介します。

# 事例：あるページから市区町村名一覧を取ってくる
例えば、以下のページから、市区町村名を抽出するスクリプトを作ってもらいたいとします。
https://the-issues.jp/politicians/pref/22/

以下の要領で依頼文を書き、調査対象ページのHTMLを添えたプロンプトをChatGPTに投げるだけで、欲しいデータを取ってくるためのスクリプトをこしらえてくれます。
あとは開発者ツールのコンソールにコピペして実行すれば、欲しいデータがコンソールに出力されていきます。

### プロンプト
```
以下のHTMLがあります。これを読み込み、
「沼津市」や「静岡市駿河区」などの市区町村名をピックアップする
スクレイピングJSを書いてほしいです。

（前略）
<body class="amp-dark-mode amp-mode-mouse" style="opacity: 1; visibility: visible; animation: 0s ease 0s 1 normal none running none;">
<div class="contents" style="max-width:500px; margin: auto;">
	<div class="container-fluid" style="max-width:500px; margin: auto;">
（中略）
		<div style="margin:16px;">
			<span><a href="/politicians/prefList">全国</a>  /  静岡県
		</span></div>
		<div>
			<h1>静岡県の政治家を探す - 市区町村を選択</h1>
		</div>
		<div class="municipality-block">
			<span class="municipality-link"><a href="/politicians/pref/22/22203">沼津市  (3) </a> / </span> 
			<span class="municipality-link"><a href="/politicians/pref/22/22102">静岡市駿河区  (2) </a> / </span> 
			<span class="municipality-link"><a href="/politicians/pref/22/22131">浜松市中区  (1) </a> / </span> 
			<span class="municipality-link"><a href="/politicians/pref/22/22132">浜松市東区  (1) </a> / </span> 
			<span class="municipality-link"><a href="/politicians/pref/22/22134">浜松市南区  (1) </a> / </span> 
（中略）
            <span class="municipality-link">森町 (0) / </span> 			
		</div>
	</div>
</div>
</body>
</html>
```
### ChatGPTからの返答
```
このHTMLから市区町村名を抽出するためのJavaScriptスクレイピングコードを作成するには、以下の手順に従います。

DOM要素の選択: まず、市区町村名が含まれる要素を識別します。このHTMLでは、spanタグの中のmunicipality-linkクラスを持つ要素に市区町村名が含まれているようです。

テキストの抽出: 次に、これらの要素からテキストを抽出します。

データの整形: 抽出されたテキストから、市区町村名のみを切り出します。これには、テキストの整形や不要な部分の削除が必要になるかもしれません。

以下に、これらの手順に基づいたJavaScriptコードの例を示します。
```

```javascript
// DOMから市区町村名を含む要素を全て選択
const municipalityElements = document.querySelectorAll('.municipality-link');

// 市区町村名を格納する配列
const municipalityNames = [];

// 各要素から市区町村名を抽出して配列に追加
municipalityElements.forEach(element => {
    // テキストから市区町村名を抽出
    const name = element.textContent.trim().split(" ")[0];
    municipalityNames.push(name);
});

// 結果の表示
console.log(municipalityNames);
```

```
このコードは、指定されたクラスを持つ全ての要素からテキストを取得し、
市区町村名を抽出して配列に格納します。最終的に、この配列が市区町村名のリストとなります。
また、.split(" ")[0]の部分は、テキストから市区町村名の部分のみを切り出すために使用されています。
このコードは、提供されたHTML構造に基づいており、異なる構造の場合は適宜調整が必要です。
```
### 実行結果のキャプチャ
![スクリーンショット 2023-12-06 0.00.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31935/3d08ab86-7b6a-16e8-c6ce-3b394cd42d30.png)


クローリングなどで何度も使い回すものであれば、色々一般化しないといけないかと思いますが（ChatGPTのコメントの後半部分の通りですね）、「このページのこの情報が今すぐ欲しい、使い捨てで構わないから取得してくるスクリプトが欲しい。腰を据えて考えれば作れなくはないけど、そこまでするのはかったるい」という場合に有用だと思います。
ChatGPTが作ったスクリプトが意図しない返答になることもあるかもしれませんが、そのときは適宜プロンプトを変えたり、ChatGPTと対話してチューニングしてください。
もちろん、自分でコード修正するのも選択肢です。

また、今だとURLを渡すだけでページ内を解釈してくれるプラグインがあるみたいですが、そちらを使うとどうなるかは試していません。
参考：https://weel.co.jp/media/plugin-list

## おまけ：スクレイピング結果をダウンロードする
### プロンプト
注意：先述のやり取りをした後である前提です。
```
出てきた結果をテキストファイルでダウンロードすることはできますか
```
### ChatGPTからの返答
```
はい、JavaScriptを使用して、抽出した市区町村名のリストをテキストファイルとしてダウンロードすることができます。これを行うためには、抽出したデータをBlobとして作成し、それをダウンロードリンクに変換し、ユーザーがそのリンクをクリックできるようにする必要があります。

以下に、市区町村名を抽出してテキストファイルとしてダウンロードするためのコード例を示します。
```

```javascript
// DOMから市区町村名を含む要素を全て選択
const municipalityElements = document.querySelectorAll('.municipality-link');

// 市区町村名を格納する配列
const municipalityNames = [];

// 各要素から市区町村名を抽出して配列に追加
municipalityElements.forEach(element => {
    // テキストから市区町村名を抽出
    const name = element.textContent.trim().split(" ")[0];
    municipalityNames.push(name);
});

// 配列を改行で区切ったテキストに変換
const textToSave = municipalityNames.join('\n');

// テキストをBlobとして作成
const blob = new Blob([textToSave], { type: 'text/plain' });

// Blobからダウンロードリンクを作成
const downloadLink = document.createElement('a');
downloadLink.href = URL.createObjectURL(blob);
downloadLink.download = 'municipality_names.txt';

// リンクをドキュメントに追加し、自動的にクリック
document.body.appendChild(downloadLink);
downloadLink.click();

// リンクをドキュメントから削除
document.body.removeChild(downloadLink);
```

```
このコードは、まず市区町村名を抽出し、それらをテキストとして一つの文字列に結合します。
次に、このテキストからBlobを作成し、それを使用してダウンロードリンクを作成します。
最後に、リンクをクリックすることでファイルのダウンロードが開始されます。
このコードをWebページに組み込むと、市区町村名のリストがテキストファイルとしてダウンロードされます。
```

### 実際の対話ログ
https://chat.openai.com/share/49e56d8f-a707-4cb5-8a5e-49cca3e14dcb


# おわりに
明日（12/7）は、@kazuomatz さんによる、浜松市の行政区の再編によるエンジニアの苦悩 とのことです。楽しみ。