Suchfunktion in Perl
Maik
- perl
0 Sven Rautenberg0 Maik0 Sven Rautenberg0 Maik
0 Der Linke Setzer
HI Leute,
vielleicht kann mir jemand auf die Sprünge helfen.
Ich hab eine html-Datei und will daraus alle Links ziehen.
Beispiel:
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">
<div align="center">
<p><a href="http://www.abc.de">Link 1</a></p>
<p> </p>
<p><a href="http://www.def.de">Link 2</a></p>
<p> </p>
<p><a href="http://www.ghi.de">Link 3</a></p>
</div>
</body>
</html>
Und nun will ich also nur noch in einer Variable z.B. http://www.abc.de
stehen haben.
Wie kann ich das am besten realisieren?
Ich hab da irgendwas über Reguläre Ausdrücke gelesen, aber hilft mior nicht wirklich weiter.
Also schonmal tausend Dank für eure Hilfe
Wie kann ich das am besten realisieren?
Ich hab da irgendwas über Reguläre Ausdrücke gelesen, aber hilft mior nicht wirklich weiter.
Doch, genau das hilft dir weiter. Reguläre Ausdrücke sind Suchmuster, die ohne großen Programmaufwand finden, was du willst. Wenn du Perl programmierst, komst du um diese Ausdrücke fast nicht drumrum. ;)
http://www.phy.uni-bayreuth.de/~btpa25/perl/perl_main.html
Das hier ist eine brauchbare deutsche Perl-Referenz. Sie geht nicht in die Tiefe, aber für den Anfänger-Hausgebrauch (inkl. regulärer Ausdrücke) reicht es vollkommen aus.
http://www.phy.uni-bayreuth.de/~btpa25/perl/regexp_1.html
Und hier ist das Sonderkapitel "Reguläre Ausdrücke". Lies das mal durch, vollziehe es nach und lerne. Ist nicht schwer. Danach kannst du mit Sicherheit einen entsprechenden regulären Ausdruck formulieren, um ein <a>-Tag zu erkennen und den Bestandteil href in eine Variable zu isolieren.
- Sven Rautenberg
Wie kann ich das am besten realisieren?
Ich hab da irgendwas über Reguläre Ausdrücke gelesen, aber hilft mior nicht wirklich weiter.
Doch, genau das hilft dir weiter. Reguläre Ausdrücke sind Suchmuster, die ohne großen Programmaufwand finden, was du willst. Wenn du Perl programmierst, komst du um diese Ausdrücke fast nicht drumrum. ;)
Ich wollte damit sagen, dass ich daraus bis jetzt noch nicht schlau werde für mein Problem.
http://www.phy.uni-bayreuth.de/~btpa25/perl/perl_main.html
Das hier ist eine brauchbare deutsche Perl-Referenz. Sie geht nicht in die Tiefe, aber für den Anfänger-Hausgebrauch (inkl. regulärer Ausdrücke) reicht es vollkommen aus.
Hab ich schon, aber trotzdem Danke, denn die ist mein Hauptwerkzeug ;-)
http://www.phy.uni-bayreuth.de/~btpa25/perl/regexp_1.html
Und hier ist das Sonderkapitel "Reguläre Ausdrücke". Lies das mal durch, vollziehe es nach und lerne. Ist nicht schwer. Danach kannst du mit Sicherheit einen entsprechenden regulären Ausdruck formulieren, um ein <a>-Tag zu erkennen und den Bestandteil href in eine Variable zu isolieren.
Wie gesagt hab isch schon, aber mir fehlt der Ansatz wie ich das aussortieren soll, denn ich hab ja sozusagen keine direkten festen suchmuster, da sich ja die Links verändern und manchmal auhc "href" an stellen stehen wo keine brauchbaren links für mich sind, wie z.B. bei Stylesheets-Links :(
Aber du hast mir schonmal ein bisschen witergeholfen, denn jetzt weiss ich, dass ich bei den regulären Ausdrücken richtig bin
cu
Maik
Wie gesagt hab isch schon, aber mir fehlt der Ansatz wie ich das aussortieren soll, denn ich hab ja sozusagen keine direkten festen suchmuster, da sich ja die Links verändern und manchmal auhc "href" an stellen stehen wo keine brauchbaren links für mich sind, wie z.B. bei Stylesheets-Links :(
Ok, dann noch ein etwas heißerer Tip:
Du suchst einen Text, der aus '<a' besteht, dann verschiedene, beliebige Zeichen, dann 'href="', dann beliebig viele Zeichen, die nicht '"' sind, und die als Variable gespeichert werden müssen, dann beliebig viele beliebige Zeichen, und dann '>'.
Hinweis: ' ist das Zeichen, um im heißen Tip die Zeichenketten abzutrennen, " ist ein Zeichen des HTML-Textes.
- Sven Rautenberg
Danke für deine Tipps ;-)
Noch ne Frage ..
Wie kann ich denn wenn ich jetzt z.B.
$Antwort=~/href="...">/ ;
mache, das ergebniss in eine Variable speichern?
also, dass dann was hier als "..." in einer Variable steht?
Ich habs schon so versucht:
$XYZ=($Antwort=~/href="...">/);
und so
@XYZ=($Antwort=~/href="...">/);
und so
$Antwort=~/href="...">/ ;
$XYZ=$_;
Aber es ging nicht :(
Ach da fällt mir eine weitere Frage ein:
Was ist denn dann wenn ich mehrere Links habe ?
Scuht der dann weiter und speichert des in nem Array oder wie geht das?
Ich will ja nicht immer den alten Link überschreiben während einer Suche.
Danke für deine Hilfe.
Mit noch paar heißen Tipps komm ich ncoh drauf *g*
cu
Maik
Wie kann ich denn wenn ich jetzt z.B.
$Antwort=~/href="...">/ ;
mache, das ergebniss in eine Variable speichern?
also, dass dann was hier als "..." in einer Variable steht?
Du kannst beliebig viele runde Klammern im regulären Ausdruck setzten. Das, was innerhalb dieser Klammern gefunden wird, wird in spezielle Variablen übertragen, auf die du hinterher zugreifen, sie sichern und verarbeiten kannst.
Mit deinem regulären Ausdruck dort oben wäre das so:
Finde die Zeichenfolge 'href"', dann drei beliebige Zeichen (der Punkt steht für ein beliebiges Zeichen), dann '">'. Das Ergebnis wird wahr, wenn was gefunden wurde, also solltest du das immer mit einer if-Abfrage machen, wenn du willst, daß bei einem Fund was besonderes passiert.
Also:
if ($antwort=~/href="...">/)
{
#hier machen, was beim Finden stattfinden soll
}
Das mit den Klammern ist so: Wenn du wissen willst, welche Zeichen an der Stelle der drei Punkte gefunden werden: Klammere die drei Punkte ein:
if ($antwort=~/href="(...)">/)
{
#Das, was in den Klammern gefunden wurde, steht in $1
#Hurra schreien:
print "href gefunden, Linkziel ist $1";
#Variable für später aufheben:
$linkziel = $1;
}
Das zweite, dritte, vierte... Klammernpaar ist entsprechend in $2, $3 und $4 ... zu finden. Verschachteln geht auch, aber sei da vorsichtig. Ich weiß nicht sicher, was da jeweils zuerst kommt. ;)
Ich habs schon so versucht:
$XYZ=($Antwort=~/href="...">/);
Hier speicherst du wahr oder falsch in $XYZ, je nachdem, ob gefunden oder nicht.
und so
@XYZ=($Antwort=~/href="...">/);
Diese Zuweisung ist falsch, weil @XYZ ein Array ist, das Ergebnis des regulären Ausdrucks aber vom Typ Booelan.
und so
$Antwort=~/href="...">/ ;
$XYZ=$_;
Tja, wenn du mit oben vergleichst, fast ein Treffer... ;)
Aber es ging nicht :(
Ach da fällt mir eine weitere Frage ein:
Was ist denn dann wenn ich mehrere Links habe ?
Der reguläre Ausdruck sucht nur in der Variablen, die vorne dransteht vorn dem =~. Was da nicht drinsteht, wird nicht durchsucht.
Wenn du also eine gesamte Datei durchsuchen willst, dann mußt du die zeilenweise einlesen, jede Zeile durchsuchen, und die gefundenen Zeilen oder Zeilenbestandteile einzeln ausgeben.
Also:
open(HTMLFILE,"htmldateiname.html);
while (<HTMLFILE>)
{
if ($_=~/***HIER REGULÄRER AUSDRUCK***/)
{
print "Hurra, gefunden."
# mit dem Muster von oben...
# speichern, ausgeben, je nachdem, was du willst.
}
}
close(HTMLFILE);
Der Code ist nicht vollständig, dient nur als Ideengeber. ;)
- Sven Rautenberg
open(HTMLFILE,"htmldateiname.html);
while (<HTMLFILE>)
Kannst du mir diese while-Schleife mal genauer erklären..
Die Bedingung ist doch da die Datei und er mach hüpft jetzt also jeden Durchgang
eine Zeile weiter runter oder wie darf ich das jetzt verstehen ?
{
if ($_=~/***HIER REGULÄRER AUSDRUCK***/)
Hat die Umgebungsvariable $_ immer die aktuelle Zeile gespeichert?
Wenn ich mir den Code so anschaue, dann müßte das eigentlich der Fall sein
{
print "Hurra, gefunden."
# mit dem Muster von oben...
# speichern, ausgeben, je nachdem, was du willst.
}
}
close(HTMLFILE);
Der Code ist nicht vollständig, dient nur als Ideengeber. ;)
- Sven Rautenberg
Also mein Quelltext bis jetzt sieht so aus ...
open(HTMLFILE,"datei.txt");
while (<HTMLFILE>)
{
if ($_=~/href="(...)">/)
{
$i=0;
@ergebniss[i]=$1;
$i++;
}
}
close(HTMLFILE);
open (TESTFILE,">ergebnisstest.txt");
print TESTFILE @ergebniss[0];
close (TESTFILE);
In der Datei "datei.txt" ist nur ein Link drin zum testen.
Aber funktioniert nicht. Er erstellt die Datei aber es steht kein Ergebniss drinne ??
Es müsste doch so funktionieren oder ?
cu
Maik
Hallo Maik,
while (<HTMLFILE>)
{
if ($_=~/href="(...)">/)
{
$i=0;
@ergebniss[i]=$1;
$i++;
}
}
Logik!!!!
Du setzt innerhalb einer Schleife den Indexwert $i immer auf 0!
Was erwartest Du dann? Mehr als 1 ????????????????
Viele Grüße Günter
Hallo Maik,
while (<HTMLFILE>)
{
if ($_=~/href="(...)">/)
{
$i=0;
@ergebniss[i]=$1;
$i++;
}
}
Logik!!!!
Du setzt innerhalb einer Schleife den Indexwert $i immer auf 0!
Was erwartest Du dann? Mehr als 1 ????????????????
Viele Grüße Günter
Hast recht war grad neben der Kappe, aber es is dem Fall egal, denn cih hab ja geschrieben, dass nicht mehr als ein Link in der Testdatei ist
--> ischs Wurscht weil die es eh nur einmal aufgerufen wird *g*
cu
Maik
Noch was zur Info:
Inhalt meiner Testdatei
<html><head><title>KSK - STUTTGART</title><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></head><body bgcolor="#FFFFFF"><div align="center"><p>Hallo auf der HP von der Landesbank !</p><p><a href="http://www.lbbw.de">LBBW</a></p></div></body></html>
(alles in einer Zeile)
cu
Maik
HI Leute erstaml Danke, dass ihr mir hier eine ziemlich große Hilfestellung gibt.
Mit den Büchern und Tutorials und euch, blick schon ein bisschen mehr ;-)
Aber ich post euch noch mein gesamte Quelltext, denn eigentlich müßte es funzen, aber es tu nicht :-(
$i=0;
open (HTMLFILE,"test.txt") or die "Datei konnte nicht geöffnet werden";
while (<HTMLFILE>)
{
if ($_=~/href="(...)">/)
{
$ergebniss[$i]=$1;
$i++;
}
}
close(HTMLFILE);
open (TESTFILE,">ergebnisstest.txt");
print TESTFILE $ergebniss[0];
close (TESTFILE);
Der Quellltext meiner "test.txt":
<html><head><title>KSK - FELLBACH</title><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></head><body bgcolor="#FFFFFF"><div align="center"><p>DIES IST DIE SEITE DER SPARKASSE <font color="#FF3333"><b>FELLBACH !!!</b></font></p><p><a href="http://www.si-bw.de">SI-BW</a></p></div></body></html>
[wie gesagt in einer Zeile]
Also wenn ich in die Datei "test.txt" nur <a href="xxx"> reinschreibe, dann funzt es.
Aber ich versteh nicht warum, denn die Bedingung ist doch gleich:
Er soll alles zwischen 'href="' und '">' speichern. Hmm ich glaub moment ich hab ne IDEE....
*tüftel* *tüftel*
Aha also wenn ich bei meiner Datei auch nur 3 Zeichen dazwischen stelle, dann tut es auch, also muss ich nur noch wissen wie es geht, dass
er alles was dazwischen steht ausliest ?????
Und wie geht das? Wie isch denn da die Syntax?
Gruß und vielen Dank
Maik
hi!
open(HTMLFILE,"htmldateiname.html);
while (<HTMLFILE>)
Kannst du mir diese while-Schleife mal genauer erklären..
Die Bedingung ist doch da die Datei und er mach hüpft jetzt also
jeden Durchgang eine Zeile weiter runter oder wie darf ich das
jetzt verstehen ?
Er liest in jedem Durchgang die nächste Zeile der Datei ein und
speichert den Wert in der Spezialvariablen $_.
{
if ($_=~/***HIER REGULÄRER AUSDRUCK***/)
^^^^
Den unterstrichenen Teil ($_=~) kann man weglassen, weil der reg.
Ausdruck sowieso die Variable $_ überprüfen würde, wenn keine andere
angegeben ist.
open(HTMLFILE,"datei.txt");
Besser:
open HTMLFILE, "<datei.txt" or die "Konnte Datei nicht öffnen: $!";
Dann wird zum einen explizit angegeben, dass die Datei zum lesen
geöffnet wird, und zum zweiten erhälst du eine Fehlermeldung und
einen Programmabbruch, wenn das öffnen der Datei nicht geklappt hat.
while (<HTMLFILE>)
{
if ($_=~/href="(...)">/)
Hier überprüfst du auf drei beliebige Zeichen innerhalb der Klammern,
denn . steht in regulären Ausdrücken für genau ein beliebiges
Zeichen. Da musst dur dir also was anderes ausdenken, nämlich indem
du irgendwelche Quantoren[1] verwendest. Da gäbe es zb. folgende:
.? Zeichen muss null- oder einmal vorkommen.
.+ Zeichen muss mindestens einmal vorkommen.
.* Zeichen muss mindestens nullmal vorkommen.
.+? Zeichen muss mindestens einmal vorkommen, allerdings ist der
Ausdruck nicht mehr gierig.
.*? Analog zu .+? und .*.
Was gierig (engl. "greedy") bedeutet, steht sicherlich in jeder guten
Perl-Dokumentation, genauso wie die restlichen Quantoren, die zur
Verfügung stehen. Mit diesen Hilfsmitteln wirst du sicher weiter
kommen... :)
{
$i=0;
Wie schon gesagt: das in jedem Schleifendurchgang zurückzusetzen ist
nicht so günstig.
@ergebniss[i]=$1;
Auf Array-Elemente greift man folgendermaßen korrekt zu:
$ergebnis[$i] = $1;
Wichtig ist der $ vor ergebnis -- übrigens ist Rechtschreibung bei
Variablennamen nicht verboten ;) -- und der $ vor dem i, denn in
Perl müssen Variablen mit ihrem Typ gekennzeichnet sein.
print TESTFILE @ergebniss[0];
Nein, entweder @ergebnis für das komplette Array, oder $ergebnis[0]
für das erste Element.
bye, Frank!
[1] heißen die in regulären Ausdrücken überhaupt so? :)
if ($_=~/href="(...)">/)
Hier überprüfst du auf drei beliebige Zeichen innerhalb der Klammern,
denn . steht in regulären Ausdrücken für genau ein beliebiges
Zeichen. Da musst dur dir also was anderes ausdenken, nämlich indem
du irgendwelche Quantoren[1] verwendest. Da gäbe es zb. folgende:
.? Zeichen muss null- oder einmal vorkommen.
.+ Zeichen muss mindestens einmal vorkommen.
.* Zeichen muss mindestens nullmal vorkommen.
.+? Zeichen muss mindestens einmal vorkommen, allerdings ist der
Ausdruck nicht mehr gierig.
.*? Analog zu .+? und .*.
Was gierig (engl. "greedy") bedeutet, steht sicherlich in jeder guten
Perl-Dokumentation, genauso wie die restlichen Quantoren, die zur
Verfügung stehen. Mit diesen Hilfsmitteln wirst du sicher weiter
kommen... :)
HI Frank dank dir für die Antwort,
ich hab alles verstanden, bis auf wie ich das Lösen kann, dass ich belieb viele Zeichen einlesen kann zwischen
href=" und ">.
Das mit den Quantoren versteh ich nicht :((
cu
Maik
hi!
Das mit den Quantoren versteh ich nicht :((
Dann lies nochmal nach: ;)
</selfhtml/tgcg.htm#a4>
http://www.phy.uni-bayreuth.de/~btpa25/perl/regexp_3.html
bye, Frank!
open(HTMLFILE,"htmldateiname.html);
while (<HTMLFILE>)
Kannst du mir diese while-Schleife mal genauer erklären..
Die Bedingung ist doch da die Datei und er mach hüpft jetzt also jeden Durchgang
eine Zeile weiter runter oder wie darf ich das jetzt verstehen ?
Die Anweisung <HTMLFILE> hat Auswirkungen je nach Kontext.
Im Prinzip liest diese Anweisung aus einer Datei. Man kann also schreiben: $lesezeile = <HTMLFILE>. Dann hat die Variable $lesezeile die nächste Zeile der Datei.
Man kann auch schreiben: @allezeilen = <HTMLFILE>. Dann werden alle Zeilen in das Array @allezeilen gepackt. Das verbraucht allerdings mehr Speicher, eine 2MB-Datei braucht mindestens mal 2MB Speicher dafür.
Die Anweisung <HTMLFILE> ist identisch mit $_ = <HTMLFILE>.
Und die while-Schleife liest nun solange, wie aus der Datei gelesen werden kann. Die Anweisung $_ = <HTMLFILE>, oder kurz <HTMLFILE> gibt "false" zurück, wenn sie aufgrund des Dateiendes nicht mehr ausgeführt werden kann, und endet so. Während des erfolgreichen Lesens gibt sie "true" zurück, und while läuft weiter.
Also mein Quelltext bis jetzt sieht so aus ...
open(HTMLFILE,"datei.txt");
Machen wir's mal ganz ordentlich:
open (HTMLFILE,"datei.txt") or die "Datei konnte nicht geöffnet werden";
while (<HTMLFILE>)
{
if ($_=~/href="(...)">/)
Hier muß natürlich dein passender regulärer Ausdruck rein. Die Aufgabe, mal einen zu erfinden, wollte ich dir eigentlich überlassen. Die Strategie, nach was du suchen sollst, hab ich dir ja schon erklärt. :) Deswegen findet er im Moment wohl auch nichts.
{
$i=0;
Böse Falle: Wenn du $i in der Schleife immer wieder auf Null setzt, wird auch immer wieder das nullte Element des Arrays angesprochen. Pack diese Anweisung nach außerhalb, vor die while-Schleife.
@ergebniss[i]=$1;
Falsche Zuweisung. Merke: $ = $, @ = @. Richtig ist:
$ergebnis[$i] = $1;
$i++;
}
}
close(HTMLFILE);
open (TESTFILE,">ergebnisstest.txt");
print TESTFILE @ergebniss[0];
Gleiche Problematik. Das komplette Array heißt @ergebnis, ein Element heißt $ergebnis[NUMMER]. Richtig wäre also auch hier
print TESTFILE $ergebnis[0];
close (TESTFILE);
In der Datei "datei.txt" ist nur ein Link drin zum testen.
Wenn du dort als Link mal reinschreibst: <a href="xxx">, dann sollte es funktionieren. Frag nicht nach dem Sinn des Links. ;)
- Sven Rautenberg
Ich hab eine html-Datei und will daraus alle Links ziehen.
Wie kann ich das am besten realisieren?
http://search.cpan.org/doc/GAAS/HTML-Parser-3.25/lib/HTML/LinkExtor.pm