1 第一个网络爬虫(3)

连接可靠性

网页是复杂的。数据的格式差,随着网站的宕机,可使用的标签也会消失。在网络爬虫中最令人感到挫折的经历之一就是:让爬虫运行,睡觉,梦到第二天你在你的数据库中看到了所有的数据,然而,现实是---仅仅返现了爬虫遇到了一个意想不到的数据格式的小错误,在你关闭电脑屏幕之后不久就停止了任务的执行。在相类似的情形下,你可能是对构建网络的编程人员诅咒,然而,那个应该真正被你鄙视的应该是你自己,由于你没有在第一时间处理这个异常。

让我们看看我们爬虫的第一行,在重要的描述之后,搞明白如何去处理可能的异常:

html = urlopen("http://www.pythonscraping.com/pages/page1.html")

在这一行中,有两个错误的地方:
服务器中没有这个网页(或者获取它有一些错误)
服务器没有发现

在第一种情况下,会返回一个HTTP错误。这个HTTP错误可能是“404 Page Not Found”,“500 Internal Server Error”,等等。在这些情况下,urlopen会返回一个常见的异常“HTTPError”。我们以下面的方式来处理:

try:
    htmul = urlopen("http://www.pythonscraping.com/pages/page1.html")
except HTTPError as e:
    #return null, break, or do some other "Plan B"
else:
    #program continues. Note: If you return or break in the exception catch, you do not need to use "else" statement.

如果一个HTTP错误代码被返回,程序会输出错误,且不会执行else下的其他代码。

HTTPError 需要加入包 from urllib.error import HTTPError

如果始终没有发现服务器(比如说:http://www.pythonscraping.com 宕机了,或者 URL 被错误录入),urlopen会返回一个 None对象。这个对象与其他编程语言的null一致。我们可以增加一个检测去看看返回的是否是None:

if html is None:
    print("URL is not found")
else:
    #program continues

当然,如果网页能够成功地从服务器检索出来,仍然有一些问题,即网页的内容并不是我们所期待的。每一次,你调用BS对象的一个标签,检查该标签是否存在是非常明智的。如果你尝试去调用一个不存在的标签,BS会返回一个None对象。问题是,尝试调用一个None对象的标签会返回一个AttributeError结果。

下面的语句会返回一个None对象:

print(bsObj.nonExistentTag)

其中,nonExistentTag是一个捏造的标签,并不是一个真正的BS函数。对这个对象的处理和检查时完全合理的。如果你不检查它,反而继续且试图去调用None对象的函数,就会产生一些问题,下面是一个例子:

print(bsObj.nonExistentTag.someTag)

该语句会返回一个异常:

AttributeError: 'NoneType' object has no attribute 'someTag'

所以,我们如何处理这两个情况?最简单的方式是明确地检查这两种情况:

try:
    badContent = bsObj.nonExistingTag.anotherTag
except AttributeError as e:
    print("Tag was not found")
else:
    if badContent == None:
        print("Tag was not found")
    else:
        print(badContent)

对于每个错误的检查和处理确实是繁琐的,但是,我们可以很容易地对代码进行改编,使得写代码变得不那么困难(更重要的是,使得读代码变得不那么困难)。这段代码,可以以下面稍微不同的方式来写我们的爬虫:

from urllib.request import urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup

def getTitle(url):
    try:
        html = urlopen(url)
    except HTTPError as e:
        return None
    try:
        bsObj = BeautifulSoup(html.read())
        title = bsObj.body.h1
    except AttributeError as e:
        return None
    return title

title = getTitle("http://www.pythonscraping.com/pages/page1.html")
if title == None:
    print("Title could not be found")
else:
    print(title)

在这个例子中,我们构造了一个getTitle函数,该函数会返回一个网页的标题,或者在出现错误的情况下返回一个None对象。在getTitle内部,我们检查了之前例子中的HTTPError错误,然后,封装了两个BS语句。任何一个AttributeError都可能从这两个语句中出现(比如:如果服务器不存在,html会返回一个None对象,然后html.read()会抛出一个AttributeError)。

当写爬虫的时候,很重要的一点就是思考你的代码的全部的模式,这是为了处理异常以及代码具有可读性。你也有可能会再次使用这些代码。构造常用的函数,比如getSiteHTMLgetTitle,会是得爬整个网络变得快速以及可靠。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值