ซุปที่สวยงาม - การเข้ารหัส

เอกสาร HTML หรือ XML ทั้งหมดเขียนด้วยการเข้ารหัสเฉพาะบางอย่างเช่น ASCII หรือ UTF-8 อย่างไรก็ตามเมื่อคุณโหลดเอกสาร HTML / XML นั้นลงใน BeautifulSoup เอกสารนั้นจะถูกแปลงเป็น Unicode

>>> markup = "<p>I will display £</p>"
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.p
<p>I will display £</p>
>>> Bsoup.p.string
'I will display £'

พฤติกรรมข้างต้นเป็นเพราะ BeautifulSoup ใช้ภายในไลบรารีย่อยที่เรียกว่า Unicode, Dammit เพื่อตรวจจับการเข้ารหัสของเอกสารจากนั้นแปลงเป็น Unicode

อย่างไรก็ตามไม่ใช่ตลอดเวลาที่ Unicode Dammit เดาถูกต้อง เนื่องจากเอกสารถูกค้นหาแบบไบต์ต่อไบต์เพื่อเดาการเข้ารหัสจึงต้องใช้เวลามาก คุณสามารถประหยัดเวลาและหลีกเลี่ยงข้อผิดพลาดได้หากคุณรู้จักการเข้ารหัสแล้วโดยส่งต่อไปยังตัวสร้าง BeautifulSoup เป็น from_encoding

ด้านล่างนี้เป็นตัวอย่างหนึ่งที่ BeautifulSoup ระบุผิดเอกสาร ISO-8859-8 เป็น ISO-8859-7 -

>>> markup = b"<h1>\xed\xe5\xec\xf9</h1>"
>>> soup = BeautifulSoup(markup)
>>> soup.h1
<h1>νεμω</h1>
>>> soup.original_encoding
'ISO-8859-7'
>>>

ในการแก้ไขปัญหาข้างต้นให้ส่งต่อไปยัง BeautifulSoup โดยใช้ from_encoding -

>>> soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
>>> soup.h1
<h1>ולש </h1>
>>> soup.original_encoding
'iso-8859-8'
>>>

อีกคุณสมบัติใหม่ที่เพิ่มเข้ามาจาก BeautifulSoup 4.4.0 คือ exclude_encoding สามารถใช้ได้เมื่อคุณไม่ทราบการเข้ารหัสที่ถูกต้อง แต่แน่ใจว่า Unicode, Dammit แสดงผลลัพธ์ที่ไม่ถูกต้อง

>>> soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])

การเข้ารหัสเอาต์พุต

ผลลัพธ์จาก BeautifulSoup คือเอกสาร UTF-8 โดยไม่คำนึงถึงเอกสารที่ป้อนไปยัง BeautifulSoup ด้านล่างเอกสารที่มีอักขระภาษาโปลิชอยู่ในรูปแบบ ISO-8859-2

html_markup = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-2">
</HEAD>
<BODY>
ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
</BODY>
</HTML>
"""


>>> soup = BeautifulSoup(html_markup)
>>> print(soup.prettify())
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
   <head>
      <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
   </head>
   <body>
      ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
   </body>
</html>

ในตัวอย่างข้างต้นหากคุณสังเกตเห็นแท็ก <meta> ได้รับการเขียนใหม่เพื่อแสดงถึงเอกสารที่สร้างจาก BeautifulSoup ตอนนี้อยู่ในรูปแบบ UTF-8

หากคุณไม่ต้องการเอาต์พุตที่สร้างใน UTF-8 คุณสามารถกำหนดการเข้ารหัสที่ต้องการใน prettify ()

>>> print(soup.prettify("latin-1"))
b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n <head>\n <meta content="text/html; charset=latin-1" http-equiv="content-type"/>\n </head>\n <body>\n ą ć ę ł ń \xf3 ś ź ż Ą Ć Ę Ł Ń \xd3 Ś Ź Ż\n </body>\n</html>\n'

ในตัวอย่างข้างต้นเราได้เข้ารหัสเอกสารฉบับสมบูรณ์ แต่คุณสามารถเข้ารหัสองค์ประกอบใด ๆ ในซุปราวกับว่ามันเป็นสตริงงูหลาม -

>>> soup.p.encode("latin-1")
b'<p>0My first paragraph.</p>'
>>> soup.h1.encode("latin-1")
b'<h1>My First Heading</h1>'

อักขระใด ๆ ที่ไม่สามารถแสดงในการเข้ารหัสที่คุณเลือกจะถูกแปลงเป็นการอ้างอิงเอนทิตี XML ที่เป็นตัวเลข ด้านล่างนี้เป็นตัวอย่างหนึ่ง -

>>> markup = u"<b>\N{SNOWMAN}</b>"
>>> snowman_soup = BeautifulSoup(markup)
>>> tag = snowman_soup.b
>>> print(tag.encode("utf-8"))
b'<b>\xe2\x98\x83</b>'

หากคุณพยายามเข้ารหัสข้างต้นเป็น“ latin-1” หรือ“ ascii” มันจะสร้าง“ ☃” แสดงว่าไม่มีการแทนค่านั้น

>>> print (tag.encode("latin-1"))
b'<b>☃</b>'
>>> print (tag.encode("ascii"))
b'<b>☃</b>'

Unicode, Dammit

Unicode, Dammit จะใช้เป็นหลักเมื่อเอกสารขาเข้าอยู่ในรูปแบบที่ไม่รู้จัก (ส่วนใหญ่เป็นภาษาต่างประเทศ) และเราต้องการเข้ารหัสในรูปแบบที่รู้จัก (Unicode) และเราไม่ต้องการให้ Beautifulsoup ทำทั้งหมดนี้