web-dev-qa-db-ja.com

PerlのHTMLからURLとリンクテキストを抽出するにはどうすればよいですか?

以前、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でこれを行うための最良の方法は何ですか?

20
anon

これには 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は基本的にオブジェクト内のブラウザです。

40
Andy Lester

HTML :: LinkExtractor および HTML :: LinkExtorHTML :: Parser パッケージの一部をご覧ください。

HTML :: LinkExtractorはHTML :: LinkExtorに似ていますが、URLを取得するだけでなく、リンクテキストも取得する点が異なります。

11
Sherm Pendley

私はこのようなことのために pQuery を使うのが好きです...

use pQuery;

pQuery( 'http://www.perlbuzz.com' )->find( 'a' )->each(
    sub {
        say $_->innerHTML . q{, } . $_->getAttribute( 'href' );
    }
);

また、この前のstackoverflow.comの質問 PerlまたはPythonの機能のようなLexのエミュレーション も同様の回答を確認してください。

6
draegtun

冒険心があり、モジュールなしで試してみたい場合は、次のようなものが機能するはずです(ニーズに合わせて調整してください)。

#!/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>タグなどは考慮されていません)。

6
Aaron Graves

これを行う別の方法は、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');
  }
5

または、HTML :: LinkExtorを拡張して必要な処理を実行し、変更を作成者に送信することを検討してください。

4
ysth

以前の回答は完全に良かったし、パーティーに遅れていることはわかっているが、これは[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
4
Ashley

Sherm 推奨 HTML :: LinkExtor 、これはほぼあなたが望むものです。残念ながら、<a>タグ内のテキストを返すことはできません。

Andy 推奨 WWW :: Mechanize 。それがおそらく最良の解決策です。

WWW :: Mechanizeがお好みに合わない場合は、 HTML :: TreeBuilder を試してください。 HTMLからDOMのようなツリーを構築し、必要なリンクを検索して、必要な近くのコンテンツを抽出できます。

4
cjm

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";
        }
    }
3
user13107

HTMLは構造化されたマークアップ言語であり、エラーなしでその意味を抽出するために解析する必要があります。リストされているモジュールShermは、HTMLを解析し、リンクを抽出します。入力が常に同じ方法で形成されることがわかっている場合(属性を忘れないでください)、アドホックな正規表現ベースのソリューションは受け入れられるかもしれませんが、構造化テキストを処理するには、ほとんどの場合、パーサーが正しい答えです。

2
converter42