Come utilizzare grep e tagliare gli script per ottenere gli URL dei siti Web da un file HTML


21

Sto cercando di utilizzare grep e cut per estrarre gli URL da un file HTML. I collegamenti sembrano:

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

Altri siti Web hanno .net, .govma suppongo che potrei fare il punto di interruzione proprio prima >. Quindi so che posso usare grep e tagliare in qualche modo per tagliare tutto prima di http e dopo .com, ma sono rimasto bloccato per un po '.


L'ho modificato. Per alcuni ignorare lo spazio tra <e a, l'HTML non verrebbe visualizzato senza di esso. Grazie per averlo catturato!
eltigre,

Usa la formattazione del codice (seleziona il testo e premi Ctrl-K). Altrimenti lo <>costringe a essere visto come un tag HTML.
Muru,

perché non abbinare la citazione di apertura e di fine del parametro href? inoltre, credo che le espressioni regolari non siano più adatte agli html.
把 友情 留 在 无 盐

Voglio scrivere un comando usando specificamente grep e tagliare per farlo. Mi rendo conto che ci sono altri modi, ma volevo sapere di quelli.
eltigre,

9
In generale non è una buona idea analizzare l'HTML con le espressioni regolari, poiché l'HTML non è un linguaggio normale. Se si riesce a garantisce che il codice HTML voi sono l'analisi è abbastanza semplice, e la roba si sta cercando di estrarre è prevedibile che si può essere in grado di farla franca. Ma vedere stackoverflow.com/a/1732454/4014959
PM 2Ring

Risposte:


25

Come ho detto nel mio commento, generalmente non è una buona idea analizzare HTML con espressioni regolari, ma a volte puoi cavartela se l'HTML che stai analizzando è ben educato.

Per ottenere solo URL che si trovano hrefnell'attributo di <a>elementi, trovo più semplice farlo in più fasi. Dai tuoi commenti, sembra che tu voglia solo il dominio di primo livello, non l'URL completo. In tal caso puoi usare qualcosa del genere:

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

dove si source.htmltrova il file contenente il codice HTML da analizzare.

Questo codice stamperà tutti gli URL di livello superiore che si presentano come l' hrefattributo di tutti gli <a>elementi in ciascuna riga. L' -iopzione per il primo grepcomando è assicurarsi che funzionerà su entrambi <a>e sugli <A>elementi. Suppongo che potresti anche dare -ial 2 ° grepper catturare gli HREFattributi maiuscoli , OTOH, preferirei ignorare un HTML così rotto. :)

Per elaborare il contenuto di http://google.com/

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

produzione

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

Il mio output è leggermente diverso dagli altri esempi quando vengo reindirizzato alla pagina Google australiana.


GRAZIE. Questo è esattamente quello che stavo cercando. Questo è il modo più pulito per farlo.
eltigre,

@eltigre: piacere mio! Ma per favore fai attenzione all'avvertimento che ho collegato nel mio commento sopra. :)
PM 2Ring

Sono arrivato a questa domanda aspettandomi dei punti facili ... e avresti già colpito completamente l'unghia sulla testa
Mark K Cowan,

Grazie, @MarkKCowan. :) FWIW, inizialmente ho iniziato a scrivere una risposta usando awk, ma poi ho deciso che una soluzione basata su grep sarebbe stata più facile da capire per chi non avesse familiarità con awk. E comunque, il codice sopra è più corto del mio codice awk.
PM 2Ring

2
@mavavilj: Perché l'OP voleva solo il dominio di primo livello, quindi dopo ://accettiamo solo i caratteri prima del primo /o ". Ma se vuoi vedere l'URL completo, modifica quel comando in grep -Eo '(http|https)://[^"]+. Un'altra opzione per quella linea è grep -Eo '(http|https)://[^?"]+'che interrompe le opzioni di query. Tuttavia, tale variante stamperà comunque gli URL contenuti in un altro URL come parametro di query, ma verranno stampati su una riga separata.
PM 2Ring

25

Non sono sicuro se sei limitato agli strumenti:

Ma regex potrebbe non essere il modo migliore di procedere come indicato, ma ecco un esempio che ho messo insieme:

cat urls.html | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
  • grep -E: è uguale a egrep
  • grep -o: restituisce solo ciò che è stato grepped
  • (http | https): è un / o
  • az: è tutto minuscolo
  • AZ: è tutto migliorato
  • . : è punto
  • \ ?: è?
  • *: è ripetere il gruppo [...]
  • uniq: rimuoverà tutti i duplicati

Produzione:

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
...

È inoltre possibile aggiungere \dper catturare altri tipi numerici.


2
Regexes dell'IRI! Usane uno e spaventa l'OP! :)
muru,

2
@muru ... rabbrividendo io ... non so cosa dire. Sono anche reali !?
Jmunsch,

4
@jmunsch, uniq rimuove solo i duplicati adiacenti. sort -u?
JJoao,

1
funziona alla grande, migliore risposta !!
Gery,

@JJoao è la fonte per ordinare -u più veloce delle tubazioni? Solo un esperimento mentale, devo guardare. Ma probabilmente hai ragione, riguardo al middleware shell.
Jmunsch,

9

Se il tuo grep supporta le regex del Perl:

grep -Po '(?<=href=")[^"]*(?=")'
  • (?<=href=")e (?=")sono espressioni lookaround per l' hrefattributo. Questo ha bisogno -Pdell'opzione.
  • -o stampa il testo corrispondente.

Per esempio:

$ 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
...

Come al solito, non esiste alcuna garanzia che si tratti di URI validi o che l'HTML che stai analizzando sia valido.


8

Come alternativa non regex , usa pup :

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

Individua tutti gli aelementi che hanno un hrefattributo, quindi visualizza il valore hrefdell'attributo.

Per installare pup, è necessario Go (un linguaggio di programmazione):

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

Il vantaggio di questa soluzione è che non si basa sulla formattazione corretta dell'HTML .


1
+1 per pup, tempo di installarlo ....
Mark K Cowan,

Puoi anche metterli in archivio. pup 'a.classname[href] attr{href}' < tut.html >links.md
Ahmad Awais,

1

Ho trovato una soluzione qui che è IMHO molto più semplice e potenzialmente più veloce di quanto è stato proposto qui. Ho modificato un po 'per supportare i file https. Ma la versione TD; TR è ...

PS: puoi sostituire l'URL del sito con un percorso a un file e funzionerà allo stesso modo.

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

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

Se vuoi solo vedere i link invece di metterli in un file, prova questo invece ...

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

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

Il risultato sarà simile al seguente ...

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.

Nel mio caso d'uso, ha funzionato bene. Ma attenzione al fatto che oggigiorno le persone aggiungono collegamenti come src = "// blah.tld" per l'URI delle librerie CDN. Non volevo vedere quelli nei link recuperati.

Non c'è bisogno di provare a cercare href o altre fonti per i collegamenti perché "lynx -dump" estrarrà di default tutti i collegamenti cliccabili da una data pagina. Quindi l'unica cosa che devi fare è analizzare il risultato di "lynx -dump" usando grep per ottenere una versione raw più pulita dello stesso risultato.


Ma la domanda dice "estrarre gli URL da un file HTML [che assomiglia]" (esempio), NON "estrarre gli URL da una pagina Web". Se la tua risposta può essere utilizzata su un file che si trova sul computer locale, spiega come. Si prega di non rispondere nei commenti; modifica la tua risposta per renderla più chiara e completa.
G-Man dice "Reinstate Monica" il

1
È possibile sostituire l'URL con un nome file.
asiby

@ G-Man, perché il -1? Devi provare tu stesso il codice e vedere che funziona anche per i file locali. Ho aggiunto questo chiarimento nel caso in cui non fosse ovvio.
asiby

Questo è davvero utile .. se stai usando con xargs vale la pena aggiungere | ordina | uniq per tagliare i collegamenti duplicati.
Stuart Axon,

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

... probabilmente farebbe abbastanza bene. Come scritto, stampa:

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

Se è importante abbinare solo i collegamenti e tra quei domini di primo livello, puoi fare:

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

... o qualcosa del genere - anche se per alcuni sedpotresti dover sostituire un letterale\n carattere ewline per ciascuno degli ultimi due ns.

Come scritto, il comando sopra stampa:

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

... e per entrambi i casi (ma probabilmente più utilmente con quest'ultimo) puoi puntare su un |sort -ufiltro fino alla fine per ottenere l'elenco sorted eliminare i duplicati.



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

Non sono sicuro che quelle citazioni "intelligenti" siano quelle che intendevi lì - forse le virgolette "doppie" regolari?
Jeff Schaller
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.