ktty1220 / cheerio-httpcli

iconvによる文字コード変換とcheerioによるHTMLパースを組み込んだNode.js用HTTPクライアントモジュール
MIT License
262 stars 28 forks source link

cheerio.load()のオプションをclient.fetch()から渡したい #16

Closed MasaGon closed 7 years ago

MasaGon commented 7 years ago

下記に記載がある cheerio.load() のオプションを client.fetch() から渡したいのですが、やり方はありますか? https://www.npmjs.com/package/cheerio#loading

具体的には下記の方と同じ状況が発生しておりまして、おそらく xmlMode: true を渡せば解決するのではないかと考えています。 https://teratail.com/questions/21820

RSSのlinkタグは割と使用頻度が高いのではないかと思います。

[参考] https://github.com/cheeriojs/cheerio/issues/46

ktty1220 commented 7 years ago

返答がちょっと長いので3行でまとめると、

という感じです。以下、詳細になります。


今の所、cheerio.load()に外部からオプションを渡すことはできません。

利用者側で取り急ぎ対応したい場合は、直接ライブラリのソースに手を入れることになりますが、

lib/client.jsの

result.$ = this.cheerio.load(result.body, { decodeEntities: true });

の部分にxmlMode:trueを追加する感じになります。

で、正式な対応について、いくつか方法はありますが、

1. fetch()にcheerio.load()に渡すオプションを指定する => :x:

現状のfetch()自体、すでに引数が4つあり、かつそれぞれが省略可能なので、これ以上増やすと利用する上で混乱したり指定ミスが生じる可能性がある、ということもあり避けたいと考えています。

2. cheerio-httpcliの共通オプションとしてcheerio.load()に渡すオプションを指定する => :x:

共通オプションとして指定すると、「このURLはxmlとして取得したいけど、あのURLはhtmlとして取得したい」といった場合に非同期処理だと制御が難しい & いちいち設定し直すのが面倒くさい、という理由でこれもちょっと・・・という感じです。

あと、余談ですが、cheerio.load()に外部からオプションを渡せなくしているのはちょっと意図的だったりします(詳細: #9)。

今回のxmlModeとは関係ないのですが、cheerio-httpcliではcheerio.load()時にdecodeEntities:trueでパースすることを前提として内部で色々と動作調整しているので、cheerio.load()のオプションを外部から指定できるようにしてdecodeEntities:falseにされた場合、意図しない結果が返ってくる可能性があります。

したがって、オプション指定できるようにするとしてもxmlModeだけにしたいと考えていますが、先述の通り、どこで指定するかという点でちょっと問題ありという状況です。

したがって、

3. fetch()でのコンテンツ取得時にcontent-typeやURLの拡張子を見て、xmlやrssであると判別された場合は自動でxmlMode:trueにする => :white_check_mark:

といった対応を考えています。

ただ、その場合、既存で動いているスクリプトがxmlMode:falseで正常に動作することを前提とした組み方をしていると挙動がおかしくなる可能性がでてくるので、cheerio-httpcliの共通オプションにforceHtmlといったオプションを用意して、この自動判別機能をオフにできる、といった形で対処する予定です。

一応年内を目標にこのような対応を行ったバージョンをリリースしようと思いますのでよろしくお願いします。

※いやそれはマズいっしょ、といったことがあればお知らせください。

MasaGon commented 7 years ago

ベストな対応かと思います。ありがとうございます!