TypeError: 不能在 re.findall()中的类字节对象上使用字符串模式

我试图学习如何自动获取网页的网址。在下面的代码中,我试图获得网页的标题:

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)

我得到了一个意想不到的错误:

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

我做错了什么?

270354 次浏览

您需要使用 .decode(例如 html = response.read().decode('utf-8'))将 html (类似字节的对象)转换为字符串。

参见 将字节转换为 Python 字符串

问题是你的正则表达式是一个字符串,但是 html字节:

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

因为 python 不知道这些字节是如何编码的,所以当您尝试对它们使用字符串 regex 时,它会抛出异常。

您可以将字节转换为字符串:

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

或者使用字节 regex:

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

在这个特定的上下文中,您可以从响应头中获得编码:

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

有关详细信息,请参阅 urlopen文档

基于最后一个,这是很简单的做当 pdf 阅读完成。

text = text.decode('ISO-8859-1')

谢谢@Aran-fey