人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PERLのスクレイピングに関しての質問です。

Web::Scraperを使用して指定したところから情報をとることはわかるのですが

たとえば、tebleのthのテキスト部分が○○の場合
その下のtdの部分からテキストの部分を取り出す

みたいな指定をしたいのですが
Web::Scraperで可能でしょうか?

可能でしたら指定の仕方を
ダメでしたら、他のやり方を教えていただければと思います。



●質問者: robopit
●カテゴリ:ウェブ制作 学習・教育
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● Cherenkov
●100ポイント ベストアンサー

ケースバイケースなのでHTMLを提示したほうが質問者回答者双方楽になります。
適当(精一杯)ですが、、
1回目のscrapeはtableのhtml(キャッシュしておいて2回アクセスするのを避ける)とthの集合を取得。
thの中から任意の文字列にマッチする要素の順番を取得。
さっきのhtmlをscrape対象にして、thと同じ順番のtdを取得。

use strict;
use warnings;
use Web::Scraper;
use Data::Dumper;

my $html_content = <<"EOT";
<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 </head>
 <body>
 <table align="center" border="4" width="250">
 <tr bgcolor="#cccccc">
 <th>
 <br>
 </th>
 <th>列-A</th>
 <th>列-B</th>
 <th>列-C</th>
 </tr>
 <tr align="center">
 <td>行-1</td>
 <td>A1</td>
 <td>B1</td>
 <td>C1</td>
 </tr>
 <tr align="center">
 <td>行-2</td>
 <td>A2</td>
 <td>B2</td>
 <td>C2</td>
 </tr>
 <tr align="center">
 <td>行-3</td>
 <td>A3</td>
 <td>B3</td>
 <td>C3</td>
 </tr>
 </table>
 </body>
</html>
EOT

my $res = scraper {
 process '/html/body/table', 'table[]' => 'HTML';
 process '/html/body/table//th', 'th[]' => 'TEXT';
}->scrape($html_content); #URLに変える

my $th_position;
for (my $i=0; $i < $res->{th}; $i++ ) {
 if ($res->{th}[$i] eq "列-B") {
 $th_position = $i;
 last;
 }
}

my $table_html = $res->{table}[0];

my $res2 = scraper {
 process '//td[' . ($th_position + 1) . ']', 'td[]' => 'TEXT'
}->scrape($table_html);
print Dumper $res2;

結果

$VAR1 = {
 'td' => [
 'B1',
 'B2',
 'B3'
 ]
 };

robopitさんのコメント
回答ありがとうございます。 色々と試してみたのですがInvalid [] rangeというメッセージしかでてきません 正規化関係みたいなのですが、どこが問題なのでしょうか?

Cherenkovさんのコメント
"色々"と対象のHTMLがわからないので答えようがないです。

robopitさんのコメント
すいません エラーの件ですがUSEの設定が悪かったようです。 ただ、これを実行するとCPUが100%になって数分放置しても終了しないのですが こちらのPCが原因なんでしょうか?

Cherenkovさんのコメント
回答したコードでCPU100%になるのですか?

robopitさんのコメント
上記のコードをそのままだと問題なく機能するのですが URLなどをいじってみるとそうなりました。 forループのところで問題が起こっているようなのですが(個別で機能させてみたところそこ以外は普通に機能していました)何が原因かはわかりません。

robopitさんのコメント
コードを貼っておきます https://gist.github.com/29de1f3e6fa26dcd3cff

Cherenkovさんのコメント
回答したコードのままで対象サイトのthを取りに行くと"Japanese"だけではマッチしませんよ。具体的にどれとどの値を取得したいのでしょうか。

robopitさんのコメント
thにJapaneseが含まれている場合tdを部分を抜き出すというイメージです 複数はダメということなんでしょうか? この場合Japanese(感じ)とJapanese(カナ)です。

Cherenkovさんのコメント
https://gist.github.com/af4ec2c95b06bd09792b どうでしょう。16進を読みやすい形にする方法はわかりません。

robopitさんのコメント
この文字列は16進というなんですね。 なぜこのような表示になるんでしょうか?」

Cherenkovさんのコメント
更新しました。 適当にやったらできたレベルなのでなぜかは答えられません…。

Cherenkovさんのコメント
(tdではなくspanです)

Cherenkovさんのコメント
XPathの学習に関して。 「XPath使いのための日本語チートシート http://aoproj.web.fc2.com/xpath/ 」 ここの上にあるPDFが大変良くできているので50回位見れば使えるようになります。 Firefoxのfirebugコンソールで以下のようなコードでマッチするか試すといいですよ。 var r = document.evaluate('//span[@lang="ja"]', document, null, 7, null); for (var i=0, l=r.snapshotLength; i<l; i++) { console.log(r.snapshotItem(i)) }

robopitさんのコメント
Xpathのシートありがとうございます。 もっとXpathを勉強したいと思います。 ありがとうございました。

Cherenkovさんのコメント
XPathは軸をどうするかによって書き方が全然違ってきます。 効果的な軸を決めるには(Firebugを使って)観察です。 次に質問する際は初めからHTMLを提示していただけるとありがたいです。早く解決に結びつきます。

robopitさんのコメント
ありがとうございます。 今後はそうしたいと思います。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ