Rubyでちゃんと文字列からURIを抽出する

イタンジでエンジニアをしているぽんこつです。フロントからインフラまでなんでもやってます。

なにか文字列の塊からURI/URLを抽出しなければいけない、という案件はRubyに限らずよくでてくると思いますが、実際に真面目にやらないといけないとなるとかなりしんどいです。日本語URL、invalidなホスト名etc...

RubyであればURI.extractという、URIを文字列中から探して、ヒットしたURIを全部返してくれるメソッドがあるのですが、

  • obsolateである
  • matchした文字列でしか返ってこない

という問題があり、あまり使いたくはありません。

ところでURI.extractですが、Rubyソースコードを読んでみると、

  1. RFC2396_Parser.extractを呼び出す
  2. make_regexp正規表現を生成
  3. `string`.scan

しているだけということが分かります。make_regexp正規表現さえあれば、なんでもできそうですね!表題のパターンだとこうなります。

regexp = URI::DEFAULT_PARSER.make_regexp(['http', 'https'])
text.to_enum(:scan, regexp).map { Regexp.last_match }.each { |match|
  ...
}

URIスキームを引数に持つのでftpは除外したいとかでも大丈夫。どこぞで公開されていた謎正規表現と違ってRFCに準拠しているという安心感があります。やはり正規表現は自作したら負けですね。