LoginSignup
5
3

More than 1 year has passed since last update.

GASでちゃんとしたHTMLパーサーが使いたかったのでライブラリにした

Posted at

HTMLパーサーが欲しい

GASでスクレイピングすると誰もが思うこと、「HTMLパーサーが…欲しい…!!」
正規表現でもなんとかなるといえばなるけど柔軟性に欠けるし保守性も低い。
よく紹介されるのはParserだけど個人的には「コレ使うなら正規表現でも変わらなくね?」と思ってしまうし、同一タグのネストを解決するのが大変。

ならnodejsから移植すれば良いじゃない。
というわけでライブラリを作りました。下記IDをライブラリ検索で利用できます。
スクリプトID: 1JTLPVXGW6Pq4zSAV5ED9XrWOPydVywumQZSOWN7l6KJ0UtWxtX3RbYO6
GitHub: https://github.com/kairi003/gas-html-parser

使い方

本ライブラリはほぼnode-html-parserそのままです。作ったとか言えないレベル。
細かい利用方法は本家のドキュメントを確認していただくとして、以下のように使えます。

const html = `<body>
  <ul id="fruits">
    <li class="apple">Apple</li>
    <li class="orange">Orange</li>
    <li class="pear">Pear</li>
  </ul>
</body>`;
const dom = HtmlParser.parse(html);
console.log(dom.querySelector('#id .pear').textContent);

ちなみになんでnode-html-parserなのかというとAPIがブラウザDOMに近い(同じではない)のと軽いからです。jqueryが好きならcheerioのほうがいいかも。jsdomは無理そうでした。

作り方

GitHub: https://github.com/kairi003/gas-html-parser

node-html-parserをimportするだけのindex.jsをwebpackでバンドルしてます。
またGASライブラリとして使う都合上、ライブラリのグローバルとnode-html-parserのグローバルを一致させたかったのでglobalThisObject.assignしてます。

Object.assign(globalThis, require('node-html-parser'));

普通に使う分には以下のようにexportしてwebpackの設定でoutput.library: "HtmlParser"などを指定したほうが良いでしょう。

module.exports(require('node-html-parser'));

ちなみにwebpackでちょっと困ったこととして、developmentモードでは動くのにproductionでは動かないという自体に遭遇しました。
これはminimize時にオブジェクトキーに非ASCII文字がクォーテーション無しに生成されて一部がSyntaxErrorになっていたこと ({ℵ: "aleph",...}←こんなの) が原因で、次のようにterserのオプションを指定することで解決しました。

module.exports = {
    ...,
    optimization: {
        minimize: true,
        minimizer: [
          new TerserPlugin({
            terserOptions: { output: { ascii_only: true } }
          })
        ],
    }
}

感想

割と手軽にできて驚きでした。なんで普及してないんだろう。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3