メメメモモ

プログラミング、筋トレ、ゲーム、etc

perlでスクレイピング「正規表現でデータを取得」

取得してきたHTMLから必要な箇所だけを抽出します。
perlには正規表現の機能があります。
正規表現を使って必要なデータを取って来れます。
例えば下記のようなHTMLを取得したとします。

<html>                                                                           
<head>                                                                           
<title>Test Page</title>                                                         
</head>                                                                          
<body>                                                                           
<div id="content">                                                               
<h1>Test Page</h1>                                                               
<h2>主なトピックス</h2>                                                          
<ul class="clr">                                                                 
<li><span class="dateRight">8月30日</span><a href="/topics/title1.html">Title1</a></li>                                                                          
<li><span class="dateRight">8月29日</span><a href="/topics/title2.html">Title2</a></li>                                                                          
<li><span class="dateRight">8月28日</span><a href="/topics/title3.html" class="newTitle">Title3</a></li>                                                         
<li><span class="dateRight">8月27日</span><a href="/topics/title4.html">Title4</a></li>                                                                          
</ul>                                                                            
</div>                                                                           
</body>                                                                          
</html>  


ここで、h1タグで囲まれている「Test Page」という部分を抜き出したい時は、次のような正規表現になると思います。

if ($html =~ m#<h1>(.*?)</h1>#) {
   my $h1 = $1;
}


また、liタグに囲まれている部分で、

  • spanタグで囲まれている部分
  • href属性の値の部分
  • aタグで囲まれている部分

を抜き出すとします。
複数のliタグがあることやhref属性の後に「class="new"」が付く事もあることを考慮すれば、
次のような処理になると思います。

while ($html =~ m#<span class="dateRight">(.*?)</span><a href="(.*?)".*?>(.*?)</a>#g) {
    my $date  = $1;
    my $url   = $2;
    my $title = $3;
}


このようにして正規表現を駆使すれば、必要なデータが取得できます。


正規表現を勉強する際に、「書き方を覚えたけどどうやって練習すればいいのか分からない」ということがありました。
スクレイピング正規表現を使うようにすれば良い練習になります。
正しい正規表現を書けるようになってくると、うまくデータが取って来れるようになるので、楽しく練習できると思います。


最後に実際に動かしたスクリプトです。

#!/usr/bin/env perl                                                              
use strict;
use warnings;
use utf8;
use Encode;

my $html=<<'HTML';
<html>                                                                           
<head>                                                                           
<title>Test Page</title>                                                         
</head>                                                                          
<body>                                                                           
<div id="content">                                                               
<h1>Test Page</h1>                                                               
<h2>主なトピックス</h2>                                                          
<ul class="clr">                                                                 
<li><span class="dateRight">8月30日</span><a href="/topics/title1.html">Title1</\
a></li>                                                                          
<li><span class="dateRight">8月29日</span><a href="/topics/title2.html">Title2</\
a></li>                                                                          
<li><span class="dateRight">8月28日</span><a href="/topics/title3.html" class="n\
ewTitle">Title3</a></li>                                                         
<li><span class="dateRight">8月27日</span><a href="/topics/title4.html">Title4</\
a></li>                                                                          
</ul>                                                                            
</div>                                                                           
</body>                                                                          
</html>                                                                          
HTML                                                                             

my $title = '';
if ($html =~ m#<h1>(.*?)</h1>#) {
    $title = $1;
}

print $title, "\n";

while ($html =~ m#<span class="dateRight">(.*?)</span><a href="(.*?)".*?>(.*?)</\
a>#g) {
    my $date  = encode_utf8($1);
    my $url   = $2;
    my $title = encode_utf8($3);

    print "$date, $url, $title\n";
}