Jak używać grep i wycinać skrypty, aby uzyskać adresy URL witryn z pliku HTML


21

Próbuję użyć grep i cut, aby wyodrębnić adresy URL z pliku HTML. Linki wyglądają następująco:

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

Inne strony internetowe mają .net, .govale zakładam, że mógłbym zrobić punkt odcięcia już wcześniej >. Wiem, że mogę użyć grep i wyciąć jakoś, aby odciąć wszystko przed http i po .com, ale utknąłem na nim przez jakiś czas.


Zredagowałem to. Dla niektórych ignorowanie odstępu między a a HTML nie pojawiłby się bez niego. Dzięki za złapanie tego!
eltigre

Użyj formatowania kodu (zaznacz tekst i naciśnij Ctrl-K). W przeciwnym razie <>wymusza to, aby był postrzegany jako tag HTML.
muru

dlaczego nie dopasować początkowego i końcowego cytatu parametru href? poza tym uważam, że wyrażenia regularne nie najlepiej pasują do html.
把 友情 留 在 无 盐

Chcę napisać polecenie używając grep i wytnij, aby to zrobić. Zdaję sobie sprawę, że istnieją inne sposoby, ale chciałem o nich wiedzieć.
eltigre

9
Zasadniczo analizowanie HTML za pomocą wyrażeń regularnych nie jest dobrym pomysłem, ponieważ HTML nie jest zwykłym językiem. Jeśli możesz zagwarantować, że kod HTML, który analizujesz, jest dość prosty, a rzeczy, które próbujesz wyodrębnić, są przewidywalne, być może uda Ci się go uniknąć. Ale proszę zobacz stackoverflow.com/a/1732454/4014959
PM 2Ring

Odpowiedzi:


25

Jak powiedziałem w moim komentarzu, generalnie nie jest dobrym pomysłem analizowanie kodu HTML za pomocą wyrażeń regularnych, ale czasem możesz go uniknąć, jeśli analizowany kod HTML jest dobrze zachowany.

Aby uzyskać tylko adresy URL, które są hrefatrybutami <a>elementów, najłatwiej jest to zrobić na wielu etapach. Z twoich komentarzy wynika, że ​​chcesz tylko domeny najwyższego poziomu, a nie pełnego adresu URL. W takim przypadku możesz użyć czegoś takiego:

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

gdzie source.htmljest plik zawierający kod HTML do przeanalizowania.

Ten kod wydrukuje wszystkie adresy URL najwyższego poziomu, które występują jako hrefatrybut dowolnych <a>elementów w każdym wierszu. -iOpcja do pierwszego greppolecenia jest, aby zapewnić, że będzie działać na obu <a>i <A>elementów. Chyba można też dać -ido 2 grepuchwycić wielkimi literami HREFatrybuty OTOH, wolałbym zignorować taką złamaną HTML. :)

Aby przetworzyć zawartość http://google.com/

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

wynik

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

Moje wyniki nieco się różnią od innych przykładów, gdy jestem przekierowywany na australijską stronę Google.


DZIĘKUJĘ CI. Właśnie tego szukałem. To najczystszy sposób na zrobienie tego.
eltigre

@eltigre: Cała przyjemność po mojej stronie! Ale proszę, zwróć uwagę na ostrzeżenie, które zamieściłem w moim komentarzu powyżej. :)
PM 2Ring

Doszedłem do tego pytania, oczekując łatwych punktów ... a ty już całkowicie uderzyłeś w głowę
Mark K Cowan

Dzięki, @MarkKCowan. :) FWIW, zacząłem pisać odpowiedź za pomocą awk, ale potem zdecydowałem, że rozwiązanie oparte na grep będzie łatwiejsze do zrozumienia dla tych, którzy nie znają awk. Poza tym powyższy kod jest krótszy niż mój kod awk.
PM 2,

2
@mavavilj: Ponieważ OP chciał tylko domeny najwyższego poziomu, więc po znaku ://akceptujemy tylko znaki przed pierwszym /lub ". Ale jeśli chcesz zobaczyć pełny adres URL, zmień to polecenie na grep -Eo '(http|https)://[^"]+. Inną opcją dla tego wiersza jest grep -Eo '(http|https)://[^?"]+'odcięcie opcji zapytania. Jednak ta odmiana nadal będzie drukować adresy URL zawarte w innym adresie URL jako parametr zapytania, ale będą one drukowane w osobnym wierszu.
PM 2,

25

Nie jestem pewien, czy masz ograniczone narzędzia:

Jednak wyrażenie regularne może nie być najlepszym sposobem, jak wspomniano, ale oto przykład, który przygotowałem:

cat urls.html | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
  • grep -E: jest taki sam jak egrep
  • grep -o: wyświetla tylko to, co zostało grepowane
  • (http | https): jest albo / lub
  • az: wszystkie małe litery
  • AZ: wszystko ma przewagę
  • . : jest kropką
  • \?: jest ?
  • *: to powtórzenie grupy [...]
  • uniq: usunie wszelkie duplikaty

Wynik:

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

Możesz również dodać, \daby złapać inne typy liczb.


2
Wyrażenia regularne IRI! Użyj jednego z nich i przestraszyć OP! :)
muru

2
@muru ... dreszcze ja ... Nie wiem co powiedzieć. Czy to nawet prawdziwe !?
jmunsch

4
@ junschsch, uniq wystarczy usunąć sąsiednie duplikaty. sort -u?
JJoao

1
działa świetnie, najlepsza odpowiedź !!
Gery,

@JJoao jest źródłem sortowania -u szybciej niż orurowanie? Tylko eksperyment myślowy, muszę spojrzeć. Ale prawdopodobnie masz rację co do oprogramowania pośredniego powłoki.
jmunsch

9

Jeśli twój grep obsługuje wyrażenia regularne Perla:

grep -Po '(?<=href=")[^"]*(?=")'
  • (?<=href=")i (?=")są wyrażeniami wyglądającymi dla hrefatrybutu. To wymaga -Popcji.
  • -o drukuje pasujący tekst.

Na przykład:

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

Jak zwykle nie ma gwarancji, że są to poprawne identyfikatory URI ani że analizowany kod HTML będzie prawidłowy.


8

Jako alternatywę inną niż regularna , użyj pup :

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

Znajduje wszystkie aelementy, które mają hrefatrybut, a następnie wyświetla wartość hrefatrybutu.

Aby zainstalować pup, potrzebujesz Go (język programowania):

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

Zaletą tego rozwiązania jest to, że nie polega on na poprawnym sformatowaniu kodu HTML .


1
+1 za pup, czas na zainstalowanie tego ...
Mark K Cowan

Możesz również umieścić je w pliku. pup 'a.classname[href] attr{href}' < tut.html >links.md
Ahmad Awais,

1

Znalazłem tutaj rozwiązanie, które jest IMHO znacznie prostsze i potencjalnie szybsze niż to, co zostało tutaj zaproponowane. Trochę dostosowałem, aby obsługiwać pliki https. Ale wersja TD; TR to ...

PS: Możesz zastąpić adres URL witryny ścieżką do pliku, a to będzie działać w ten sam sposób.

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

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

Jeśli chcesz zobaczyć linki zamiast umieszczać je w pliku, spróbuj zamiast tego ...

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

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

Wynik będzie wyglądał podobnie do następującego ...

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.

W moim przypadku to zadziałało. Ale uważaj na to, że w dzisiejszych czasach ludzie dodają linki takie jak src = "// blah.tld" dla URI CDN bibliotek. Nie chciałem widzieć tych w pobranych linkach.

Nie trzeba próbować sprawdzać href ani innych źródeł linków, ponieważ „lynx -dump” domyślnie wyodrębnia wszystkie klikalne linki z danej strony. Więc jedyną rzeczą, którą musisz zrobić po tym, jest przeanalizowanie wyniku „lynx -dump” za pomocą grep, aby uzyskać czystszą, surową wersję tego samego wyniku.


Ale pytanie brzmi: „wyodrębnij adresy URL z pliku HTML [który wygląda] jak” (przykład)), a NIE „wyodrębnij adresy URL ze strony internetowej”. Jeśli Twojej odpowiedzi można użyć w odniesieniu do pliku na komputerze lokalnym, wyjaśnij, w jaki sposób. Proszę nie odpowiadać w komentarzach; edytuj swoją odpowiedź, aby była jaśniejsza i bardziej kompletna.
G-Man mówi „Przywróć Monikę”

1
Możesz zastąpić adres URL nazwą pliku.
asiby

@ G-Man, dlaczego -1? Musisz sam wypróbować kod i przekonać się, że działa on również w przypadku plików lokalnych. Dodałem to wyjaśnienie na wypadek, gdyby nie było oczywiste.
asiby

Jest to bardzo przydatne ... jeśli używasz xargs, warto dodać | sortuj | uniq, aby przyciąć duplikaty linków.
Stuart Axon

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

... prawdopodobnie poradziłby sobie całkiem nieźle. Jak napisano, drukuje:

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

Jeśli ważne jest, aby dopasowywać tylko linki i spośród tych domen najwyższego poziomu, możesz:

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

... lub coś w tym rodzaju - choć dla niektórych sedmożesz potrzebować zastąpić dosłowny \nznak ewline dla każdego z dwóch ostatnich n.

Jak napisano, powyższe polecenie wypisuje:

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

... i w obu przypadkach (ale najprawdopodobniej najbardziej przydatne z tym drugim) możesz przyczepić |sort -ufiltr do końca, aby uzyskać listę sorti usunąć duplikaty.



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

Nie jestem pewien, czy te „inteligentne” cytaty są tym, co tam zamierzałeś - być może zwykłe „podwójne” cytaty?
Jeff Schaller
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.