Cara menggunakan skrip grep dan cut untuk mendapatkan URL situs web dari file HTML

21

Saya mencoba menggunakan grep dan cut untuk mengekstrak URL dari file HTML. Tautannya terlihat seperti:

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

Situs web lain sudah .net,, .govtapi saya berasumsi saya bisa membuat cut off point tepat sebelumnya >. Jadi saya tahu saya bisa menggunakan grep dan memotong entah bagaimana untuk memotong semuanya sebelum http dan setelah .com, tapi saya sudah terjebak di sana untuk sementara waktu.

Eltigre
sumber
Saya mengeditnya. Untuk beberapa mengabaikan ruang antara <dan a, HTML tidak akan muncul tanpa itu. Terima kasih telah menangkap itu!
eltigre
Gunakan pemformatan kode (pilih teks dan tekan Ctrl-K). Kalau tidak, <>kekuatan itu harus dilihat sebagai tag HTML.
muru
mengapa tidak cocok dengan kutipan pembukaan dan akhir dari parameter href? selain itu, saya percaya persamaan reguler tidak paling cocok untuk html.
把 友情 留 在 无 盐
Saya ingin menulis perintah menggunakan khusus grep dan cut untuk melakukannya. Saya menyadari ada cara lain, tetapi saya ingin tahu tentang itu.
eltigre
9
Secara umum itu bukan ide yang baik untuk mem-parsing HTML dengan Ekspresi Reguler, karena HTML bukan bahasa biasa. Jika Anda dapat menjamin bahwa HTML yang Anda parsing cukup sederhana, dan hal-hal yang Anda coba ekstrak dapat diprediksi, Anda mungkin dapat melakukannya. Tapi tolong lihat stackoverflow.com/a/1732454/4014959
PM 2Ring

Jawaban:

25

Seperti yang saya katakan di komentar saya, umumnya bukan ide yang baik untuk mem-parsing HTML dengan Ekspresi Reguler, tetapi Anda kadang-kadang bisa lolos jika HTML yang Anda parsing berperilaku baik.

Untuk hanya mendapatkan URL yang ada dalam hrefatribut <a>elemen, saya merasa paling mudah untuk melakukannya dalam beberapa tahap. Dari komentar Anda, sepertinya Anda hanya menginginkan domain tingkat atas, bukan URL lengkap. Dalam hal ini Anda dapat menggunakan sesuatu seperti ini:

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

di mana source.htmlfile yang berisi kode HTML untuk diuraikan.

Kode ini akan mencetak semua URL tingkat atas yang terjadi sebagai hrefatribut dari setiap <a>elemen di setiap baris. The -ipilihan untuk pertama grepperintah adalah untuk memastikan bahwa ia akan bekerja pada kedua <a>dan <A>elemen. Saya kira Anda juga bisa memberi -ike-2 grepuntuk menangkap HREFatribut huruf besar , OTOH, saya lebih suka mengabaikan HTML yang rusak. :)

Untuk memproses isi http://google.com/

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

keluaran

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

Keluaran saya sedikit berbeda dari contoh lain ketika saya diarahkan ke halaman Google Australia.

PM 2Ring
sumber
TERIMA KASIH. Sekarang ini persis apa yang saya cari. Ini adalah cara terbersih untuk melakukannya.
eltigre
@eltigre: Dengan senang hati! Tapi tolong perhatikan peringatan yang saya tautkan dalam komentar saya di atas. :)
PM 2Ring
Saya sampai pada pertanyaan ini mengharapkan poin-poin mudah ... dan Anda sudah benar-benar memukul kepalanya
Mark K Cowan
Terima kasih, @MarkKCowan. :) FWIW, saya awalnya mulai menulis jawaban menggunakan awk, tapi kemudian saya memutuskan bahwa solusi berbasis grep akan lebih mudah dipahami bagi mereka yang tidak terbiasa dengan awk. Lagi pula, kode di atas lebih pendek dari kode awk saya.
PM 2Ring
2
@mavavilj: Karena OP hanya menginginkan domain tingkat atas, maka setelah itu ://kami hanya menerima karakter sebelum /atau yang pertama ". Tetapi jika Anda ingin melihat URL lengkap, ubah perintah itu menjadi grep -Eo '(http|https)://[^"]+. Opsi lain untuk baris itu adalah grep -Eo '(http|https)://[^?"]+'yang memotong opsi kueri. Namun, variasi itu masih akan mencetak URL yang terkandung dalam URL lain sebagai parameter kueri, tetapi mereka akan dicetak pada baris terpisah.
PM 2Ring
25

Tidak yakin apakah Anda terbatas pada alat:

Tapi regex mungkin bukan cara terbaik untuk pergi seperti yang disebutkan, tetapi di sini adalah contoh yang saya kumpulkan:

cat urls.html | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
  • grep -E: sama dengan egrep
  • grep -o: hanya menampilkan apa yang telah dipahami
  • (http | https): adalah salah satu / atau
  • az: semuanya huruf kecil
  • AZ: semua kasus uper
  • . : is dot
  • \?: aku s ?
  • *: ulangi grup [...]
  • uniq: akan menghapus duplikat apa pun

Keluaran:

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

Anda juga dapat menambahkan \duntuk menangkap jenis angka lainnya.

Jonunsch
sumber
2
IRI regex! Gunakan salah satunya dan menakuti OP! :)
muru
2
@uru ... menggigil saya ... Saya tidak tahu harus berkata apa. Apakah itu nyata !?
jmunsch
4
@ jmunsch, uniq hanya menghapus duplikat yang berdekatan. sort -u?
JJoao
1
itu bekerja dengan baik, jawaban terbaik !!
Gery
@ Jojo adalah sumber untuk sort -u lebih cepat dari perpipaan? Hanya eksperimen pikiran, id harus melihat. Tapi Anda mungkin benar, tentang shell middleware.
jmunsch
9

Jika grep Anda mendukung reg reges Perl:

grep -Po '(?<=href=")[^"]*(?=")'
  • (?<=href=")dan (?=")yang lookaround ekspresi untuk hrefatribut. Ini membutuhkan -Popsi.
  • -o mencetak teks yang cocok.

Sebagai contoh:

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

Seperti biasa, tidak ada jaminan bahwa ini adalah URI yang valid, atau bahwa HTML yang Anda parsing akan valid.

muru
sumber
8

Sebagai alternatif non-regex , gunakan pup :

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

Akan menemukan semua aelemen yang memiliki hrefatribut, lalu menampilkan nilai hrefatribut.

Untuk menginstal pup, Anda perlu Go (bahasa pemrograman):

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

Keuntungan dari solusi ini adalah tidak bergantung pada HTML yang diformat dengan benar .

Kroltan
sumber
1
+1 untuk pup, waktu memasang itu ....
Mark K Cowan
Anda dapat memasukkannya ke dalam file juga. pup 'a.classname[href] attr{href}' < tut.html >links.md
Ahmad Awais
1

Saya telah menemukan solusi di sini yaitu IMHO jauh lebih sederhana dan berpotensi lebih cepat daripada yang diusulkan di sini. Saya telah menyesuaikan sedikit untuk mendukung file https. Tapi versi TD; TR adalah ...

PS: Anda dapat mengganti URL situs dengan jalur ke file dan itu akan bekerja dengan cara yang sama.

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

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

Jika Anda hanya ingin melihat tautan alih-alih menempatkannya di file, cobalah ini ...

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

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

Hasilnya akan terlihat mirip dengan yang berikut ...

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.

Untuk kasus penggunaan saya, ini bekerja dengan baik. Tetapi waspadalah terhadap kenyataan bahwa saat ini, orang menambahkan tautan seperti src = "// blah.tld" untuk CDN URI perpustakaan. Saya tidak ingin melihat itu di tautan yang diambil.

Tidak perlu mencoba memeriksa tautan href atau sumber lain karena "lynx -dump" akan mengekstraksi secara default semua tautan yang dapat diklik dari halaman yang diberikan. Jadi satu-satunya yang perlu Anda lakukan setelah itu adalah mengurai hasil "lynx -dump" menggunakan grep untuk mendapatkan versi mentah yang lebih bersih dari hasil yang sama.

asiby
sumber
Tetapi pertanyaannya mengatakan "ekstrak URL dari file HTML [yang terlihat] seperti" (contoh), BUKAN "ekstrak URL dari halaman web". Jika jawaban Anda dapat digunakan terhadap file yang ada di mesin lokal, jelaskan caranya. Tolong jangan menanggapi dalam komentar; edit jawaban Anda untuk membuatnya lebih jelas dan lebih lengkap.
G-Man Mengatakan 'Reinstate Monica'
1
Anda dapat mengganti URL dengan nama file.
asiby
@ G-Man, mengapa -1? Anda perlu mencoba kode itu sendiri dan melihatnya berfungsi untuk file lokal juga. Saya telah menambahkan klarifikasi kalau-kalau tidak jelas.
asiby
Ini sangat berguna .. jika Anda menggunakan dengan xargs, patut ditambahkan | sortir | uniq untuk memotong tautan duplikat.
Stuart Axon
0
wget -qO- google.com |
tr \" \\n | grep https\*://

... mungkin akan melakukannya dengan cukup baik. Seperti yang tertulis, ia mencetak:

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

Jika penting bahwa Anda hanya mencocokkan tautan dan dari antara domain-domain tingkat atas itu, Anda dapat melakukannya:

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

... atau sesuatu seperti itu - meskipun untuk beberapa seds Anda mungkin perlu mengganti \nkarakter ewline literal untuk masing-masing dari dua ns terakhir .

Seperti yang tertulis, perintah di atas mencetak:

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

... dan untuk kedua kasus (tapi mungkin yang paling berguna dengan yang terakhir) Anda dapat menempelkan |sort -ufilter ke ujung untuk mendapatkan daftar sorted dan untuk menjatuhkan duplikat.

mikeserv
sumber
0

Terpendek

grep -r http . --color
tali
sumber
-1
echo "<a href="http://examplewebsite.com/">"|sed -r 's:<.*"::g'|sed 's:/">$::g'
Praveen Kumar BS
sumber
Saya tidak yakin bahwa kutipan "pintar" itu adalah apa yang Anda maksudkan di sana - mungkin kutipan "ganda" biasa?
Jeff Schaller