Teks di antara dua tag


23

Saya ingin mengambil apa pun di antara kedua tag ini - <tr> </tr>- dari dokumen html. Sekarang saya tidak memiliki persyaratan html spesifik yang akan menjamin untuk parser html. Saya hanya butuh sesuatu yang cocok <tr>dan </tr>dan mendapatkan semua di antaranya dan mungkin ada banyak tr. Saya mencoba awk, yang berhasil, tetapi untuk beberapa alasan akhirnya memberi saya duplikat dari setiap baris yang diekstraksi.

awk '
/<TR/{p=1; s=$0}
p && /<\/TR>/{print $0 FS s; s=""; p=0}
p' htmlfile> newfile

Bagaimana caranya?


IIUC naskah awk Anda harus: '/<tr/{p=1}; p; /<\/tr>/{p=0}'. Posting beberapa contoh input dan output yang diharapkan jika tidak berhasil.
Thor

karena Anda awkbekerja tetapi memberikan duplikat, cobalah untuk mengeluarkan keluaran awk Anda dari sort -uuntuk membuatnya berbeda
igiannak

Jawaban:


14

Jika Anda hanya ingin ...semua <tr>...</tr>lakukan:

grep -o '<tr>.*</tr>' HTMLFILE | sed 's/\(<tr>\|<\/tr>\)//g' > NEWFILE

Untuk multiline, lakukan:

tr "\n" "|" < HTMLFILE | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g;s/|/\n/g' > NEWFILE

Periksa dulu HTMLFILE dari char "|" (tidak biasa, tapi mungkin) dan jika ada, ubah ke yang tidak ada.


1
Itu hanya akan berfungsi jika tag awal dan akhir berada di baris yang sama.
l0b0

echo "bla<tr>foo</tr>bla<tr>bar</tr>bla" | grep -o '<tr>.*</tr>' | sed 's/\(<tr>\|<\/tr>\)//g'memberi fooblabar. The blaseharusnya tidak ada?
NN

@ l0b0 benar. akan cocok untuk yang kompatibel dengan multiline ...
xx4h

grep -Po '<tr>.*?</tr>'akan mengembalikan satu hasil per baris dalam kasus @ NN, tetapi tidak portabel.
l0b0

Saya tidak yakin apa yang Anda maksud dengan 'specs' atau 'spec-style' tetapi perhatikan bahwa browser web Anda menggunakan parser html dan parser html akan mem-parsing html terlepas dari bagaimana ditulisnya. Ini tidak akan mem-parsing hal-hal yang bukan html, tetapi kemudian, browser Anda juga tidak, jadi tidak ada yang akan repot-repot menulis "html" yang tidak dapat diurai parser. Dengan kata lain: Pengurai yang baik tentu saja merupakan taruhan terbaik Anda untuk melakukan ini.
goldilocks

11

Anda memang memiliki persyaratan yang menjamin pengurai HTML: Anda harus menguraikan HTML. HTML Perl :: TreeBuilder , BeautifulSoup Python dan lainnya mudah digunakan, lebih mudah daripada menulis ekspresi reguler yang kompleks dan rapuh.

perl -MHTML::TreeBuilder -le '
    $html = HTML::TreeBuilder->new_from_file($ARGV[0]) or die $!;
    foreach ($html->look_down(_tag => "tr")) {
        print map {$_->as_HTML()} $_->content_list();
    }
' input.html

atau

python -c 'if True:
    import sys, BeautifulSoup
    html = BeautifulSoup.BeautifulSoup(open(sys.argv[1]).read())
    for tr in html.findAll("tr"):
        print "".join(tr.contents)
' input.html

9

seddan awktidak cocok untuk tugas ini, Anda sebaiknya menggunakan parser html yang tepat. Misalnya hxselectdari w3.org:

<htmlfile hxselect -s '\n' -c 'tr'

Saya tidak tahu apakah memilih adalah pilihan terbaik; Saya belum menggunakannya tetapi halaman manual mengatakan "membaca dokumen XML yang terbentuk dengan baik" yang mana banyak dokumen html tidak. Mungkin patut dicoba. Libers parser html tersedia untuk perl, python, et. Al. akan jauh lebih baik, jika itu pilihan.
goldilocks

2
@goldilocks: Pilihan terbaik tergantung pada situasinya. Dalam pengalaman saya hxselectmelakukan pekerjaan yang cukup baik dengan dokumen html / xml yang terbentuk dengan baik. Juga, ini lebih cepat digunakan daripada perl, python dan lainnya. Saya pikir hxselectadalah jalan tengah yang baik antara sed/ awkdan lib pengurai.
Thor

1
Jika berhasil itu bagus! Saya baru saja menambahkan peringatan untuk TechJack kalau-kalau tidak - karena saya juga merekomendasikan menggunakan semacam parser;) Pemrograman lib tentu saja lebih canggung tetapi harus berurusan dengan apa pun yang bisa dianggap sebagai html.
goldilocks

Thor, hxselectterlihat bagus, pasti akan lebih mengeksplorasi. Terima kasih.
TechJack

@goldilocks: hxnormalizemenangani file html / xml yang tidak terbentuk dengan baik.
tokland

5

Jika rubytersedia, Anda dapat melakukan hal berikut

ruby -e 'puts readlines.join[/(?<=<tr>).+(?=<\/tr>)/m].gsub(/<\/?tr>/, "")' file

di mana filefile input html Anda. Perintah mengeksekusi Ruby satu-liner. Pertama, ia membaca semua baris dari filedan bergabung dengan mereka ke string readlines.join,. Kemudian, dari string ia memilih apa pun di antara (tetapi tidak termasuk) <tr>dan <\/tr>itu adalah satu karakter atau lebih lama terlepas dari baris baru [/(?<=<tr>).+(?=<\/tr>)/m],. Kemudian, itu menghapus salah satu <tr>atau </tr>dari string, gsub(/<\/?tr>/, "")(ini diperlukan untuk menangani trtag bersarang ). Akhirnya, ia mencetak string puts,.

Anda mengatakan bahwa parser html tidak dijamin untuk Anda tetapi sangat mudah untuk menggunakan Nokogiri dengan rubydan itu membuat perintah lebih sederhana.

ruby -rnokogiri -e 'puts Nokogiri::HTML(readlines.join).xpath("//tr").map { |e| e.content }' file

-rnokogirimemuat Nokogiri. Nokogiri::HTML(readlines.join)membaca semua baris file. xpath("//tr")mengambil setiap trelemen dan map { |e| e.content }memilih konten untuk setiap elemen, yaitu apa yang ada di antara <tr>dan </tr>.


1

grep

Untuk mengambil konten di dalam trtag di beberapa baris, sampaikan xargsdulu, misalnya:

curl -sL https://www.iana.org/ | xargs | egrep -o "<tr>.*?</tr>"

Untuk hanya mengembalikan HTML bagian dalam, gunakan:

curl -sL https://www.iana.org/ | xargs | grep -Po "<tr>\K(.*?)</tr>" | sed "s/..tr.//g"

Periksa sintaks untuk perlrepola yang diperluas .

Catatan: Untuk kinerja yang lebih cepat, Anda dapat mempertimbangkan ripgrepyang memiliki sintaksis yang serupa.


itu dicetak lebih bagus mencari tanpa xargs, berguna untuk menemukan javascript inline menggunakan egrep -o "<script. *? </script>"
Andrew

0

pup

Contoh menggunakan pup(yang menggunakan pemilih CSS ):

pup -f myfile.html tr

Untuk mencetak hanya teks tanpa tag, gunakan: pup -f myfile.html tr text{}.

Berikut adalah beberapa contoh dengan curl:

curl -sL https://www.iana.org/ | pup tr text{}
pup -f <(curl -sL https://www.iana.org/) tr text{}

xpup

Contoh menggunakan xpupuntuk parsing HTML / XML (yang mendukung XPath):

xpup -f myfile.html "//tr"

0

jika ini hanya daftar singkat dari <tr>ini, ini bisa membantu:

perl -ne 'print if /<tr>/../</tr>/' your.html > TRs.log

tepuk tangan

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.