利用grequest 实现高并发爬虫
grequests模块
GRequests是一个用requests和gevent写的异步http请求库。实现了真正的多并发请求,通过size参数设置一下同时并发数。
grequests底层使用的是requests,因此它支持GET,OPTIONS, HEAD,POST,PUT,DELETE 等各种http方法。
安装
pip install grequests
使用
实例化请求对象: grequests.request(method, url, **kwargs)
发起请求获得响应: grequests.map(requests, stream=False, size=None, exception_handler=None, gtimeout=None)
首先构造一个请求列表,使用grequests.map()并行发送,得到一个响应列表。
范例一
'''
简单的单个请求
'''
import grequests
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
}
url = "http://www.baidu.com"
task = []
req = grequests.request("get", url=url, headers=header)
task.append(req)
#此处map的requests参数是装有实例化请求对象的列表, 其返回值也是列表, size参数可以控制并发的数量
resp = grequests.map(task, size=5)
#查看返回的是Response的对象,可以参照requests的text,json,links,url,headers等属性
print(resp[0].text)
范例二
'''
多个url的请求
'''
import grequests
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
}
urls = ["https://www.baidu.com", "https://www.hao123.com", "https://www.taobao.com"]
task = (grequests.get(u) for u in urls)
resp = grequests.map(task, size=10) # 10个并发
print(resp)
事件钩子
grequests的底层库,是requests,因此它也支持事件钩子
'''
事件钩子
'''
import grequests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
}
def print_url(r, *args, **kwargs):
print('sss', r.url)
url = "https://www.baidu.com"
tasks = []
req = grequests.get(url, headers=headers, callback=print_url) #
tasks.append(req)
res = grequests.map(tasks)
异常处理
在批量发送请求时难免遇到某个请求url无法访问或超时等异常,grequests.map()方法还支持自定义异常处理函数。
'''
异常处理
'''
import grequests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
}
def err_handler(request, exception):
print("请求出错")
req_list = [
grequests.get('http://httpbin.org/delay/1', headers=headers, timeout=0.001), # 超时异常
grequests.get('http://nodomain/', headers=headers), # 该域名不存在
grequests.get('http://httpbin.org/status/500', headers=headers) # 正常返回500的请求
]
res_list = grequests.map(req_list, exception_handler=err_handler)
print(res_list)