在爬虫开发中,我们经常会遇到请求失败的情况,比如网络超时、连接错误、服务器拒绝等。这些情况会导致我们无法获取目标网页的内容,从而影响爬虫的效果和效率。为了解决这个问题,我们需要使用异常处理机制来捕获和处理请求失败的情况,从而提高爬虫的稳定性和稳定性。
异常处理机制的特点
异常处理机制是一种编程技术,用于在程序运行过程中发生异常时,能够及时捕获并处理异常,从而避免程序崩溃或者出现不可预期的结果。异常处理机制有以下几个特点:
- 可以预先定义可能发生的异常类型,并为每种异常类型指定相应的处理方法。
- 可以使用 try-except 语句来执行可能发生异常的代码,并在 except 子句中捕获并处理异常。
- 可以使用 raise 语句来主动抛出异常,并在上层调用处捕获并处理异常。
- 可以使用 finally 语句来执行无论是否发生异常都要执行的代码,比如关闭文件或者释放资源。
异常处理机制的案例
为了演示如何使用异常处理机制来捕获和处理请求失败的情况,我们将使用 requests 库来发送 HTTP 请求,并使用异步技术来提高爬虫的速度。同时,我们将使用亿牛云代理服务器来隐藏我们的真实 IP 地址和位置信息,以防止被目标网站封禁或者限制。
首先,我们需要导入 requests 库和 asyncio 库,并定义一个异步函数 send_request 来发送 HTTP 请求。在这个函数中,我们需要使用 try-except 语句来执行可能发生异常的代码,并在 except 子句中捕获并处理 requests.exceptions.RequestException 异常,这是 requests 库中最基本的异常类型,包含了所有与请求相关的异常。如果发生了这种异常,我们可以打印出异常信息,并返回 None 表示请求失败。如果没有发生异常,我们可以返回响应对象 response 表示请求成功。
import requests
import asyncio
# 定义一个异步函数 send_request 来发送 HTTP 请求
async def send_request(url):
# 使用 try-except 语句来执行可能发生异常的代码
try:
# 使用 requests 库发送 GET 请求,并设置超时时间为 10 秒
response = requests.get(url, timeout=10)
# 返回响应对象 response 表示请求成功
return response
# 在 except 子句中捕获并处理 requests.exceptions.RequestException 异常
except requests.exceptions.RequestException as e:
# 打印出异常信息
print(e)
# 返回 None 表示请求失败
return None
接下来,我们需要定义一个异步函数 get_proxy 来获取代理服务器的信息,并返回一个代理字典 proxy。在这个函数中,我们需要使用 requests 库的 auth 模块来生成一个 HTTPBasicAuth 对象,用于验证我们的代理账号和密码。然后,我们需要使用 requests 库的 get 方法来发送 GET 请求,并将 auth 参数设置为我们的 HTTPBasicAuth 对象,从而获取代理服务器的信息。如果请求成功,我们可以从响应对象 response 中提取代理服务器的 IP 地址和端口号,并构造一个代理字典 proxy,其中包含了 http 和 https 协议对应的代理地址。如果请求失败,我们可以返回 None 表示获取代理失败。
import requests
import asyncio
# 定义一个异步函数 get_proxy 来获取代理服务器的信息,并返回一个代理字典 proxy
async def get_proxy():
# 亿牛云 爬虫加强版 代理服务器
proxyHost = "www.16yun.cn"
proxyPort = "3111"
# 代理验证信息
proxyUser = "16YUN"
proxyPass = "16IP"
# 使用 requests 库的 auth 模块来生成一个 HTTPBasicAuth 对象,用于验证我们的代理账号和密码
auth = requests.auth.HTTPBasicAuth(proxyUser, proxyPass)
# 使用 requests 库的 get 方法来发送 GET 请求,并将 auth 参数设置为我们的 HTTPBasicAuth 对象,从而获取代理服务器的信息
response = requests.get("http://www.16yun.cn/api/ip", auth=auth)
# 如果请求成功
if response.status_code == 200:
# 从响应对象 response 中提取代理服务器的 IP 地址和端口号
ip = response.json()["data"][0]["ip"]
port = response.json()["data"][0]["port"]
# 构造一个代理字典 proxy,其中包含了 http 和 https 协议对应的代理地址
proxy = {
"http": f"http://{ip}:{port}",
"https": f"https://{ip}:{port}"
}
# 返回代理字典 proxy 表示获取代理成功
return proxy
# 如果请求失败
else:
# 返回 None 表示获取代理失败
return None
最后,我们需要定义一个异步函数 main 来执行主程序。在这个函数中,我们需要使用 asyncio 库的 gather 方法来创建一个任务列表 tasks,其中包含了多个 send_request 函数的调用,每个调用都传入一个目标网站的 URL。然后,我们需要使用 asyncio 库的 run 方法来运行这个任务列表,并等待所有任务完成。如果任务完成,我们可以遍历返回的结果列表 results,并打印出每个结果的状态码和内容长度。如果任务失败,我们可以打印出 None 表示请求失败。
import requests
import asyncio
# 定义一个异步函数 main 来执行主程序
async def main():
# 使用 asyncio 库的 gather 方法来创建一个任务列表 tasks,其中包含了多个 send_request 函数的调用,每个调用都传入一个目标网站的 URL
tasks = [
send_request("https://www.baidu.com"),
send_request("https://www.google.com"),
send_request("https://www.bing.com")
]
# 使用 asyncio 库的 run 方法来运行这个任务列表,并等待所有任务完成
results = await asyncio.gather(*tasks)
# 遍历返回的结果列表 results
for result in results:
# 如果结果不是 None 表示请求成功
if result is not None:
# 打印出结果的状态码和内容长度
print(result.status_code, len(result.content))
# 如果结果是 None 表示请求失败
else:
# 打印出 None 表示请求失败
print(None)
# 调用 main 函数来执行主程序
asyncio.run(main())
结语
通过上面的介绍和案例,我们可以看到,使用异常处理机制来捕获和处理请求失败的情况,可以有效地提高爬虫的稳定性和稳定性,从而避免程序崩溃或者出现不可预期的结果。同时,使用异步技术和代理服务器,可以进一步提高爬虫的速度和效率,从而爬取更多的目标网页。