爬虫效率提升(线程池+asyncio)

一.线程池

import requests
import time
from multiprocessing.dummy import Pool
start = time.time()
pool = Pool(3)
urls = [
    'http://127.0.0.1:5000/index',
    'http://127.0.0.1:5000/index',
    'http://127.0.0.1:5000/index'
]
#用作与网络请求(耗时)
def req(url):
    return requests.get(url).text

page_text_list = pool.map(req,urls)
print(page_text_list)
print('总耗时:',time.time()-start)

二.asyncio

2.1 asyncio简单认识

asyncio用来实现单线程+多任务异步协程

1. asyncio的几大学习对象

  • 特殊函数
- 就是async关键字修饰的一个函数的定义
- 特殊之处:
    - 特殊函数被调用后会返回一个协程对象	
    - 特殊函数调用后内部的程序语句没有被立即执行
  • 协程
对象。协程==特殊的函数。协程表示的就是一组特定的操作。
  • 任务对象
- 高级的协程(对协程的进一步的封装)
	- 任务对象==协程==特殊的函数
	- 任务对象==特殊的函数
- 绑定回调:
	- task.add_done_callback(task)
	- 参数task:当前回调函数对应的任务对象
	- task.result():返回的就是任务对象对应的特殊函数的返回值
  • 事件循环对象
- 创建事件循环对象
    - 将任务对象注册到该对象中并且开启该对象
    - 作用:loop可以将其内部注册的所有的任务对象进行异步执行

重点!!!!

在特殊函数内部的实现中,不可以出现不支持异步的模块代码(如time.sleep()、request),如果出现了,则会中断整个的异步效果!!!

2. 代码实现

import asyncio
from time import sleep

#特殊的函数
async def get_request(url):
    print('正在下载:',url)
    sleep(2)
    print('下载完毕:',url)

    return 'page_text'
#回调函数的定义(普通的函数)
def parse(task):
    #参数表示的就是任务对象
    print('i am callback!!!',task.result())

#特殊函数的调用
c = get_request('www.1.com')

#创建一个任务对象
task = asyncio.ensure_future(c)
#给任务对象绑定一个回调函数
task.add_done_callback(parse)

#创建一个事件循环对象
loop = asyncio.get_event_loop()
#将任务对象注册到该对象中并且开启该对象
loop.run_until_complete(task)#让loop执行了一个任务

2.2 多任务协程

import asyncio
from time import sleep
import time
#特殊的函数
async def get_request(url):
    print('正在下载:',url)
    await asyncio.sleep(2)  #在任务中有阻塞,前面加上await
    print('下载完毕:',url)

    return 'i am page_text!!!'
def parse(task):
    page_text = task.result()
    print(page_text)

start = time.time()
urls = ['www.1.com','www.2.com','www.3.com']

tasks = []#存储的是所有的任务对象。多任务!
for url in urls:
    c = get_request(url)
    task = asyncio.ensure_future(c)
    task.add_done_callback(parse)
    tasks.append(task)

loop = asyncio.get_event_loop()
#asyncio.wait(tasks):给每一个任务对象赋予一个可被挂起的权限
loop.run_until_complete(asyncio.wait(tasks))

print('总耗时:',time.time()-start)

2.3 基于aiohttp的多任务异步爬虫

因为requests模块不支持异步,因此引入aiohttp

1.安装

pip install aiohttp

2.代码实现

import asyncio
import aiohttp
import time
from bs4 import BeautifulSoup
#将被请求的url全部整合到一个列表中
urls = ['http://127.0.0.1:5000/bobo','http://127.0.0.1:5000/jay','http://127.0.0.1:5000/tom']
start = time.time()

async def get_request(url):
    async with aiohttp.ClientSession() as s:
        #s.get(url,headers,params,proxy="http://ip:port")
        async with await s.get(url) as response:
            #response.read()二进制(.content)
            page_text = await response.text()
            return page_text

def parse(task):
    page_text = task.result()
    soup = BeautifulSoup(page_text,'lxml')
    data = soup.find('div',class_="tang").text
    print(data)
tasks = []
for url in urls:
    c = get_request(url)
    task = asyncio.ensure_future(c)
    task.add_done_callback(parse)
    tasks.append(task)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

print('总耗时:',time.time()-start)
posted @ 2019-12-06 20:46  MISF  阅读(745)  评论(0编辑  收藏  举报
     JS过度和变形效果演示   
  
    html5.png