[JS] 文章中にURLが含まれるか調べるための正規表現

正しいURL構文かどうかをチェックするものではなく、文章中にURLが含まれるかどうかを調べるための正規表現について。

URL正規表現

ユーザーが投稿する文章にURL的文字列が含まれているかどうかチェックし、含まれていればSafe Browsing APIなどに投げたりするのに使う。

(?:[A-Za-z]{3,9})(?::\/\/|@)(?:(?:[A-Za-z0-9\-.]+[.:])|(?:www\.|[-;:&=+$,\w]+@))(?:[A-Za-z0-9.-]+)(?:[/\-+=&;%@.\w_~()]*)(?:[.!/\\\w-?%#~&=+()]*)

RegExrのサンプル

?: (non-capturing group)を削除すればマッチ部分の文字列を得ることができたりもする。

マッチした文字列を得る場合

([A-Za-z]{3,9})(?::\/\/|@)((?:[A-Za-z0-9\-.]+[.:])|(?:www\.|[-;:&=+$,\w]+@))([A-Za-z0-9.-]+)([/\-+=&;%@.\w_~()]*)([.!/\\\w-?%#~&=+()]*)

URLhttps://firebase.google.com/docs/reference/js/firebase.firestore.Query#on-snapshot に対するマッチ結果:

  1. https
  2. firebase.google.
  3. com
  4. /docs/reference/js/firebase.firestore.Query
  5. #on-snapshot

RegExrのサンプル

The Perfect URL Regular Expression の正規表現を改変した。
主な改変内容:

  • ポート番号に対応
  • x-www-form-url符号化形式に対応
  • ドメイン不在に反応しない
  • javascript:に反応しない

以下はチェック用に使ったURL

<pre class="wp-block-syntaxhighlighter-code">http://testsafebrowsing.appspot.com/s/malware.html

https://testsafebrowsing.appspot.com/

mongodb://localhost:27017/db

git@github.com:axios/axios.git

https://.com

/path/to/hoge.html

javascript:alert(1)

http://123.102.216.70:8080/view/dev/job/dev-build/

https://getbootstrap.com/docs/4.4/components/tooltips/

https://firebase.google.com/docs/reference/js/firebase.firestore.Query#on-snapshot

https://imt.services.isca.jp/imart/collaboration/schedule/user/calendar/groupweek?

https://console.firebase.google.com/u/0/project/foo-bar-112345/database/firestore/data~2Fpoints~2FHN8IjOreJYOYpaSMuGDxFEY9gAC3~2Fhistory_point_gain~2F0GWxXldAJrwjWOMYjh0M

https://www.boost.org/doc/libs/1_66_0/libs/regex/doc/html/boost_regex/ref/non_std_strings/mfc_strings/mfc_intro.html

https://ja.nuxtjs.org/guide/routing#%E3%83%8D%E3%82%B9%E3%83%88%E3%81%95%E3%82%8C%E3%81%9F%E3%83%AB%E3%83%BC%E3%83%88

http://localhost:9000/?path=/story/foo-bar--default

https://vue-test-utils.vuejs.org/ja/api/wrapper/#setdata-data

https://kamigame.jp/%E9%99%B0%E9%99%BD%E5%B8%AB/index.html

https://ja.wikipedia.org/wiki/%E9%99%B0%E9%99%BD%E5%B8%AB_(%E3%82%B2%E3%83%BC%E3%83%A0)

https://ja.wikipedia.org/wiki/%E9%99%B0%E9%99%BD%E5%B8%AB_(%E3%82%B2%E3%83%BC%E3%83%A0)#%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%B8%E3%82%AB%E3%83%AB%E3%80%8C%E9%99%B0%E9%99%BD%E5%B8%AB%E3%80%8D%E3%80%9C%E5%B9%B3%E5%AE%89%E7%B5%B5%E5%B7%BB%E3%80%9C

<iframe title="Nintendo Switch 本体 (ニンテンドースイッチ) Joy-Con(L) ネオンブルー/(R) ネオンレッド" type="text/html" width="825" height="550" frameborder="0" allowfullscreen style="max-width:100%" src="https://read.amazon.com.au/kp/card?preview=inline&linkCode=kpd&ref_=k4w_oembed_RMHnlXyLRQgoac&asin=B07WXL5YPW&tag=kpembed-20"></iframe>

<iframe title="Nintendo Switch 本体 (ニンテンドースイッチ) Joy-Con(L) ネオンブルー/(R) ネオンレッド" type="text/html" width="825" height="550" frameborder="0" allowfullscreen style="max-width:100%" src="https://read.amazon.com.au/kp/card?preview=inline&linkCode=kpd&ref_=k4w_oembed_NAToYCXK5AdBM9&asin=B07WXL5YPW&tag=kpembed-20"></iframe>

https://www.amazon.co.jp/gp/video/detail/B07QBC423H/ref=atv_wl_hom_c_unkc_1_32</pre>

プロトコル必須

http(p)から始まることを条件にする場合、文章中なら5chのh抜き表記も考慮がいる

(?:h?ttps?:\/\/)(?:(?:[A-Za-z0-9\-.]+[.:])|(?:www\.|[-;:&=+$,\w]+@))(?:[A-Za-z0-9.-]+)(?:[/\-+=&;%@.\w_~()]*)(?:[.!/\\\w-?%#~&=+()]*)

RegExrのサンプル

相対指定URL

前述の正規表現は相対指定のURLに対応していない。
もし対応するなら専用の正規表現を用意する。

(\/{1}(?:[A-Za-z0-9.-]+)\/)([/\-+=&;%@.\w_~()]*)([.!/\\\w-?%#~&=+()]*)

RegExrのサンプル

これだけだと相対指定だけマッチする条件にはならない。
何らかの日本語的文字かスペースがURL前にあるかどうかを条件に含めれば、相対パスだけにマッチする。

([\u2000-\u2B90\u3000-\u30FF\u3220-\u33FE\u3400-\u9FFF\uF900-\uFAFF\uD840-\uD87F\uDC00-\uDFFF\uFF01-\uFFE6])

Unicode正規表現のサンプル

日本語ドメイン

ブラウザのアドレスバーからURLをコピーした場合、Punycode表記になるので、ここまでの正規表現で対応できる。

日本語.jp → xn--wgv71a119e.jp

ドメインを直接日本語で表記した場合、前述のUnicode正規表現で対応したいドメインの文字種別を判別すれば対応できる。Punycodeへの変換はJSDOMのライブラリを使えばよさそうだし、日本語.jpの日本語ドメインリストをスクレイピングして有効な日本語ドメインリストを作ることもできなくはない。

が、日本語ドメイン自体が下火なので、その労力を払ってまで対応したいとは思わなかった🙄

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください