ปรับปรุง 2018:
ตั้งแต่เดือนกุมภาพันธ์ 2018 การใช้การบีบอัดอย่างgzip
เป็นที่นิยม (ประมาณ 73% ของเว็บไซต์ทั้งหมดใช้รวมถึงเว็บไซต์ขนาดใหญ่เช่น Google, YouTube, Yahoo, Wikipedia, Reddit, Stack Overflow และ Stack Exchange Network)
หากคุณทำการถอดรหัสอย่างง่ายเช่นเดียวกับคำตอบดั้งเดิมที่มีการตอบกลับ gzipped คุณจะได้รับข้อผิดพลาดเช่นหรือคล้ายกับสิ่งนี้:
UnicodeDecodeError: ตัวแปลงสัญญาณ 'utf8' ไม่สามารถถอดรหัสไบต์ 0x8b ในตำแหน่งที่ 1: ไบต์รหัสที่ไม่คาดคิด
ในการถอดรหัสการตอบกลับ gzpipped คุณต้องเพิ่มโมดูลต่อไปนี้ (ใน Python 3):
import gzip
import io
หมายเหตุ: ใน Python 2 คุณจะใช้StringIO
แทนio
จากนั้นคุณสามารถแยกเนื้อหาออกดังนี้:
response = urlopen("https://example.com/gzipped-ressource")
buffer = io.BytesIO(response.read()) # Use StringIO.StringIO(response.read()) in Python 2
gzipped_file = gzip.GzipFile(fileobj=buffer)
decoded = gzipped_file.read()
content = decoded.decode("utf-8") # Replace utf-8 with the source encoding of your requested resource
รหัสนี้อ่านการตอบสนองและวางไบต์ในบัฟเฟอร์ gzip
โมดูลแล้วอ่านบัฟเฟอร์โดยใช้GZipFile
ฟังก์ชั่น หลังจากนั้นไฟล์ gzipped สามารถอ่านเป็นไบต์อีกครั้งและถอดรหัสเป็นข้อความที่อ่านได้ตามปกติในตอนท้าย
คำตอบเดิมจาก 2010:
เราสามารถรับมูลค่าที่แท้จริงได้link
หรือไม่?
นอกจากนี้เรามักจะพบปัญหานี้ที่นี่เมื่อเราพยายามที่จะ.encode()
สตริงไบต์เข้ารหัสแล้ว ดังนั้นคุณอาจลองถอดรหัสก่อน
html = urllib.urlopen(link).read()
unicode_str = html.decode(<source encoding>)
encoded_str = unicode_str.encode("utf8")
ตัวอย่างเช่น:
html = '\xa0'
encoded_str = html.encode("utf8")
ล้มเหลวด้วย
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)
ในขณะที่:
html = '\xa0'
decoded_str = html.decode("windows-1252")
encoded_str = decoded_str.encode("utf8")
ประสบความสำเร็จโดยไม่มีข้อผิดพลาด ทำทราบว่า "1252 หน้าต่าง" เป็นสิ่งที่ฉันใช้เป็นตัวอย่าง ฉันได้รับมาจากชาร์ตและมีความมั่นใจ 0.5 ว่าถูกต้อง! (เช่นเดียวกับที่ได้รับกับสตริงที่มีความยาว 1 ตัวอักษรคุณคาดหวังอะไร) คุณควรเปลี่ยนการเข้ารหัสไบต์สตริงที่ส่งกลับจาก.urlopen().read()
เป็นสิ่งที่ใช้กับเนื้อหาที่คุณดึงมา
ปัญหาอื่นที่ฉันเห็นมีอยู่ว่า.encode()
วิธีสตริงส่งกลับสตริงที่แก้ไขและไม่ได้แก้ไขแหล่งที่มา ดังนั้นมันจึงไม่มีประโยชน์ที่จะมีself.response.out.write(html)
html ไม่ใช่สตริงที่เข้ารหัสจาก html.encode (ถ้านั่นคือสิ่งที่คุณตั้งใจไว้ตั้งแต่แรก)
ตามที่อิกนาชิโอแนะนำให้ตรวจสอบหน้าเว็บต้นทางสำหรับการเข้ารหัสสตริงที่ส่งคืนread()
จริง มันอาจเป็นหนึ่งในแท็ก Meta หรือในส่วนหัว ContentType ในการตอบสนอง .decode()
ใช้นั้นเป็นพารามิเตอร์สำหรับ
โปรดทราบว่าไม่ควรถือว่าผู้พัฒนารายอื่นมีความรับผิดชอบเพียงพอที่จะตรวจสอบให้แน่ใจว่าการประกาศชุดอักขระส่วนหัวและ / หรือเมตาตรงกับเนื้อหาจริง (ซึ่งเป็น PITA ใช่ฉันควรรู้ฉันเป็นหนึ่งในนั้นก่อนหน้านี้)