"""
----异步回调----
异步任务使用场景
爬虫
1.从目标站点下载网页数据 本质就是HTML格式字符串
2.用re从字符串中提取出你需要的数据
什么是回调(函数)
a 交给 b一个任务 b在执行完成后回过头调用了a的一个函数 就称之为回调
为什么需要回调函数?
需要获取异步任务的结果,但是又不应该阻塞(降低效率)
高效的获取任务结果
(像生产者与消费者,生产者生产了产品后,通知消费者过来消费,消费者不需要一直等待生产者)
通常异步任务都会和回调函数一起使用
使用方式:
使用add_done_callback函数()给Future对象绑定一个回调函数
注意:在多进程中回调函数 是交给主进程来执行 而在多线程中 回调函数是谁有空谁执行(不是主线程)
"""
#-----进程中使用异步回调来处理结果----
import requests, re, os
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import current_thread
# 请求下载一个网业的数据
response = requests.get("https://www.baidu.com")
# 下载网站的数据,转换格式
htm = response.content.decode("utf-8")
# 用正则表达式取出网页里面的所有链接
# print(re.findall("href=.*?com",htm))
def get_data(url):
print("%s 正在请求%s" % (os.getpid(), url))
# 下载网址的内容
response = requests.get(url)
print("%s 请求%s成功" % (os.getpid(), url))
# 返回出去----1
return response
def parser(obj):
# 获得上一段代码的返回值
res = obj.result()
htm = res.content.decode("utf-8")
ls = re.findall("href=.*?com", htm)
print("%s解析完成! 共%s个连接" % (os.getpid(), len(ls)))
# 不加报错
if __name__ == '__main__':
urls = ["https://www.baidu.com",
"https://www.sina.com",
"https://www.tmall.com",
"https://www.taobao.com",
"https://www.jd.com",
"https://www.python.org",
"https://www.apple.com"]
# 用一个进程池 来开启进程
pool = ProcessPoolExecutor(3)
for i in urls:
# 循环取出urls 中的网址 交给进程池 得到执行完后的返回值
obj = pool.submit(get_data, i)
# res = obj.result() # 会把任务变成串行
# parser(res)
# 上一段代码执行完成后 会得到通知,继续执行下一段代码
obj.add_done_callback(parser)
# ----线程池中使用异步回调----
import requests, re, os
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import current_thread
def get_data(url):
# current_thread().name 获取执行线程的名字
print("%s 正在请求%s" % (current_thread().name, url))
response = requests.get(url)
print("%s 请求%s成功" % (current_thread().name, url))
return response
def parser(obj):
res = obj.result()
htm = res.content.decode("utf-8")
ls = re.findall("href=.*?com", htm)
print("%s解析完成! 共%s个连接" % (current_thread().name,len(ls)))
if __name__ == '__main__':
urls = ["https://www.baidu.com",
"https://www.tmall.com",
"https://www.taobao.com",
"https://www.jd.com",
"https://www.python.org",
"https://www.apple.com"]
pool = ThreadPoolExecutor(3)
for i in urls:
# 循环取出urls 中的网址 交给线程池 得到执行完后的返回值
obj = pool.submit(get_data, i)
# res = obj.result() # 会把任务变成串行
# parser(res)
# 上一段代码执行完成后 会得到通知,继续执行下一段代码
obj.add_done_callback(parser)