Jak mogę wyodrębnić URL i link tekst z HTML w Perlu?
Wcześniej pytałem, jak to zrobić w Groovy. Jednak teraz przepisuję moją aplikację w Perlu ze względu na wszystkie biblioteki CPAN.
Jeśli strona zawierała te linki:
<a href="http://www.google.com">Google</a> <a href="http://www.apple.com">Apple</a>
Wyjście będzie:
Google, http://www.google.com Apple, http://www.apple.com
Jaki jest najlepszy sposób, aby to zrobić w Perlu?
11 answers
Prosimy o zapoznanie się z Modułem WWW::Mechanize . Pobierze za Ciebie Twoje strony internetowe, a następnie zapewni Ci łatwą pracę z listami adresów 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;
}
Całkiem proste, a jeśli chcesz przejść do innych adresów URL na tej stronie, jest jeszcze prostsze.
Mech jest w zasadzie przeglądarką w obiekcie.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 20:04:34
Spójrz na HTML::LinkExtractor i HTML::LinkExtor, część pakietu HTML::Parser.
HTML:: LinkExtractor jest podobny do HTML:: LinkExtor, z tą różnicą, że oprócz uzyskania adresu URL, otrzymujesz również tekst linku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-25 10:55:51
Jeśli jesteś poszukiwaczem przygód i chcesz spróbować bez modułów, coś takiego powinno zadziałać (dostosuj to do swoich potrzeb):
#!/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";
}
Jest prawdopodobnie kilka rzeczy, które zrobiłem źle, ale działa to w kilku przypadkach testowych, które próbowałem po napisaniu (nie uwzględnia rzeczy takich jak tagi itp.).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-04 20:39:14
Lubię używać pQuery do takich rzeczy...
use pQuery;
pQuery( 'http://www.perlbuzz.com' )->find( 'a' )->each(
sub {
say $_->innerHTML . q{, } . $_->getAttribute( 'href' );
}
);
Również sprawdź ten poprzedni stackoverflow.com question Emulacja funkcji lex like w Perlu lub Pythonie dla podobnych odpowiedzi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:42
Innym sposobem na to jest użycie XPath do odpytywania przetworzonego HTML. Jest to potrzebne w skomplikowanych przypadkach, takich jak wyodrębnienie wszystkich linków w div z określoną klasą. W tym celu użyj 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');
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-05 17:49:25
Sherm recommended HTML:: LinkExtor , czyli prawie to, czego chcesz. Niestety, nie można zwrócić tekstu wewnątrz znacznika .
Andy poleca WWW:: Mechanize . To chyba najlepsze rozwiązanie.
Jeśli nie podoba ci się Strona WWW::Mechanize, spróbuj HTML::TreeBuilder. Zbuduje drzewo podobne do DOM z HTML, które można następnie wyszukać linki, które chcesz i wyodrębnić dowolną pobliską zawartość chcesz.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:01
Lub rozważ ulepszenie HTML:: LinkExtor, aby zrobić to, co chcesz i przesłać zmiany do autora.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-02 02:43:11
Poprzednie odpowiedzi były całkiem dobre i Wiem, że jestem spóźniony na imprezę, ale to wpadło w kanał [perl], więc ...
XML:: LibXML jest doskonały do parsowania HTML i nie do pobicia pod względem szybkości. Ustawia opcję recover
podczas parsowania źle uformowanego HTML.
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>
–{–4]}
Google -> http://www.google.com
Apple -> http://www.apple.com
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-22 23:10:38
HTML:: LinkExtractor jest lepszy / a niż HTML:: LinkExtor
Może podać zarówno tekst linku, jak i adres URL.
Użycie:
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";
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-25 11:00:18
HTML jest strukturalnym językiem znaczników, który musi być parsowany, aby wydobyć jego znaczenie bez błędów. Wymieniony moduł Sherm przetworzy kod HTML i wyodrębni linki dla Ciebie. Rozwiązania ad hoc oparte na wyrażeniach regularnych mogą być akceptowalne, jeśli wiesz, że Twoje dane wejściowe będą zawsze tworzone w ten sam sposób( nie zapomnij o atrybutach), ale parser jest prawie zawsze właściwą odpowiedzią na przetwarzanie tekstu strukturalnego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 18:49:00
Możemy użyć wyrażenia regularnego, aby wyodrębnić link z jego tekstem. Jest to również jedyny sposób.
local $/ = '';
my $a = <DATA>;
while( $a =~ m/<a[^>]*?href=\"([^>]*?)\"[^>]*?>\s*([\w\W]*?)\s*<\/a>/igs )
{
print "Link:$1 \t Text: $2\n";
}
__DATA__
<a href="http://www.google.com">Google</a>
<a href="http://www.apple.com">Apple</a>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-29 09:36:48