Python Urlib - 忽略Unicode错误

时间:2018-04-13 23:38:53

标签: python beautifulsoup web-crawler urllib

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

然而,在我的测试网站上,我设置了一个< a href =“file.pdf”>。当python中的urlib函数尝试请求.pdf文件时,我收到此错误:

http://example.com/about.html

有没有办法可以构建一个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

代码继续运行,但这是导致错误的主要部分。有任何想法吗?我想这是一个简单的解决方案。

2 个答案:

答案 0 :(得分:2)

要处理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执行该部分)

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

  • 第一步很简单:page.headers.get_content_charset()
  • 最后一步简单:如果你无法弄清楚编码,只需传递BeautifulSoup个字节,它就会使用" Unicode,该死的& #34;试探法。
  • 另一方面,解析META标签可能会很痛苦。您需要对二进制数据进行加密并交叉,或者使用非严格的错误处理解码为ASCII并对其进行解密,然后执行soup.find_all('meta'),并检查每个数据以查看它是否具有{{1如果属性具有http-equiv="Content-Type"值或charset属性,则您可以使用该属性重新解码并重新充值。

答案 1 :(得分:0)

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