TypeError:在re.findall()中无法在类似字节的对象上使用字符串模式。

173

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

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

我做错了什么?


1
可能是将字节转换为Python字符串的重复问题。 - gnat
3个回答

252

2
这解决了错误 TypeError: cannot use a string pattern on a bytes-like object,但是我又遇到了像 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 1: invalid start byte 这样的错误。我通过使用 .decode("utf-8", "ignore") 来修复它:https://dev59.com/urvoa4cB1Zd3GeqP2mKf#62170725 - baptx
“忽略”会被忽略。如果这正是您想要的,那么一切都很好。然而,有时这种问题掩盖了更深层次的问题,例如您想要解码的内容实际上无法解码或不应该解码,例如压缩或加密文本。或者它可能需要其他编码方式,如“utf-16”。请注意风险。 - rocky

56

问题在于你的正则表达式是一个字符串,但是html字节类型(bytes)

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

由于Python不知道这些字节的编码方式,当您尝试在它们上使用字符串正则表达式时,它会抛出异常。

您可以将字节解码成字符串:

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

或者使用字节正则表达式:

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

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

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

请参阅urlopen文档以获取更多详细信息。

0

基于上一个步骤,在完成PDF阅读后,这个步骤很容易实现。

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

感谢 @Aran-fey


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接