Python Urlib - 忽略 Unicode 错误

Python Urlib - Ignore Unicode Error

我正在构建网络爬虫,但遇到了问题。基本上,爬虫找到 的所有值,然后尝试系统地导航到所有这些相关链接。例如,如果在 http://example.com there was the links "home.html" and "about.html" the crawler would move through and try to request the base domain + the newly found domain (ex. http://example.com/home.html, http://example.com/about.html 的主页上)。

但是,在我的测试站点上,我将其设置为 。当 python 中的 urlib 函数尝试请求 .pdf 文件时,出现此错误:

有没有一种方法可以构建一个 try / except,如果发生这种情况会忽略 URL?这是我当前的相关代码:

def soupify(url):
"""
:param: URL string.
:return: HTML BeautifulSoup object as html.parser
Process: Requests website for HTML code. If it responds, converts the code into IO stream so that it can become a
Soup object.
"""
# Header info so that the web server does not deny the request
hdr = {
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
req = urllib.request.Request(url, headers=hdr)
page = urllib.request.urlopen(req)

# This is to create in memory the HTML code of the page.
file = io.TextIOWrapper(page, encoding='utf-8')
fileContents = file.read()

soupObject = soup(fileContents, "html.parser")
return soupObject

下面是当我尝试实际访问 URL 后发生的情况。URL

url = baseDomain + queue[0]
queueLength = len(queue)
print("Queue:", queueLength)

isError = False

# Exception handling when attempting to make a soup object.
try: fileContents = soupify(url)
except urllib.error.HTTPError:  # If the website returns an HTTP error, such as a 404
    inaccessibleSites += 1
    isError = True
    queue.pop(0)
except urllib.error.URLError:  # If the website does not exist or does not have a valid URL
    inaccessibleSites += 1
    isError = True
    queue.pop(0)
# Here is where I want to build an except to handle the bad codec but I am not sure where to start

代码继续运行,但这是遇到错误的主要部分。有任何想法吗?我想这很容易解决。

我认为您只需在脚本底部添加一个 except UnicodeDecodeError: 就可以了。

要处理 UnicodeDecodeError,您需要执行与处理 urllib.error.HTTPErrorurllib.error.URLError.

完全相同的操作

所以:

try:
    fileContents = soupify(url)
except urllib.error.HTTPError:  # If the website returns an HTTP error, such as a 404
    inaccessibleSites += 1
    isError = True
    queue.pop(0)
except urllib.error.URLError:  # If the website does not exist or does not have a valid URL
    inaccessibleSites += 1
    isError = True
    queue.pop(0)
except UnicodeDecodeError:  # If the website is not in UTF-8
    inaccessibleSites += 1
    isError = True
    queue.pop(0)

或者,由于您实际上并没有对这三个错误做任何不同的事情,您可以使用一个 except:

try:
    fileContents = soupify(url)
except (urllib.error.HTTPError, # If the website returns an HTTP error, 
        urllib.error.URLError,  # If the website does not exist or does not have a valid URL
        UnicodeDecodeError):  # If the website is not in UTF-8
    inaccessibleSites += 1
    isError = True
    queue.pop(0)

但与此同时,您可能 真正 想在这里做的是停止假设每个网页都是 UTF-8,而是使用 headers and/or 元标记,告诉您实际编码是什么。

正确执行此操作是 not trivial. and you might be happier using requests 而不是 urllib,因为它具有所有内置逻辑(除了最后的 "heuristic" 步骤——但 BeautifulSoup 执行该部分) .

如果由于某种原因您不能使用 stdlib 之外的任何东西:

  • 第一步很简单:page.headers.get_content_charset()
  • 最后一步 简单:如果您不知道编码,只需传递 BeautifulSoup 个字节,它将使用 "Unicode, damnit"启发式。
  • 另一方面,解析 META 标签可能会很痛苦。您需要对二进制数据进行 soupify 并祈祷,或者使用 non-strict 错误处理解码为 ASCII 并对其进行 soupify,然后执行 soup.find_all('meta'),并检查每个数据以查看它是否具有 http-equiv="Content-Type" 属性具有 charset 值,或 charset 属性,那么您可以将其用于 re-decode 和 re-soupify.