以前、Groovyでこれを行う方法を尋ねました。ただし、すべてのCPANライブラリがあるため、現在、Perlでアプリを書き直しています。
ページに次のリンクが含まれている場合:
<a href="http://www.google.com"> Google </a> <a href = "http://www.Apple.com ">アップル</a>
出力は次のようになります。
Google、http://www.google.com Apple、http://www.Apple.com
Perlでこれを行うための最良の方法は何ですか?
これには WWW :: Mechanize モジュールの使用をご覧ください。それはあなたのためにあなたのウェブページをフェッチし、そしてあなたにURLのリストであなたに働きやすいものを与えるでしょう。
my $mech = WWW::Mechanize->new();
$mech->get( $some_url );
my @links = $mech->links();
for my $link ( @links ) {
printf "%s, %s\n", $link->text, $link->url;
}
非常にシンプルで、そのページの他のURLに移動する場合は、さらにシンプルです。
Mechは基本的にオブジェクト内のブラウザです。
HTML :: LinkExtractor および HTML :: LinkExtor 、 HTML :: Parser パッケージの一部をご覧ください。
HTML :: LinkExtractorはHTML :: LinkExtorに似ていますが、URLを取得するだけでなく、リンクテキストも取得する点が異なります。
私はこのようなことのために pQuery を使うのが好きです...
use pQuery;
pQuery( 'http://www.perlbuzz.com' )->find( 'a' )->each(
sub {
say $_->innerHTML . q{, } . $_->getAttribute( 'href' );
}
);
また、この前のstackoverflow.comの質問 PerlまたはPythonの機能のようなLexのエミュレーション も同様の回答を確認してください。
冒険心があり、モジュールなしで試してみたい場合は、次のようなものが機能するはずです(ニーズに合わせて調整してください)。
#!/usr/bin/Perl
if($#ARGV < 0) {
print "$0: Need URL argument.\n";
exit 1;
}
my @content = split(/\n/,`wget -qO- $ARGV[0]`);
my @links = grep(/<a.*href=.*>/,@content);
foreach my $c (@links){
$c =~ /<a.*href="([\s\S]+?)".*>/;
$link = $1;
$c =~ /<a.*href.*>([\s\S]+?)<\/a>/;
$title = $1;
print "$title, $link\n";
}
ここで私が間違えたことがいくつかある可能性がありますが、それを書いた後に試したいくつかのテストケースで機能します(<img>タグなどは考慮されていません)。
これを行う別の方法は、XPathを使用して解析されたHTMLを照会することです。特定のクラスを持つdiv内のすべてのリンクを抽出するなど、複雑な場合に必要です。これにはHTML :: TreeBuilder :: XPathを使用します。
my $tree=HTML::TreeBuilder::XPath->new_from_content($c);
my $nodes=$tree->findnodes(q{//map[@name='map1']/area});
while (my $node=$nodes->shift) {
my $t=$node->attr('title');
}
または、HTML :: LinkExtorを拡張して必要な処理を実行し、変更を作成者に送信することを検討してください。
以前の回答は完全に良かったし、パーティーに遅れていることはわかっているが、これは[Perl]フィードにぶつかったので…
XML :: LibXML は、HTMLの解析に優れており、速度の点で他の追随を許しません。不正な形式のHTMLを解析する場合は、recover
オプションを設定します。
use XML::LibXML;
my $doc = XML::LibXML->load_html(IO => \*DATA);
for my $anchor ( $doc->findnodes("//a[\@href]") )
{
printf "%15s -> %s\n",
$anchor->textContent,
$anchor->getAttribute("href");
}
__DATA__
<html><head><title/></head><body>
<a href="http://www.google.com">Google</a>
<a href="http://www.Apple.com">Apple</a>
</body></html>
–利回り–
Google -> http://www.google.com
Apple -> http://www.Apple.com
Sherm 推奨 HTML :: LinkExtor 、これはほぼあなたが望むものです。残念ながら、<a>タグ内のテキストを返すことはできません。
Andy 推奨 WWW :: Mechanize 。それがおそらく最良の解決策です。
WWW :: Mechanizeがお好みに合わない場合は、 HTML :: TreeBuilder を試してください。 HTMLからDOMのようなツリーを構築し、必要なリンクを検索して、必要な近くのコンテンツを抽出できます。
HTML :: LinkExtractor はHTML :: LinkExtorよりも優れています
リンクテキストとURLの両方を提供できます。
使用法:
use HTML::LinkExtractor;
my $input = q{If <a href="http://Apple.com/"> Apple </a>}; #HTML string
my $LX = new HTML::LinkExtractor(undef,undef,1);
$LX->parse(\$input);
for my $Link( @{ $LX->links } ) {
if( $$Link{_TEXT}=~ m/Apple/ ) {
print "\n LinkText $$Link{_TEXT} URL $$Link{href}\n";
}
}
HTMLは構造化されたマークアップ言語であり、エラーなしでその意味を抽出するために解析する必要があります。リストされているモジュールShermは、HTMLを解析し、リンクを抽出します。入力が常に同じ方法で形成されることがわかっている場合(属性を忘れないでください)、アドホックな正規表現ベースのソリューションは受け入れられるかもしれませんが、構造化テキストを処理するには、ほとんどの場合、パーサーが正しい答えです。