Verwendung von grep und cut in script zum Abrufen von Website-URLs aus einer HTML-Datei


21

Ich versuche, grep and cut zu verwenden, um URLs aus einer HTML-Datei zu extrahieren. Die Links sehen so aus:

<a href="http://examplewebsite.com/">

Andere Websites haben .net, .govaber ich gehe davon aus, dass ich den Cut-Off-Punkt direkt vorher machen könnte >. Also weiß ich, dass ich grep und cut irgendwie verwenden kann, um alles vor http und nach .com abzuschneiden, aber ich bin schon eine Weile dabei geblieben.


Ich habe es bearbeitet. Für einige, die den Abstand zwischen <und a ignorieren, würde der HTML-Code ohne ihn nicht angezeigt. Danke, dass du das verstanden hast!
eltigre

Verwenden Sie die Code-Formatierung (markieren Sie den Text und drücken Sie Strg-K). Andernfalls <>erzwingt das, dass es als HTML-Tag betrachtet wird.
Muru

Warum nicht das Eröffnungs- und Endzitat des href-Parameters abgleichen? Außerdem glaube ich, dass reguläre Ausdrücke nicht am besten für HTMLs geeignet sind.
把 把 友情 留 在 盐

Ich möchte einen Befehl schreiben, der speziell grep und cut verwendet, um dies zu tun. Mir ist klar, dass es andere Wege gibt, aber ich wollte davon wissen.
eltigre

9
Im Allgemeinen ist es keine gute Idee, HTML mit regulären Ausdrücken zu analysieren, da HTML keine reguläre Sprache ist. Wenn Sie sicherstellen können , dass der HTML-Code, den Sie analysieren, recht einfach ist und der Inhalt, den Sie extrahieren möchten, vorhersehbar ist, können Sie ihn möglicherweise umgehen . Aber bitte sehen Sie stackoverflow.com/a/1732454/4014959
PM 2Ring

Antworten:


25

Wie ich in meinem Kommentar sagte, ist es im Allgemeinen keine gute Idee, HTML mit regulären Ausdrücken zu analysieren, aber Sie können manchmal damit durchkommen, wenn sich das HTML, das Sie analysieren, gut verhält.

Um nur URLs zu erhalten, die in den hrefAttributen von <a>Elementen enthalten sind, ist es für mich am einfachsten, sie in mehreren Schritten auszuführen. Aus Ihren Kommentaren geht hervor, dass Sie nur die Top-Level-Domain und nicht die vollständige URL wünschen. In diesem Fall können Sie Folgendes verwenden:

grep -Eoi '<a [^>]+>' source.html |
grep -Eo 'href="[^\"]+"' | 
grep -Eo '(http|https)://[^/"]+'

Wo source.htmlist die Datei, die den zu analysierenden HTML-Code enthält?

Dieser Code gibt alle URLs der obersten Ebene aus, die als hrefAttribut aller <a>Elemente in jeder Zeile auftreten. Die -iOption für den ersten grepBefehl besteht darin, sicherzustellen, dass er sowohl für Elemente <a>als auch für <A>Elemente funktioniert . Ich vermute, Sie könnten auch -idie 2. eingeben, grepum HREFAttribute in Großbuchstaben zu erfassen , OTOH. :)

Zum Verarbeiten des Inhalts von http://google.com/

wget -qO- http://google.com/ |
grep -Eoi '<a [^>]+>' | 
grep -Eo 'href="[^\"]+"' | 
grep -Eo '(http|https)://[^/"]+'

Ausgabe

http://www.google.com.au
http://maps.google.com.au
https://play.google.com
http://www.youtube.com
http://news.google.com.au
https://mail.google.com
https://drive.google.com
http://www.google.com.au
http://www.google.com.au
https://accounts.google.com
http://www.google.com.au
https://www.google.com
https://plus.google.com
http://www.google.com.au

Meine Ausgabe unterscheidet sich ein wenig von den anderen Beispielen, da ich auf die australische Google-Seite weitergeleitet werde.


DANKE DIR. Das ist genau das, wonach ich gesucht habe. Dies ist der sauberste Weg, dies zu tun.
eltigre

@eltigre: Es ist mir ein Vergnügen! Beachten Sie jedoch bitte die Warnung, auf die ich in meinem obigen Kommentar verwiesen habe. :)
PM 2Ring

Ich bin auf diese Frage gekommen, weil ich einfache Punkte erwartet hatte ... und du hättest schon den Nagel auf den Kopf getroffen
Mark K. Cowan,

Vielen Dank, @ MarkKCowan. :) FWIW, ich habe ursprünglich angefangen, eine Antwort mit awk zu schreiben, aber dann habe ich beschlossen, dass eine grep-basierte Lösung für diejenigen, die nicht mit awk vertraut sind, einfacher zu verstehen ist. Der obige Code ist jedoch kürzer als mein awk-Code.
PM 2Ring

2
@mavavilj: Da das OP nur die Top-Level-Domain haben wollte, ://akzeptieren wir nach dem nur noch Zeichen vor dem ersten /oder ". Wenn Sie jedoch die vollständige URL anzeigen möchten, ändern Sie diesen Befehl in grep -Eo '(http|https)://[^"]+. Eine weitere Option für diese Zeile ist grep -Eo '(http|https)://[^?"]+'das Ausschneiden von Abfrageoptionen. Diese Variante gibt jedoch weiterhin URLs aus, die in einer anderen URL als Abfrageparameter enthalten sind, sie werden jedoch in einer separaten Zeile gedruckt.
PM 2Ring

25

Nicht sicher, ob Sie auf Werkzeuge beschränkt sind:

Aber Regex ist vielleicht nicht der beste Weg, wie erwähnt, aber hier ist ein Beispiel, das ich zusammengestellt habe:

cat urls.html | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
  • grep -E: ist dasselbe wie egrep
  • grep -o: gibt nur das aus, was gegriffen wurde
  • (http | https): ist entweder / oder
  • az: ist alles in Kleinbuchstaben
  • AZ: Ist alles in Ordnung
  • . : ist Punkt
  • \ ?: ist?
  • *: ist die Wiederholung der [...] Gruppe
  • uniq: entfernt alle Duplikate

Ausgabe:

bob@bob-NE722:~s$  wget -qO- https://stackoverflow.com/ | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
https://stackauth.com
https://meta.stackoverflow.com
https://cdn.sstatic.net/Img/svg-icons
https://stackoverflow.com
https://www.stackoverflowbusiness.com/talent
https://www.stackoverflowbusiness.com/advertising
https://stackoverflow.com/users/login?ssrc=head
https://stackoverflow.com/users/signup?ssrc=head
https://stackoverflow.com
https://stackoverflow.com/help
https://chat.stackoverflow.com
https://meta.stackoverflow.com
...

Sie können auch hinzufügen \d, um andere Zifferntypen abzufangen.


2
IRI Regexes! Verwenden Sie einen von ihnen und erschrecken Sie den OP! :)
muru

2
@muru ... Schüttelfrost ich ... Ich weiß nicht , was ich sagen soll. Sind die überhaupt echt !?
jmunsch

4
@jmunsch, uniq entferne nur benachbarte Duplikate. sort -u?
JJoao,

1
es funktioniert super, beste antwort !!
Gery

@JJoao ist die Quelle für sort -u schneller als Piping? Nur ein Gedankenexperiment, ich muss schauen. Aber Sie haben wahrscheinlich Recht, was die Shell-Middleware betrifft.
Jmunsch

9

Wenn Ihr grep Perl-Regexes unterstützt:

grep -Po '(?<=href=")[^"]*(?=")'
  • (?<=href=")und (?=")sind Lookaround- Ausdrücke für das hrefAttribut. Dies erfordert die -POption.
  • -o druckt den passenden Text.

Beispielsweise:

$ curl -sL https://www.google.com | grep -Po '(?<=href=")[^"]*(?=")'
/search?
https://www.google.co.in/imghp?hl=en&tab=wi
https://maps.google.co.in/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
https://www.youtube.com/?gl=IN&tab=w1
https://news.google.co.in/nwshp?hl=en&tab=wn
...

Wie üblich kann nicht garantiert werden, dass es sich um gültige URIs handelt oder dass der von Ihnen analysierte HTML-Code gültig ist.


8

Verwenden Sie als nicht reguläre Alternative pup :

pup 'a[href] attr{href}' < yourfile.html

Findet alle aElemente, die ein hrefAttribut haben, und zeigt dann den Wert des hrefAttributs an.

Zur Installation pupbenötigen Sie Go (eine Programmiersprache):

sudo apt-get install golang
sudo go get github.com/ericchiang/pup

Der Vorteil dieser Lösung besteht darin, dass das HTML nicht ordnungsgemäß formatiert werden muss .


1
+1 für pup, Zeit, um das zu installieren ....
Mark K Cowan

Sie können sie auch in einer Datei ablegen. pup 'a.classname[href] attr{href}' < tut.html >links.md
Ahmad Awais

1

Ich habe hier eine Lösung gefunden , die meiner Meinung nach viel einfacher und potenziell schneller ist als das, was hier vorgeschlagen wurde. Ich habe ein wenig angepasst, um https-Dateien zu unterstützen. Aber die TD; TR-Version ist ...

PS: Sie können die Site-URL durch einen Pfad zu einer Datei ersetzen, und das funktioniert genauso.

lynx -dump -listonly -nonumbers "http://www.goggle.com" > links.txt

lynx -dump -listonly -nonumbers "some-file.html" > links.txt

Wenn Sie nur die Links sehen möchten, anstatt sie in einer Datei zu platzieren, versuchen Sie dies stattdessen ...

lynx -dump -listonly -nonumbers "http://www.google.com"

lynx -dump -listonly -nonumbers "some-file.html"

Das Ergebnis sieht ungefähr so ​​aus ...

http://www.google.ca/imghp?hl=en&tab=wi
http://maps.google.ca/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
http://www.youtube.com/?gl=CA&tab=w1
http://news.google.ca/nwshp?hl=en&tab=wn
https://mail.google.com/mail/?tab=wm
https://drive.google.com/?tab=wo
https://www.google.ca/intl/en/options/
http://www.google.ca/history/optout?hl=en
...
etc.

Für meinen Anwendungsfall hat dies einwandfrei funktioniert. Hüten Sie sich jedoch vor der Tatsache, dass heutzutage Links wie src = "// blah.tld" für die CDN-URI von Bibliotheken hinzugefügt werden. Ich wollte die in den abgerufenen Links nicht sehen.

Sie müssen nicht versuchen, nach href oder anderen Quellen für Links zu suchen, da "lynx -dump" standardmäßig alle anklickbaren Links von einer bestimmten Seite extrahiert. Der einzige Gedanke, den Sie danach tun müssen, ist, das Ergebnis von "lynx -dump" mit grep zu analysieren, um eine sauberere Rohversion desselben Ergebnisses zu erhalten.


Die Frage lautet jedoch "URLs aus einer HTML- Datei extrahieren , die so aussieht" (Beispiel), NICHT "URLs aus einer Webseite extrahieren". Wenn Ihre Antwort für eine Datei verwendet werden kann, die sich auf dem lokalen Computer befindet, erläutern Sie, wie. Bitte antworten Sie nicht in Kommentaren; Bearbeiten Sie Ihre Antwort, um sie klarer und vollständiger zu gestalten.
G-Man sagt, dass Monica

1
Sie können die URL durch einen Dateinamen ersetzen.
Asiby

@ G-Man, warum die -1? Sie müssen den Code selbst ausprobieren und sicherstellen, dass er auch für lokale Dateien funktioniert. Ich habe diese Klarstellung hinzugefügt, falls es nicht offensichtlich war.
Asiby

Dies ist sehr praktisch. Wenn Sie mit xargs arbeiten, lohnt es sich, | hinzuzufügen sortieren | Uniq zum Trimmen der doppelten Links.
Stuart Axon

0
wget -qO- google.com |
tr \" \\n | grep https\*://

... würde sich wohl ganz gut machen. Wie geschrieben wird gedruckt:

http://schema.org/WebPage
http://www.google.com/imghp?hl=en&tab=wi
http://maps.google.com/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
http://www.youtube.com/?tab=w1
http://news.google.com/nwshp?hl=en&tab=wn
https://mail.google.com/mail/?tab=wm
https://drive.google.com/?tab=wo
http://www.google.com/intl/en/options/
http://www.google.com/history/optout?hl=en
https://accounts.google.com/ServiceLogin?hl=en&continue=http://www.google.com/
https://www.google.com/culturalinstitute/project/the-holocaust?utm_source=google&amp;utm_medium=hppromo&amp;utm_campaign=auschwitz_q1&amp;utm_content=desktop
https://plus.google.com/116899029375914044550

Wenn es wichtig ist, dass Sie nur Links und Domains der obersten Ebene zuordnen, können Sie Folgendes tun:

wget -qO- google.com |
sed '/\n/P;//!s|<a[^>]*\(https*://[^/"]*\)|\n\1\n|;D'

... oder so ähnlich - für einige seds müssen Sie jedoch möglicherweise \njedes der letzten beiden ns durch ein wörtliches ewline-Zeichen ersetzen .

Der obige Befehl gibt wie geschrieben aus:

http://www.google.com
http://maps.google.com
https://play.google.com
http://www.youtube.com
http://news.google.com
https://mail.google.com
https://drive.google.com
http://www.google.com
http://www.google.com
http://www.google.com
https://www.google.com
https://plus.google.com

... und in beiden Fällen (aber wahrscheinlich am nützlichsten bei letzteren) können Sie einen |sort -uFilter bis zum Ende anheften , um die Liste zu sortbearbeiten und Duplikate zu löschen.



-1
echo "<a href="http://examplewebsite.com/">"|sed -r 's:<.*"::g'|sed 's:/">$::g'

Ich bin mir nicht sicher, ob diese "intelligenten" Anführungszeichen das sind, was Sie dort beabsichtigt haben - vielleicht normale "doppelte" Anführungszeichen?
Jeff Schaller
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.