Ubah HTML menjadi teks biasa, cara mencegah dua paragraf teks saling menempel
Artikel ini bertujuan untuk mengatasi masalah adhesi teks saat mengonversi HTML menjadi teks biasa, dan menjelaskan secara rinci penggunaan gabungan parameter pemisah dan strip get_text di Beautiful Soup. Menyediakan kasus uji DOM sintetis dan kode pernyataan Python lengkap termasuk batas tingkat blok/sebaris, pemrosesan spasi putih, metode persiapan masukan yang jelas dan kriteria penerimaan, dan menyediakan pintu masuk tambahan ke OmniDoc dalam skenario dokumen yang kompleks.
Saat mengonversi HTML menjadi teks biasa, dua paragraf teks saling menempel, terutama karena get_text() dipanggil secara langsung tanpa menentukan strategi pemisahan. Beautiful Soup menyatukan semua node teks dengan mulus secara default, dan batas antara elemen tingkat blok menghilang. Masalah ini biasa terjadi saat menggunakan Beautiful Soup untuk mengekstrak konten web.
Daripada menggunakan ekspresi reguler untuk menebak di mana harus istirahat setelah ekstraksi, Anda dapat menggabungkan parameter separator dan strip dengan benar selama ekstraksi. Artikel ini menggunakan sampel sintetis untuk mendemonstrasikan metode ini, memberikan kode pernyataan yang dapat dijalankan, dan menjelaskan situasi mana yang memerlukan tinjauan manual.
Setelah membaca artikel ini, Anda dapat menentukan apakah hasil ekstraksi Anda macet, menggunakan skrip pernyataan untuk memverifikasi keluaran, dan memperjelas masalah mana yang dapat diselesaikan dengan parameter dan mana yang perlu diubah.
Apa yang harus saya lakukan jika saya mengonversi HTML menjadi teks biasa? Kesimpulan satu kalimat
Pertama-tama gunakan kombinasi separator='\n' dan strip=True untuk memanggil get_text(), lalu tangani tag yang tidak relevan dan masalah struktural sesuai dengan situasi halaman.
| situasi Anda | Praktik yang direkomendasikan | alasan |
|---|---|---|
| Teks antar paragraf atau item daftar saling menempel | Atur separator='\n' dan strip=True | pemisah bertanggung jawab untuk pemisahan, strip menghilangkan bagian depan dan belakang yang kosong |
| Hanya pemisah yang disetel | Ditambah strip=True | Jika tidak, spasi yang tidak berarti akan dipertahankan |
| Hanya strip yang disetel | Tambahkan juga pemisah | Baris mungkin masih menempel satu sama lain |
| Halaman tersebut berisi tag yang tidak relevan seperti skrip | Hapus tag ini sebelum menelepon | Parameter get_text hanya menyelesaikan format, bukan pembersihan konten. |
| Berisi Tabel, Kanvas, atau Shadow DOM | Ubah rencana pengumpulan, atau terima informasi yang hilang | Konten semacam ini tidak dapat diselesaikan dengan menyesuaikan parameter |
Perangkap dan semantik parameter perilaku default
Mengapa menempel?
Metode get_text() menerima dua parameter utama: separator dan strip. Jika tidak ada parameter yang diteruskan, maka semua node teks di pohon tag akan langsung terhubung.
Perilaku default ini sangat bermasalah untuk elemen tingkat blok seperti div, p, dan li. Jeda baris dan indentasi dalam kode sumber HTML sering kali diubah menjadi string kosong atau diabaikan setelah penguraian, dan batas semantik menghilang.
Apa fungsi pemisah dan strip?
- separator: Mendefinisikan penyisipan antar node teks. Menyetel ke
'\n'adalah praktik umum, namun tidak sempurna. Jika HTML sangat bertumpuk, pembungkusan global dapat menghasilkan banyak baris kosong. - strip: Mengontrol apakah akan menghapus ruang kosong di awal dan akhir setiap fragmen teks. Saat
strip=True, Beautiful Soup pertama-tama akan menjalankan.strip()pada setiap NavigableString independen, lalu menggunakan pemisah untuk menyambungkannya.
Misalnya, <p> Hello </p> akan mendapatkan Hello yang bersih, bukan \n Hello \n dengan keluaran data yang kotor.
Keduanya harus digunakan bersama-sama:
- Hanya menggunakan pemisah tanpa strip akan mempertahankan ruang menjorok yang tidak berarti.
- Dengan hanya strip dan tanpa pemisah, satu garis akan bersih, namun mungkin masih ada adhesi antar garis.
Untuk deskripsi parameter lebih lanjut, silakan merujuk ke Dokumentasi resmi Sup Cantik: get_text().
Kasus uji batas DOM sintetis
Untuk memvalidasi logika ekstraksi, sampel HTML sintetis yang berisi masalah batas umum harus dibuat daripada mengandalkan halaman web nyata yang tidak stabil. Kasus pengujian berikut mencakup tiga situasi: adhesi elemen tingkat blok, jarak elemen sebaris, dan spasi berlebih.
Contoh masukan (contoh sintetik):
<div>
<p>第一段文字</p>
<p>第二段文字<span>内联补充</span></p>
<ul>
<li> 列表项A </li>
<li>列表项B</li>
</ul>
</div>
Hasil yang diharapkan benar:
第一段文字
第二段文字
内联补充
列表项A
列表项B
Perlu dicatat bahwa separator='\n' bertindak pada node teks yang diekstraksi dan tidak akan secara otomatis menghasilkan jeda baris ganda berdasarkan tag tingkat blok. Harus ada jeda baris yang jelas antara paragraf dan item daftar, dan spasi tambahan sebelum dan sesudah item daftar harus dihilangkan. "Teks kedua" dan "Suplemen sebaris" terletak pada label yang berbeda, dan merupakan simpul teks, sehingga akan dipisahkan oleh pembatas.
Kesalahan dan masukan batas
Jika inputnya menjadi <p>End</p><script>alert(1)</script><p>Start</p> dan tag skrip tidak difilter, outputnya akan berisi alert(1). Hal ini berlaku meskipun pemisah disetel. Apakah node skrip disertakan dalam teks bergantung pada parser dan jenis node.
Cara yang benar untuk menangani hal ini adalah dengan menggunakan soup.find_all('script') untuk menghapus tag yang tidak relevan sebelum memanggil get_text, atau untuk melewati jenis tag tertentu saat melakukan traversing. Parameter get_text hanya menyelesaikan masalah format, bukan masalah pembersihan konten.
Implementasi Python dan pemeriksaan pernyataan
Kode di bawah ini membuat contoh di atas dalam memori dan melakukan verifikasi deterministik. Contohnya bergantung pada beautifulsoup4, dan direkomendasikan versi 4.9.0 ke atas.
Untuk menguji file eksternal, harap simpan HTML sebagai pengkodean UTF-8 terlebih dahulu, lalu gunakan open('file.html', encoding='utf-8') untuk membacanya guna menghindari kesalahan pengkodean yang menyebabkan pengecualian penguraian. Kode ini tidak berisi permintaan jaringan dan sepenuhnya mandiri.
from bs4 import BeautifulSoup
# 合成示例:模拟常见的HTML文本边界问题
html_content = """
<div>
<p>第一段文字</p>
<p>第二段文字<span>内联补充</span></p>
<ul>
<li> 列表项A </li>
<li>列表项B</li>
</ul>
</div>
"""
soup = BeautifulSoup(html_content, 'html.parser')
# 关键配置:separator定义边界,strip清理碎片空白
text_result = soup.get_text(separator='\n', strip=True)
# 过滤空行以获得干净的语义行
lines = [line for line in text_result.split('\n') if line]
# 验收断言:确保边界清晰且无脏数据
assert lines[0] == '第一段文字', f"段落粘连或内容错误: {lines[0]}"
assert lines[1] == '第二段文字', "块级元素间未正确分隔"
assert lines[2] == '内联补充', "内联元素文本节点被错误合并"
assert lines[3] == '列表项A', f"列表项前置空格未清除: '{lines[3]}'"
assert lines[4] == '列表项B', "列表项间边界丢失"
print("提取结果预览:")
for i, line in enumerate(lines):
print(f"{i}: [{line}]")
Output yang diharapkan dari kode ini adalah lima baris teks bersih. Jika lingkungan Anda menghasilkan lebih banyak baris kosong, itu berarti ada node NavigableString kosong murni di DOM yang belum dihapus. Ini adalah perilaku normal html.parser dan dapat difilter dengan pemahaman daftar setelah pemisahan.
Kode ini hanya digunakan untuk mendemonstrasikan prinsip kombinasi parameter dan tidak boleh digunakan secara langsung pada halaman kompleks di lingkungan produksi.
📊 Perbandingan inti
| rencana | Memengaruhi | keterbatasan |
|---|---|---|
Hanya gunakan separator='\n' | Ada jeda garis antar blok | Pertahankan spasi yang menjorok ke dalam, sejumlah besar garis kosong mungkin muncul saat penyatuannya dalam |
Hanya gunakan strip=True | Bersihkan awal dan akhir setiap paragraf | Baris mungkin masih menempel satu sama lain |
| Gunakan keduanya secara bersamaan | Mempertimbangkan pemisahan dan penghapusan spasi | Tag yang tidak relevan masih perlu dihapus sebelum ekstraksi |
| Gunakan ekspresi reguler untuk menebak baris baru setelah ekstraksi | Tampaknya fleksibel | Tidak disarankan, prioritas harus diberikan pada kombinasi parameter yang benar saat mengekstraksi |
Kriteria penerimaan dan batasan tinjauan manual
Ekstraksi otomatis tidak dapat mencapai restorasi visual 100%. Tabel berikut mencantumkan cara membedakan antara situasi "kode dapat diperbaiki" dan "memerlukan intervensi manusia". Penilaian didasarkan pada struktur DOM, bukan perasaan subjektif.
| mengamati | apa yang harus dilakukan | tidak boleh disimpulkan |
|---|---|---|
| Pemisahan node sebaris | Periksa apakah kalimatnya terbagi | Pembatas bertindak pada node teks |
| Perataan meja | Pertahankan struktur baris dan kolom untuk pemrosesan terpisah | Anda tidak bisa hanya mengandalkan get_text |
| Menggambar konten secara dinamis | Identifikasi kesenjangan pengumpulan | Penguraian statis tidak sama dengan rendering browser |
Cakupan ketidakberlakuan secara eksplisit: Beautiful Soup tidak dapat memperoleh informasi yang valid ketika HTML berisi sejumlah besar teks yang dihasilkan oleh elemen semu CSS, konten yang dirender Canvas, atau Shadow DOM. Pada saat ini, parameter tidak boleh terus di-debug, tetapi skema akuisisi harus diubah, atau informasi yang hilang harus diterima.
🎯 Metode mana yang cocok untuk Anda?
jika kamu……
Perlu mengekstrak teks biasa paragraf dan item daftar
Tetapkan separator='\n' dan strip=True dan verifikasi hasilnya dengan skrip pernyataan.
Ada banyak skrip atau tag gaya di halaman
Hapus tag ini sebelum memanggil get_text, dan jangan berharap parameter tersebut menyelesaikan masalah konten.
Perlu mempertahankan struktur baris dan kolom tabel
Jangan hanya mengandalkan get_text, tangani struktur tabel secara terpisah.
Laman bergantung pada rendering browser atau Shadow DOM
Ubah rencana pengumpulan, atau catat dengan jelas kesenjangan pengumpulan selama penerimaan.
❓ Pertanyaan yang Sering Diajukan (FAQ)
1. Apakah cukup dengan menyetel pemisah saja?
tidak cukup. Menyetel pemisah saja akan mempertahankan ruang lekukan yang tidak berarti, dan memerlukan penambahan strip=True.
2. Mengapa ada baris kosong di output?
Mungkin ada node NavigableString kosong di DOM yang belum dihapus. Ini adalah perilaku normal html.parser dan dapat difilter dengan pemahaman daftar setelah pemisahan.
3. Mengapa tag skrip muncul di hasil?
Parameter get_text hanya menyelesaikan masalah format. Harus dihapus dengan soup.find_all('script') sebelum menelepon, atau dilewati selama traversal.
4. Bagaimana cara memverifikasi apakah hasil ekstraksi sudah benar?
Buatlah set pengujian sintetik yang terdiri dari 5–10 kasus edge tipikal dan jalankan skrip pernyataan. Jika tingkat kelulusan lebih rendah dari yang diharapkan, periksa apakah Anda perlu memproses DOM terlebih dahulu sebelum mengekstraknya.
📝 Ringkasan
Inti dari masalah adhesi terletak pada kombinasi parameter selama ekstraksi, bukan perbaikan string setelah ekstraksi. Pertama-tama jalankan sampel dan pernyataan sintetis, lalu tangani tag yang tidak relevan dan masalah struktural di halaman sebenarnya.


