XPathや正規表現を用いてGoogle SpreadSheetに情報をまとめる

## まるで黒魔術

XPathや正規表現を学び始めたとき、同時期にmod_rewriteについての下記の言葉を知りました。

> 膨大な設定例やドキュメントがあるにもかかわらず、 mod_rewrite は黒魔術である。かなりイケてるっぽい黒魔術だが、 やっぱり黒魔術である。
> 
> **Brian Moore**

XPathや正規表現も、まさにこれと同じ印象で素晴らしく魅力的で一方、混沌としており黒魔術だなと感じていました。

これらの技術は簡易なものであれ直感的にかけますし、その場合はプログラム処理として任せるより、解読しやすくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426622/aab1192d-348a-acea-7f27-ea60039710f3.png)

## Google Spreasheetでの実例

Google SpreadsheetではIMPORTXML関数を用いて外部サイトの情報をXPathで取得することが出来ます。

### Case1: 既存サイトの情報整理や分析

既存サイトの情報整理や分析のケースを考えてみましょう。

例えば、A2に対象のURLが入っているとするとmeta descriptionの内容取得には下記のように記載すればよいでしょう。

```
=IMPORTXML(A2, "//meta[@name='description']/@content")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426622/27d706cc-6233-169d-bb92-e92ec9ea64da.png)

#### 少し複雑な例

XPathはコードから目的を読み取るのは簡単ですが、入り組んだものを書くのが大変です。

ここでは、サイトリニューアルなどを想定して、既存コンテンツの内容のアウトラインを把握するため、下記のようなことを考えてみましょう。

* コンテンツ本文が入る site-mainというclassを持つ要素配下のh2からh4の見出しタグをすべて取得し、セル内に改行区切りで出力する。site-mainというclassを持つ要素はdivとは限らない。

```
=TEXTJOIN(CHAR(10), true, IMPORTXML(A2, "//*[contains(@class, 'site-main')]//h2 | //*[contains(@class, 'site-main')]//h3 | //*[contains(@class, 'site-main')]//h4"))
```

読めばやりたいことの想像がつきますが、書くのは少し面倒です。
このようなものは生成AIに考えてもらうと良いでしょう。

### Case2: WordPressプラグインのメンテナンス資料

WordPressプラグインの最終更新日や最新バージョンなどを常に追いかけて手動でドキュメントをメンテナンスするのはとても面倒です。

これも、IMPORTXMLと正規表現を用いれば手作業で入力や更新の手間を最小限にすることができます。

#### 構造化データの取得

DOM上の情報取得には様々なアプローチがありますが、WordPressのプラグインページのHTMLを見ると、[ソフトウェアアプリの構造化データ](https://developers.google.com/search/docs/appearance/structured-data/software-app?hl=ja)に対応していることが分かります。

例: https://wordpress.org/plugins/classic-editor/

```html
<script type="application/ld+json">
[
    {
        "@context": "http://schema.org",
        "@type": [
            "SoftwareApplication",
            "Product"
        ],
        "applicationCategory": "Plugin",
        "operatingSystem": "WordPress",
        "name": "Classic Editor",
        "url": "https://wordpress.org/plugins/classic-editor/",
        "description": "Enables the previous &quot;classic&quot; editor and the old-style Edit Post screen with TinyMCE, Meta Boxes, etc. Supports all plugins that extend this screen.",
        "softwareVersion": "1.6.3",
        "fileFormat": "application/zip",
        "downloadUrl": "https://downloads.wordpress.org/plugin/classic-editor.1.6.3.zip",
        "dateModified": "2024-04-06T00:44:50+00:00",
        "aggregateRating": {
            "@type": "AggregateRating",
            "worstRating": 1,
            "bestRating": 5,
            "ratingValue": 4.9,
            "ratingCount": 1174,
            "reviewCount": 1174
        },
        "interactionStatistic": {
            "@type": "InteractionCounter",
            "interactionType": "http://schema.org/DownloadAction",
            "userInteractionCount": 57757370
        },
        "image": [
            "https://ps.w.org/classic-editor/assets/icon-256x256.png?rev=1998671",
            "https://ps.w.org/classic-editor/assets/banner-1544x500.png?rev=1998671"
        ],
        "offers": {
            "@type": "Offer",
            "url": "https://wordpress.org/plugins/classic-editor/",
            "price": "0.00",
            "priceCurrency": "USD",
            "seller": {
                "@type": "Organization",
                "name": "WordPress.org",
                "url": "https://wordpress.org"
            }
        }
    }
]
</script>
```

必要になりそうな情報はすべてここに集約されており、便利そうですね。

まずは、この情報をGoogleSpreadsheetに転写しましょう。
（A2にプラグインURLが入っている想定）

```
= SUBSTITUTE(IMPORTXML(A2, "//script[@type='application/ld+json']/text()"),CHAR(10),"")
```

改行は邪魔になるので、SUBSTITUTEを用いて取り除いています。

#### プラグイン説明文の取得

例えば、プラグインの説明文を取得する場合、あとは下記の正規表現で抜き出すだけです。
（B2に前述のJSONデータが入っている想定）

```
=REGEXEXTRACT(B2,"""description"":\s*""([^""]+)"))
```

#### 最終更新の取得

最終更新日の取得は下記のように正規表現で抽出したものを日付型に置き換えると良いでしょう。

```
= DATEVALUE(REGEXEXTRACT(REGEXEXTRACT(B2,"""dateModified"":\s*""([^""]+)"),"([^T]*)T*"))
```

この結果に対して、例えば条件付き書式で1年以上経過している場合は色を付けるとメンテナンスされていないプラグインが可視化されて一目瞭然になります。
何もGoogle Spreadsheet上でXPathや正規表現置換を頑張らなくてもと思うかもしれませんが、値に対して条件付き書式を設定したり、二次利用したりを考えるとやはり便利です。

## 開発の現場でも

何かの目的があって、ちょっとしたツールや機能を開発する際に、XPathや正規表現置換を用いれば、予定していた複数の処理はすべて同一のロジックに落とし込めることがあります。

それらを設定ファイルとして抜き出すことで汎用化することも出来ます。

目的に沿わない形で無理に固執して使うと、どのような技術であれ難解な魔術に見えますが、適している場合は強力なツールになることもあります。

データベースへのクエリとして実装するべきか、正規表現を用いるべきか、XPathを用いるべきか、プログラムロジックか、状況に応じてうまく使い分けられると良いですね。

## add moreではエンジニアを募集しています

株式会社add moreではWebサイトの制作、WordPressなどの汎用CMSを用いたサイト制作、フルスクラッチのWebアプリケーション、静的サイト制作、PoC構築、SPAなど幅広い業務を手掛けています。

Webエンジニアを積極的に採用しておりますので、ご興味のある方は[コーポレートサイト](https://www.add-more.co.jp/recruit/engineer/)または[Wantedly](https://www.wantedly.com/companies/add-more)からご応募ください。