Comment utiliser grep et cut in script pour obtenir les URL de sites Web à partir d'un fichier HTML

21

J'essaie d'utiliser grep et cut pour extraire les URL d'un fichier HTML. Les liens ressemblent à:

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

D'autres sites Web l'ont fait .net, .govmais je suppose que je pourrais faire le point juste avant >. Je sais donc que je peux utiliser grep et cut d'une manière ou d'une autre pour tout couper avant http et après .com, mais je suis coincé dessus depuis un moment.

eltigre
la source
Je l'ai édité. Pour certains, ignorer l'espace entre <et a, le HTML n'apparaîtrait pas sans lui. Merci d'avoir attrapé ça!
eltigre
Utilisez la mise en forme du code (sélectionnez le texte et appuyez sur Ctrl-K). Sinon, le <>force à être considéré comme une balise HTML.
muru
pourquoi ne pas faire correspondre les guillemets d'ouverture et de fin du paramètre href? en outre, je pense que les expressions régulières ne conviennent pas aux html.
把 友情 留 在 无 盐
Je veux écrire une commande en utilisant spécifiquement grep et cut pour le faire. Je me rends compte qu'il existe d'autres façons, mais je voulais en savoir plus.
eltigre
9
En général, ce n'est pas une bonne idée d'analyser HTML avec des expressions régulières, car HTML n'est pas un langage normal. Si vous pouvez garantir que le code HTML que vous analysez est assez simple et que les éléments que vous essayez d'extraire sont prévisibles, vous pourrez peut- être vous en sortir. Mais s'il vous plaît voir stackoverflow.com/a/1732454/4014959
PM 2Ring

Réponses:

25

Comme je l'ai dit dans mon commentaire, ce n'est généralement pas une bonne idée d'analyser le HTML avec des expressions régulières, mais vous pouvez parfois vous en tirer si le HTML que vous analysez se comporte bien.

Afin d'obtenir uniquement les URL qui se trouvent dans l' hrefattribut des <a>éléments, je trouve qu'il est plus facile de le faire en plusieurs étapes. D'après vos commentaires, il semble que vous ne souhaitiez que le domaine de premier niveau, pas l'URL complète. Dans ce cas, vous pouvez utiliser quelque chose comme ceci:

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

source.htmlest le fichier contenant le code HTML à analyser.

Ce code imprimera toutes les URL de niveau supérieur qui apparaissent comme l' hrefattribut de tous les <a>éléments de chaque ligne. L' -ioption de la première grepcommande est de faire en sorte que cela fonctionnera sur les deux <a>et <A>éléments. Je suppose que vous pourriez aussi donner -iau 2egrep pour capturer les HREFattributs majuscules , OTOH, je préférerais ignorer un tel HTML cassé. :)

Pour traiter le contenu de http://google.com/

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

production

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

Ma sortie est un peu différente des autres exemples car je suis redirigé vers la page Google australienne.

PM 2Ring
la source
MERCI. Maintenant, c'est exactement ce que je cherchais. C'est la façon la plus propre de le faire.
eltigre
@eltigre: Mon plaisir! Mais veuillez tenir compte de l'avertissement auquel j'ai lié dans mon commentaire ci-dessus. :)
PM 2Ring
Je suis venu à cette question en m'attendant à des points faciles ... et vous aviez déjà complètement cloué la tête
Mark K Cowan
Merci, @MarkKCowan. :) FWIW, à l'origine, j'ai commencé à écrire une réponse en utilisant awk, mais j'ai ensuite décidé qu'une solution basée sur grep serait plus facile à comprendre pour ceux qui ne connaissent pas awk. Et de toute façon, le code ci-dessus est plus court que mon code awk.
PM 2Ring
2
@mavavilj: Parce que l'OP ne voulait que le domaine de premier niveau, donc après le ://nous n'acceptons que les caractères avant le premier /ou ". Mais si vous voulez voir l'URL complète, changez cette commande en grep -Eo '(http|https)://[^"]+. Une autre option pour cette ligne est de grep -Eo '(http|https)://[^?"]+'couper les options de requête. Cependant, cette variante imprimera toujours les URL contenues dans une autre URL en tant que paramètre de requête, mais elles seront imprimées sur une ligne distincte.
PM 2Ring
25

Je ne sais pas si vous êtes limité sur les outils:

Mais l'expression régulière n'est peut-être pas la meilleure façon de procéder, comme mentionné, mais voici un exemple que j'ai rassemblé:

cat urls.html | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
  • grep -E: est le même que egrep
  • grep -o: affiche uniquement ce qui a été récupéré
  • (http | https): est un / ou
  • az: est tout en minuscules
  • AZ: est tout cas majuscule
  • . : est un point
  • \?: est ?
  • *: c'est répéter le [...] groupe
  • uniq: supprimera tous les doublons

Production:

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

Vous pouvez également ajouter \dpour attraper d'autres types de chiffres.

jmunsch
la source
2
IRI regexes! Utilisez l'un d'eux et effrayez l'OP! :)
muru
2
@muru ... grelottant je ... je ne sais pas quoi dire. Sont-ils même réels!?
jmunsch
4
@jmunsch, uniq vient de supprimer les doublons adjacents. sort -u?
JJoao
1
cela fonctionne très bien, meilleure réponse !!
Gery
@JJoao est la source du tri -u plus rapide que la tuyauterie? Juste une expérience de pensée, je dois regarder. Mais vous avez probablement raison sur le middleware shell.
jmunsch
9

Si votre grep prend en charge les expressions rationnelles Perl:

grep -Po '(?<=href=")[^"]*(?=")'
  • (?<=href=")et (?=")sont des expressions de contournement pour l' hrefattribut. Cela nécessite l' -Poption.
  • -o imprime le texte correspondant.

Par exemple:

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

Comme d'habitude, rien ne garantit que ce sont des URI valides ou que le code HTML que vous analysez sera valide.

muru
la source
8

Comme alternative non regex , utilisez pup :

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

Trouvera tous les aéléments qui ont un hrefattribut, puis affichera la valeur duhref attribut.

Pour installer pup, vous avez besoin de Go (un langage de programmation):

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

L'avantage de cette solution est qu'elle ne dépend pas du formatage correct du HTML .

Kroltan
la source
1
+1 pour pup, il est temps d'installer cela ....
Mark K Cowan
Vous pouvez également les mettre dans un fichier. pup 'a.classname[href] attr{href}' < tut.html >links.md
Ahmad Awais
1

J'ai trouvé une solution ici qui est à humble avis beaucoup plus simple et potentiellement plus rapide que ce qui a été proposé ici. J'ai ajusté un peu pour prendre en charge les fichiers https. Mais la version TD; TR est ...

PS: Vous pouvez remplacer l'URL du site par un chemin d'accès à un fichier et cela fonctionnera de la même manière.

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

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

Si vous souhaitez simplement voir les liens au lieu de les placer dans un fichier, essayez plutôt ceci ...

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

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

Le résultat ressemblera à ce qui suit ...

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.

Pour mon cas d'utilisation, cela a très bien fonctionné. Mais attention, de nos jours, les gens ajoutent des liens comme src = "// blah.tld" pour l'URI CDN des bibliothèques. Je ne voulais pas les voir dans les liens récupérés.

Pas besoin d'essayer de vérifier les liens href ou autres sources car "lynx -dump" extraira par défaut tous les liens cliquables d'une page donnée. Donc, la seule chose que vous devez faire après cela est d'analyser le résultat de "lynx -dump" en utilisant grep pour obtenir une version brute plus propre du même résultat.

asiby
la source
Mais la question dit «extraire les URL d'un fichier HTML [qui ressemble] à» (exemple), PAS «extraire les URL d'une page Web». Si votre réponse peut être utilisée contre un fichier qui se trouve sur la machine locale, expliquez comment. Veuillez ne pas répondre dans les commentaires; modifiez votre réponse pour la rendre plus claire et plus complète.
G-Man dit `` Réintègre Monica ''
1
Vous pouvez remplacer l'URL par un nom de fichier.
asiby
@ G-Man, pourquoi le -1? Vous devez essayer le code vous-même et voir qu'il fonctionne également pour les fichiers locaux. J'ai ajouté cette précision au cas où elle ne serait pas évidente.
asiby
C'est vraiment pratique .. si vous utilisez des xargs, cela vaut la peine d'ajouter | trier | uniq pour couper les liens en double.
Stuart Axon
0
wget -qO- google.com |
tr \" \\n | grep https\*://

... ferait probablement très bien. Tel qu'écrit, il imprime:

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

S'il est important de ne faire correspondre que des liens et parmi ces domaines de premier niveau, vous pouvez faire:

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

... ou quelque chose comme ça - bien que pour certains seds vous devrez peut-être substituer un caractère littéral \newline pour chacun des deux derniers ns.

Comme écrit, la commande ci-dessus imprime:

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

... et dans les deux cas (mais probablement le plus utilement avec ce dernier), vous pouvez virer |sort -uau bout d' un filtre pour obtenir la liste sortet supprimer les doublons.

mikeserv
la source
0

Le plus court

grep -r http . --color
effleurer
la source
-1
echo "<a href="http://examplewebsite.com/">"|sed -r 's:<.*"::g'|sed 's:/">$::g'
Praveen Kumar BS
la source
Je ne suis pas sûr que ces citations «intelligentes» correspondent à ce que vous vouliez - peut-être des citations «doubles» régulières?
Jeff Schaller