画像のURL抽出を通して正規表現を勉強してみた

今まで正規表現というものに対して、ネットのコピペでやり過ごしていました。
ただそれでは流石にまずいな、と思い勉強をしてみました。

何か目的がないと作っていても楽しくないので、rubyで画像を収集するクローラーっぽいものを作ることにしました。
今回は、画像のURLを取得した正規表現周りのみについて書きます。

画像の行を探す

まずは、指定したURLのページのソースを一行ずつ読み込み、画像(jpeg,jpg,png,gif)についての記述があるか正規表現で探しました。

line = line.match( /.+(jpeg|jpg|png|gif).+/ )

lineには、ページのソースの一行が入っているとします。

正規表現の構文(以下のURL)を参考にすると
https://msdn.microsoft.com/ja-jp/library/cc392020.aspx
「.」は、任意の一文字
「+」は、直前のサブ式(今回は文字と考えて問題ありません)を1回以上繰り返す
「x|y」は、xまたはyに一致する

つまり「何かしらの文字を繰り返した後に、画像の拡張子があり、再び文字が繰り返す」というものです。
これで画像があるソースの行の取得ができました。

画像のある行から画像のURLのみを取得

今回は以下のlineに以下のような行が代入されたと仮定して、話を勧めます。

<meta itemprop="image" content="https://blog.st-hatena.com/images/theme/og-image-1500.png"/>

このようなHTMLのコードから、pngのURLのみを取得したいと思います。
画像のURLは文字列ですので、「"」で囲まれています。
「"」で囲まれているものを抽出して画像のURLを取得したいのですが、今回の場合は「itemprop」があるように色々と余分なものが入っている場合があります。
そのため、まずは空白や「;」「(」など色々なものを削除する作業をします。

array = line.to_s.split(/[ ()<>;,]/)

正規表現では「[ ]」は、角かっこで囲まれた文字の中のいずれかに一致

そのため、「空白,()<>;,」というコードの切れる部分を全部切るということをします。
そうするとarrayはカットされた結果の配列になります。
arrayの中身は以下のようになります。

[0]:(「<」で切ったため空です)
[1]:meta
[2]:itemprop="image"
[3]:content="https://blog.st-hatena.com/images/theme/og-image-1500.png"/

いい感じになっていきましたね!
ただ今回の場合は文字の最後に「/」が入ったように、何かしらのゴミが入る場合があります。

この配列の中身を一つ一つ確認し文字だけ取得するために、先ほど言った「"」で囲まれているものを抽出します。

array.each do |cut|
  image_url = cut.to_s.match(/".+(\.jpeg|\.jpg|\.png|\.gif).*"/)
end

image_urlの中身は以下のようになります

"https://blog.st-hatena.com/images/theme/og-image-1500.png"

これで「"」に囲まれていますが、画像のURLのみ抽出できました。
あとは最初と最後の文字をカットすると、画像のURLのみとなります。

最後は力技になってしまいましたが、正規表現のいい勉強になりました。


(実行環境)
Ruby