python爬虫容易被忽略的问题:确保可靠的网络连接
太阳HTTP
2021-03-19 19:05:5857浏览 · 0收藏 · 0评论
随着代理ip技术的普及,爬虫的使用也变得简单起来。 但网络是非常复杂的。网页数据格式不友好,网站服务器宕机,目标数据的标签找不到,都是很麻烦的事情。网络数据采集最痛苦的遭遇之一,就是爬虫运行的时候你洗洗睡了,梦想着明天一早数据就都会采集好放在数据库里,结果第二天醒来,你看到的却是一个因某种数据格式异常导致运行错误的爬虫。在前一天当你不再盯着屏幕去睡觉时,没过一会爬虫就不行了。针对这种情况,如何进行这种异常的处理方式:
让我们看看爬虫import语句后面的第一行代码,如何处理那里可能出现的异常:
html=urlopen("http://www.pythonscraping.com/pages/page1.html")
这行代码主要可能会发生两种异常:
(1)服务器不存在
(2)网页在服务器上不存在(或者获取页面的时候出现错误)
第一种异常情况,如果服务器不存在(就是说链接http://www.pythonscraping.com/打不开,或者是URL链接写错了),urlopen会返回一个None对象。这个对象与其他编程语言中的null类似。我们可以增加一个判断语句检测返回的html是不是none
if html is None:
print("URL is not found")
else:
#程序继续
当然,即使网页已经从服务器成功获取,如果网页上的内容并非完全是我们期望的那样,仍然会出现异常。每当你调用BeautifulSoup对象里的一个标签时,增加一个检查条件保证标签确实存在时很聪明的做法。如果你想要调用的标签不存在,BeautifulSoup就会返回None对象。不过,如果再调用这个None对象下面的子标签,就会发生AttributeError错误。
下面这行代码(notExistentTag是虚拟的标签,BeautifulSoup对象里实际没有)
print (bsObj.noExistentTag)
就会返回一个None对象,处理和检查这个对象是十分必要的。如果你不检查,直接调用这个None对象的子标签,麻烦就来了,如下所示
print (bsObj.noExistentTag.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)
第二种异常情况,程序返回HTTP错误。HTTP错误可能是“404 Page Not Found”"500 Internal Server Error"等。所有类似情形,urlopen函数都会抛出“Http Error”异常。我们可以用下面的方式处理这种异常:
try:
html=urlopen("http://www.pythonscrapinig.com/pages/page1.html")
except HTTPError as e:
print(e)
#返回空值,中断程序,或者执行另一个方案
else:
#程序继续:注意,如果你已经在上面异常捕捉那段代码里返回或中断(break)
#那么久不需要使用else语句了,这段代码也不会执行
如果程序返回HTTP错误代码,程序就会显示错误内容,不再执行else语句后面的代码。
整合上面的两种异常处理,一个全新的爬虫写法如下:
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(),"html.parser")
title=bsObj.body.h1
except AttributeError as e:
return None
return title
title=getTitle("http://pythonscraping.com/pages/page1.html")
if title == None:
print("Title Could not be found")
else:
print(title)
执行结果如下:
在这个例子中,我们创建了一个getTitle函数,可以返回网页的标题,如果获取网页的时候遇到问题就返回同一个None对象。在getTitle函数里面,我们像前面那样检查了HTTPError,然后把两行BeautifulSoup代码封装在一个try语句里面。这两行中的任何一行有问题,AttributeError都可能被抛出(如果服务器不存在,html就是一个None对象,html.read()就会抛出AttributeError). 其实,我们可以在try语句里面放任意多行代码,或者放一个在任意位置都可以抛出AttributeError的函数。
在写爬虫的时候,思考代码的总体格局,让代码既可以捕捉异常又容易阅读,这是很重要的。如果你还希望能够很大程度地重用代码,那么拥有像getSiteHTML和getTitle这样的通用函数(具有周密的异常处理功能)会让快速稳定地网络数据采集变得简单易行。
关注公众号,随时随地在线学习