- ベストアンサー
[LWP?] 特定のCLASSの値だけ取得したい
- LWPを使って特定のWebページの内容を取得する方法について質問します。具体的には、指定したclassのinnerTextだけを取得したいです。
- LWPを使用して特定のWebページの情報を取得する際、特定のclassに属する要素の値のみを取得したいです。具体的には、classがbbbである要素の値のみを取得したいです。
- LWPを使用して取得したWebページの中から、特定のclassに属する要素の値のみを取得する方法について教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
#2のプログラムだと、リンクのあるLI のクラスをccc にしても、同じ結果がでる(LIの終わりを判定していないから)ので、さすがにあんまりだと思って、判定をするようにしてみました。 ---------------------------------------------------------------- use HTML::TokeParser; @a=(); $data = <<DATA; <BODY> <UL> <LI class=aaa>xxx1</LI> <LI class=aaa>xxx2</LI> <LI class=aaa>xxx3</LI> </UL> <UL> <LI class=bbb>yyy1</LI> <LI class=bbb>yyy2</LI> <LI class=bbb>yyy3</LI> </UL> <UL> <LI class=bbb><img alt="xyz"><a href="yyysite1">yyy1</a></LI> <LI class=bbb><img alt="xyz"><a href="yyysite2">yyy2</a></LI> <LI class=bbb><img alt="xyz"><a href="yyysite3">yyy3</a></LI> </UL> </BODY> DATA $parser = HTML::TokeParser->new(\$data); while ($token = $parser->get_tag('li')) { if($token->[1]{'class'} eq 'bbb'){ while($token = $parser->get_tag('a',"/li") ){ last if $token->[0] eq '/li'; #/LI が見つかったらブレイク if($token->[0] eq 'a'){ $text = $parser->get_text('/a'); $href = $token->[1]{'href'}; push @a, "$href\t$text\n"; } } } } print @a;
その他の回答 (3)
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
とりあえず、#2の場合はうまくと思いますが、 よく考えたら、#2の回答は手抜き過ぎで一般的な状況ではうまくいかないような気がします。(<なんだそれ、"どうしてベストを尽くさないのか?") ご注意まで・
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#1>yyysite1 とyyy1 が欲しいのですが、どのようにすればよいのでしょうか? 同じことですが、、 書き直してみました。 ---------------------------------------------------------------- use HTML::TokeParser; @a=(); $data = <<DATA; <BODY> <UL> <LI class=aaa>xxx1</LI> <LI class=aaa>xxx2</LI> <LI class=aaa>xxx3</LI> </UL> <UL> <LI class=bbb>yyy1</LI> <LI class=bbb>yyy2</LI> <LI class=bbb>yyy3</LI> </UL> <UL> <LI class=bbb><img alt="xyz"><a href="yyysite1">yyy1</a></LI> <LI class=bbb><img alt="xyz"><a href="yyysite2">yyy2</a></LI> <LI class=bbb><img alt="xyz"><a href="yyysite3">yyy3</a></LI> </UL> </BODY> DATA $parser = HTML::TokeParser->new(\$data); while ($token = $parser->get_tag('li')) { if($token->[1]{'class'} eq 'bbb'){ # LI class="bbb" while($token = $parser->get_tag('a') ){ $href = $token->[1]{'href'}; $text = $parser->get_text('/a'); push @a, "$href\t$text\n"; } } } print @a;
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
そのような場合にはHTMLパーサーを使います。 CPANモジュールに HTML::TokeParser というモジュールがありますが、それを使った場合のサンプル ---------------------------------------------------------------- use HTML::TokeParser; @LI_text=(); #$data には、要するにゲットしたHTML文字列 $data = <<DATA; <BODY> <UL> <LI class=aaa>xxx1</LI> <LI class=aaa>xxx2</LI> <LI class=aaa>xxx3</LI> </UL> <UL> <LI class=bbb>yyy1</LI> <LI class=bbb>yyy2</LI> <LI class=bbb>yyy3</LI> </UL> </BODY> DATA $parser = HTML::TokeParser->new(\$data); while ($token = $parser->get_tag('li')) { my $text = $parser->get_text('/li'); push(@LI_text, "$text\n") if $token->[1]{'class'} eq 'bbb'; } print @LI_text;
お礼
ありがとうございます! 一発で解決です! ところで、質問の仕方が悪かったのですが、本当は <UL> <LI class=bbb><img alt="xyz"><a href="yyysite1">yyy1</a></LI> <LI class=bbb><img alt="xyz"><a href="yyysite2">yyy2</a></LI> <LI class=bbb><img alt="xyz"><a href="yyysite3">yyy3</a></LI> </UL> のようにLIに複数のタグが入れ子になっています。 教えていただいた方法だと、 bbb yyy1 のように表示されてしまいました。 本来であれば yyysite1 と yyy1 が欲しいのですが、どのようにすればよいのでしょうか? http://homepage3.nifty.com/hippo2000/perltips/html/TokeParser.htm を見て、一度、LIタグの間の文字列をすべて取り出してからAタグの要素を処理しようとしたのですが、うまくいきませんでした。 よろしければ教えていただけないでしょうか? よろしくお願い致します。m(__)m
お礼
何度も何度も本当にありがとうございます。m(__)m 実は、LIタグの中にAが2つあり、悩んだのですが、 いただいた回答とその工夫を拝借して、おかげさまでかきのようにして解決することができました。 本当にありがとうございます。 -- $parser = HTML::TokeParser->new(\$res->content); while ($token = $parser->get_tag("li")) { if($token->[1]{'class'} eq "site") { while($token = $parser->get_tag("a","/a","/li") ) { last if $token->[0] eq "/a"; last if $token->[0] eq "/li"; if($token->[0] eq "a") { $text = $parser->get_text("/a"); from_to($text, 'euc-jp', 'shiftjis'); $href = $token->[1]{'href'}; $href =~ s/^http.*\&rd=(.*)/$1/eg; $href =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg; push @a, "$href\t$text\n"; } } } } print @a;