【问题标题】:Python Urlib - Ignore Unicode ErrorPython Urllib - 忽略 Unicode 错误
【发布时间】:2018-04-13 23:38:52
【问题描述】:

我正在构建一个网络爬虫,但遇到了障碍。基本上,爬虫会找到 的所有值,然后尝试系统地导航到所有这些相关链接。例如,如果在http://example.com 的主页上有“home.html”和“about.html”链接,爬虫将通过并尝试请求基本域+新找到的域(例如http://example.com/home.htmlhttp://example.com/about.html)。

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

有没有一种方法可以构建一个 try / 除非发生这种情况时忽略 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 = 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

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

【问题讨论】:

  • 请将您的回溯发布为文本,而不是屏幕截图。

标签: python beautifulsoup web-crawler urllib


【解决方案1】:

要处理 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 格式,而是使用标题和/或元标记来告诉您实际编码是什么.

正确的做法是not trivial。使用requests 而不是urllib 可能会更开心,因为它内置了所有逻辑(除了最后的“启发式”步骤,但BeautifulSoup 完成了那部分)。

如果由于某种原因你不能使用标准库之外的任何东西:

  • 第一步很简单:page.headers.get_content_charset()
  • 最后一步很简单:如果你不知道编码,只需传递 BeautifulSoup 字节,它将使用“Unicode,该死的”启发式算法。
  • 另一方面,解析META 标签可能会很痛苦。您需要对二进制数据进行修正并交叉手指,或者使用非严格的错误处理将其解码为 ASCII 并对其进行修正,然后执行soup.find_all('meta'),并检查每个数据是否具有http-equiv="Content-Type" 属性charset 值或 charset 属性,然后您可以使用它来重新解码和重新整理。

【讨论】:

  • 是的,做到了!方便,谢谢!感谢您提供有关如何采用新请求方式的建议,我会对其进行更多研究,因为它可能会更好地扩展它!
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 2011-07-07
    • 2017-06-12
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 2018-08-25
    相关资源
    最近更新 更多