TypeError: tidak dapat menggunakan pola string pada objek seperti byte di re.findall ()

108

Saya mencoba mempelajari cara mengambil url dari halaman secara otomatis. Dalam kode berikut saya mencoba mendapatkan judul halaman web:

import urllib.request
import re

url = "http://www.google.com"
regex = r'<title>(,+?)</title>'
pattern  = re.compile(regex)

with urllib.request.urlopen(url) as response:
   html = response.read()

title = re.findall(pattern, html)
print(title)

Dan saya mendapatkan kesalahan tak terduga ini:

Traceback (most recent call last):
  File "path\to\file\Crawler.py", line 11, in <module>
    title = re.findall(pattern, html)
  File "C:\Python33\lib\re.py", line 201, in findall
    return _compile(pattern, flags).findall(string)
TypeError: can't use a string pattern on a bytes-like object

Apa yang saya lakukan salah?

Inspired_Blue
sumber
1
kemungkinan duplikat dari Konversi byte ke string Python
gnat

Jawaban:

161

Anda ingin mengubah html (objek mirip byte) menjadi string menggunakan .decode, mis html = response.read().decode('utf-8').

Lihat Mengonversi byte menjadi String Python

berbatu
sumber
Ini memecahkan kesalahan TypeError: cannot use a string pattern on a bytes-like objecttetapi kemudian saya mendapat kesalahan seperti UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 1: invalid start byte. Saya memperbaikinya dengan menggunakan .decode("utf-8", "ignore"): stackoverflow.com/questions/62170614/…
baptx
"abaikan" mengabaikan. Jika itu yang Anda inginkan, maka semuanya baik-baik saja. Namun terkadang masalah semacam ini memungkiri masalah yang lebih dalam, misalnya hal yang ingin Anda dekode sebenarnya tidak dapat didekodekan atau dimaksudkan untuk menjadi, misalnya teks yang dikompresi atau dienkripsi. Atau mungkin perlu pengkodean lain seperti utf-16. Caveat emptor.
berbatu
28

Masalahnya adalah bahwa regex Anda adalah string, tetapi htmladalah byte :

>>> type(html)
<class 'bytes'>

Karena python tidak tahu bagaimana byte tersebut dikodekan, itu membuat pengecualian saat Anda mencoba menggunakan string regex padanya.

Anda dapat decodebyte ke string:

html = html.decode('ISO-8859-1')  # encoding may vary!
title = re.findall(pattern, html)  # no more error

Atau gunakan regex byte:

regex = rb'<title>(,+?)</title>'
#        ^

Dalam konteks khusus ini, Anda bisa mendapatkan pengkodean dari header respons:

with urllib.request.urlopen(url) as response:
    encoding = response.info().get_param('charset', 'utf8')
    html = response.read().decode(encoding)

Lihat urlopendokumentasi untuk lebih jelasnya.

Aran-Fey
sumber