it-swarm.com.de

Die einfachste Möglichkeit, die URLs aus einer HTML-Seite nur mit sed oder awk zu extrahieren

Ich möchte die URL aus den Ankertags einer HTML-Datei extrahieren. Dies muss in BASH mit SED/AWK erfolgen. Kein Perl bitte.

Was ist der einfachste Weg, dies zu tun?

52
codaddict

Sie könnten auch so etwas tun (vorausgesetzt, Sie haben Luchs installiert) ...

Lynx-Versionen <2.8.8

lynx -dump -listonly my.html

Lynx-Versionen> = 2.8.8 (mit freundlicher Genehmigung von @condit)

lynx -dump -hiddenlinks=listonly my.html
53
Hardy

Du hast danach gefragt:

$ wget -O - http://stackoverflow.com | \
  grep -o '<a href=['"'"'"][^"'"'"']*['"'"'"]' | \
  sed -e 's/^<a href=["'"'"']//' -e 's/["'"'"']$//'

Dies ist ein grobes Werkzeug, daher gelten alle üblichen Warnungen vor dem Versuch, HTML mit regulären Ausdrücken zu analysieren.

35
Greg Bacon
grep "<a href=" sourcepage.html
  |sed "s/<a href/\\n<a href/g" 
  |sed 's/\"/\"><\/a>\n/2'
  |grep href
  |sort |uniq
  1. Das erste grep sucht nach Zeilen, die URLs enthalten. Sie können weitere Elemente nach .__ hinzufügen, wenn Sie nur auf lokalen Seiten suchen möchten, also kein http, sondern Relativer Pfad.
  2. Der erste sed fügt vor jedem a href url-Tag einen Newline mit dem\n ein
  3. Der zweite sed verkürzt jede URL nach dem zweiten "in der Zeile, indem er sie mit dem Tag/a durch eine Newline .__ ersetzt. Beide Seds geben Ihnen jede URL in einer einzelnen Zeile, aber es gibt Müll
  4. Der zweite Grep href räumt das Chaos auf
  5. Durch sort und uniq erhalten Sie eine Instanz jeder vorhandenen in der sourcepage.html vorhandenen URL
14
kerkael

Mit dem Xidel - HTML/XML-Datenextraktionswerkzeug kann dies über Folgendes erfolgen:

$ xidel --extract "//a/@href" http://example.com/

Bei der Konvertierung in absolute URLs:

$ xidel --extract "//a/resolve-uri(@href, base-uri())" http://example.com/
13
Ingo Karkat

Ein Beispiel, da Sie keine Probe bereitgestellt haben

awk 'BEGIN{
RS="</a>"
IGNORECASE=1
}
{
  for(o=1;o<=NF;o++){
    if ( $o ~ /href/){
      gsub(/.*href=\042/,"",$o)
      gsub(/\042.*/,"",$o)
      print $(o)
    }
  }
}' index.html
11
ghostdog74

Ich habe ein paar Änderungen an Greg Bacon Solution vorgenommen

cat index.html | grep -o '<a .*href=.*>' | sed -e 's/<a /\n<a /g' | sed -e 's/<a .*href=['"'"'"]//' -e 's/["'"'"'].*$//' -e '/^$/ d'

Dies behebt zwei Probleme:

  1. Wir stimmen mit Fällen überein, in denen der Anker nicht mit href als erstes Attribut beginnt 
  2. Wir behandeln die Möglichkeit, mehrere Anker in derselben Linie zu haben
9
Crisboot

Ich gehe davon aus, dass Sie eine URL aus einem HTML-Text extrahieren und nicht HTML analysieren möchten (wie in einem der Kommentare angegeben). Ob Sie es glauben oder nicht, jemand hat bereits dies getan .

OT: Die sed website hat eine Menge guter Informationen und viele interessante/verrückte sed-Skripte. Sie können sogar spielenSokoban in sed!

5
Alok Singhal

Mit dem folgenden regulären Ausdruck können Sie dies ganz leicht tun, um URLs zu finden:

\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))

Ich habe es aus John Grubers Artikel über das Finden von URLs im Text entnommen.

So können Sie alle URLs in einer Datei f.html wie folgt finden:

cat f.html | grep -o \
    -E '\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'
4
nes1983

Erweiterung auf kerkaels Antwort :

grep "<a href=" sourcepage.html
  |sed "s/<a href/\\n<a href/g" 
  |sed 's/\"/\"><\/a>\n/2'
  |grep href
  |sort |uniq
# now adding some more
  |grep -v "<a href=\"#"
  |grep -v "<a href=\"../"
  |grep -v "<a href=\"http"

Das erste, das ich hinzugefügt habe, entfernt Links zu lokalen Lesezeichen.

Die zweite entfernt relative Links zu höheren Ebenen.

Der dritte entfernt Links, die nicht mit http beginnen.

Wählen Sie aus, welche davon Sie für Ihre spezifischen Anforderungen verwenden.

1
Nikhil VJ

Machen Sie einen ersten Durchgang und ersetzen Sie den Anfang der URLs (http) durch eine neue Zeile (\n Http). Dann haben Sie sich versichert, dass Ihr Link am Anfang der Zeile beginnt und die einzige URL in der Zeile ist.

Der Rest sollte einfach sein, hier ein Beispiel:

sed "s/http/\nhttp/g" <(curl "http://www.cnn.com") | sed -n "s/\(^http[s]*:[a-Z0-9/.=?_-]*\)\(.*\)/\1/p"

alias lsurls='_(){ sed "s/http/\nhttp/g" "${1}" | sed -n "s/\(^http[s]*:[a-Z0-9/.=?_-]*\)\(.*\)/\1/p"; }; _'

1
user4401178

In Bash sollte Folgendes funktionieren. Beachten Sie, dass es nicht sed oder awk verwendet, sondern tr und grep, beide sehr standard und nicht Perl ;-)

$ cat source_file.html | tr '"' '\n' | tr "'" '\n' | grep -e '^https://' -e '^http://' -e'^//' | sort | uniq

zum Beispiel:

$ curl "https://www.cnn.com" | tr '"' '\n' | tr "'" '\n' | grep -e '^https://' -e '^http://' -e'^//' | sort | uniq

erzeugt

//s3.amazonaws.com/cnn-sponsored-content
//Twitter.com/cnn
https://us.cnn.com
https://www.cnn.com
https://www.cnn.com/2018/10/27/us/new-york-hudson-river-bodies-identified/index.html\
https://www.cnn.com/2018/11/01/tech/google-employee-walkout-andy-rubin/index.html\
https://www.cnn.com/election/2016/results/exit-polls\
https://www.cnn.com/profiles/frederik-pleitgen\
https://www.facebook.com/cnn
etc...
0
Brad Parks

So habe ich es für eine bessere Ansicht ausprobiert, eine Shell-Datei erstellt und den Link als Parameter angegeben. Es wird die Datei temp2.txt erstellt.

a=$1

lynx -listonly -dump "$a" > temp

awk 'FNR > 2 {print$2}' temp > temp2.txt

rm temp

>sh test.sh http://link.com
0
Abhishek Gurjar

Du kannst es versuchen:

curl --silent -u "<username>:<password>" http://<NAGIOS_Host/nagios/cgi-bin/status.cgi|grep 'extinfo.cgi?type=1&Host='|grep "status"|awk -F'</A>' '{print $1}'|awk -F"'>" '{print $3"\t"$1}'|sed 's/<\/a>&nbsp;<\/td>//g'| column -c2 -t|awk '{print $1}'
0
dpathak

Dies ist mein erster Beitrag, daher versuche ich mein Bestes zu geben, um zu erklären, warum ich diese Antwort veröffentliche ...

  1. Seit den ersten 7 Antworten, die am häufigsten gewählt wurden, enthalten 4 GREP, auch wenn in dem Beitrag explizit "using sed or awk only" steht.
  2. Auch wenn der Post "No Perl please" erfordert, aufgrund des vorherigen Punktes und weil Perl regex in grep verwendet wird.
  3. und weil dies der einfachste Weg ist (soweit ich weiß und es erforderlich war), dies in BASH zu tun.

Also hier kommt das einfachste Skript aus GNU grep 2.28:

grep -Po 'href="\K.*?(?=")'

Über die \K switch, es wurden keine Informationen in MAN und INFO-Seiten gefunden, also kam ich hier für die Antwort .... der \K switch löscht die vorherigen Zeichen (und den Schlüssel selbst). Beachten Sie die Hinweise in den Manpages: "Dies ist sehr experimentell und grep -P kann vor nicht implementierten Funktionen warnen."

Natürlich können Sie das Skript an Ihren Geschmack oder Ihre Bedürfnisse anpassen, aber ich fand es ziemlich direkt für das, was in der Post angefordert wurde, und auch für viele von uns ...

Ich hoffe, Leute, Sie finden es sehr nützlich.

vielen Dank!!!

0
X00D45