单线程多任务异步抓取(asyncio)

协程

import asyncio
import time
#定义了一个特殊的函数
#特殊:调用后会返回一个协程对象,且函数内部的实现语句不会被立即执行
#创建一个协程对象
# async def test(num):
#     print(num)
#
# c = test(10)
# print(c)

#封装一个任务对象
# async def test(num):
#     print(num)
#
# c = test(10)
# #根据协程对象封装了一个任务对象
# task = asyncio.ensure_future(c)
# print(task)

#事件循环对象
async def request(url):
    print(‘正在请求:‘,url)
    time.sleep(2)
    print(‘请求完毕!‘,url)

c1 = request(‘www.1.com‘)

task_A = asyncio.ensure_future(c1)

#创建一个事件循环对象
loop = asyncio.get_event_loop()
#将任务对象注册到该对象中并且启动事件循环
loop.run_until_complete(task_A)

任务对象绑定回调

import asyncio
import time

async def request(url):
    print(‘正在请求:‘,url)
    time.sleep(2)
    print(‘请求完毕!‘,url)

    return url

#定义一个任务对象的回调函数
#task参数表示的就是该函数被绑定的那个任务对象
def task_callback(task):
    print(‘i am task_callback()‘)
    print(task.result())
    #task.result()返回的就是任务对象对应的特殊函数内部的返回值

c = request(‘www.xxx.com‘)

task = asyncio.ensure_future(c)
task.add_done_callback(task_callback)

loop = asyncio.get_event_loop()
loop.run_until_complete(task)

多任务异步协程

import asyncio
import time
start = time.time()
#在特殊函数内部不可以出现不支持异步模块相关的代码
async def request(url):
    print(‘正在请求:‘,url)
    # time.sleep(2)#time模块是不支持异步
    await asyncio.sleep(2)  #阻塞操作必须使用await关键字进行挂起
    print(‘请求完毕!‘,url)

    return url

urls = [
    ‘www.1.com‘,
    ‘www.2.com‘,
    ‘www.3.com‘
]
def task_callback(task):
    print(task.result())

tasks = [] #多任务列表:存放多个任务对象
for url in urls:
    c = request(url)
    task = asyncio.ensure_future(c)
    task.add_done_callback(task_callback)
    tasks.append(task)  #将多个任务对象装在到一个任务列表中

loop = asyncio.get_event_loop()
#多任务注册
#wait就是将任务列表中的任务对象进行挂起
loop.run_until_complete(asyncio.wait(tasks))

print(time.time()-start)

多任务异步爬虫

import asyncio
import time
import requests
start = time.time()
#在特殊函数内部不可以出现不支持异步模块相关的代码
async def request(url):
   print(‘正在请求:‘,url)
   response = requests.get(url)
   return response.text

urls = [
    ‘http://127.0.0.1:5000/bobo‘,
    ‘http://127.0.0.1:5000/tom‘,
    ‘http://127.0.0.1:5000/jay‘
]

def parse(task):
    page_text = task.result()
    print(page_text+‘,请求到的数据!!!‘)

tasks = []
for url in urls:
    c = 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)

aiohttp使用

# import asyncio
# import time
# import aiohttp
# start = time.time()
在特殊函数内部不可以出现不支持异步模块相关的代码
简单的基本架构:
async def request(url):
   with aiohttp.ClientSession() as s:
       #s.get/post和requests中的get/post用法几乎一样:url,headers,data/prames
       #在s.get中如果使用代理操作:proxy="http://ip:port"
       with s.get(url) as response:
           #获取字符串形式的响应数据:response.text()
           #获取byte类型的:response.read()
           page_text = response.text()
           return page_text
在当前架构的基础上补充细节即可
    细节1:在每一个with前加上async关键字
    细节2:在get方法前和response.text()前加上await关键字进行手动挂起操作
# async def request(url):
   # async with aiohttp.ClientSession() as s:
       s.get/post和requests中的get/post用法几乎一样:url,headers,data/prames
       在s.get中如果使用代理操作:proxy="http://ip:port"
       # async with await s.get(url) as response:
           获取字符串形式的响应数据:response.text()
           获取byte类型的:response.read()
           # page_text = await response.text()
           # return page_text

urls = [
    ‘http://127.0.0.1:5000/bobo‘,
    ‘http://127.0.0.1:5000/tom‘,
    ‘http://127.0.0.1:5000/jay‘,
    ‘http://127.0.0.1:5000/bobo‘,
    ‘http://127.0.0.1:5000/tom‘,
    ‘http://127.0.0.1:5000/jay‘,
    ‘http://127.0.0.1:5000/bobo‘,
    ‘http://127.0.0.1:5000/tom‘,
    ‘http://127.0.0.1:5000/jay‘,
]
# urls = []
# for i in range(500):
    # urls.append(‘http://127.0.0.1:5000/bobo‘)
# def parse(task):
    # page_text = task.result()
    # print(page_text+‘,请求到的数据!!!‘)

# tasks = []
# for url in urls:
    # c = 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)

案列

import aiohttp
import asyncio
from lxml import etree

all_titles = []

headers = {
    ‘User-Agent‘:‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36‘

}
async def request(url):
    async with aiohttp.ClientSession() as s:
        async with await s.get(url,headers=headers) as response:
            page_text = await response.text()
            return page_text

urls = []
url = ‘http://wz.sun0769.com/index.php/question/questionType?type=4&page=%d‘
for page in range(100):
    u_page = page * 30
    new_url = format(url%u_page)
    urls.append(new_url)

tasks = []
def parse(task):
    page_text = task.result()
    page_text = page_text.encode(‘gb2312‘).decode(‘gbk‘)
    tree = etree.HTML(page_text)
    tr_list = tree.xpath(‘//*[@id="morelist"]/div/table[2]//tr/td/table//tr‘)
    for tr in tr_list:
        title = tr.xpath(‘./td[2]/a[2]/text()‘)[0]
        print(title)
        all_titles.append(title)

for url in urls:
    c = 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))

原文地址:https://www.cnblogs.com/youxiu123/p/11624378.html

时间: 2024-10-09 15:43:24

单线程多任务异步抓取(asyncio)的相关文章

爬虫第四章 单线程+多任务异步协程

单线程+多任务异步协程: asyncio 事件循环 loop: 无限循环的对象,事件循环中最终需要将一些特殊的函数注册到该事件循环中 特殊的函数: 被ansyc关键字修饰的函数 协程: 本质上是一个对象,可以把协程对象注册到事件循环中, 任务对象:就是对协程对象进一步的封装. 绑定回调函数(即在执行完特殊函数之后执行这个回调函数):task.add_done_callback(func) - func(task) :task 参数表示的就是绑定的任务对象 - task.result() 返回的就

单线程多任务异步协程

目录  1. 概念讲解 2. 多任务异步协程理解 3.基于aiohttp模块异步网络请求实现数据爬取及数据解析 一.需要了解的概念 特殊函数:如果async修饰了一个函数的定义,那么该函数就变成了一个特殊函数, 特殊之处:特殊函数被调用后函数内部实现语句不会被立即执行 该函数调用之后会返回一个协程对象 协程对象:特殊函数调用后可以返回一个协程对象 协程 == 特殊函数 任务对象:对协程对象的进一步封装,就是一个高级协程对象 任务对象 == 协程对象 == 特殊的函数 绑定回调:task.add_

基于线程池异步抓取

from multiprocessing.dummy import Pool #线程池模块 #必须只可以有一个参数 def my_requests(url): return requests.get(url=url,headers=headers).text start = time.time() urls = [ 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom', ] p

单线程实现了多任务异步协程

单线程+多任务异步协程: 意义:提升爬取数据的效率,我们也可以使用线程池, 异步爬虫方式: 多线程/多进程(电脑吃不消,没办法无节制开启)不建议 池:池中的线程或进程也是无法任意开启. 单线程+多任务异步协程(推荐)(500个协程,最优) 概念: 协程:本质就是一个对象,协程对象,怎么去获取?可以使用asynic该关键字去修饰一个函数定义,此时的函数就叫它特殊函数,当该特殊函数被调用之后,就可以返回一个协程对象,特殊之处不仅仅是返回一个协程对象,当函数内部实现的语句不会被立即执行(时间循环开启后

一个实用的C#网页抓取类代码分享

一个实用的C# 网页抓取类 模拟蜘蛛,类中定义了超多的C#采集文章.网页抓取文章的基础技巧,下面分享代码: using System; using System.Data; using System.Configuration; using System.Net; using System.IO; using System.Text; using System.Collections.Generic; using System.Text.RegularExpressions; using Sys

[Python爬虫] 之十:Selenium +phantomjs抓取活动行中会议活动(多线程抓取)

延续上个抓取活动行中会议活动的问题,上次使用是单线程的抓取,效率较低,现在使用多线程的抓取. 数据的抓取分为两个过程:首先获取每个关键字搜索结果对应的url和页数,保存在列表里面,这个过程用一个线程来实现(类似生产者),同时根据获取的关键字的url和页数,抓取对应的数据,这个过程用多线程来抓取(类似消费者) 这样整个抓取过程共用了144.366188 秒,采用单线程来进行抓取要用大概184秒,这样大概节省了40秒 具体代码如下: # coding=utf-8import osimport ref

Python 爬虫工程师必学 App数据抓取实战

第1章 课程介绍介绍课程目标.通过课程能学习到的内容.学会这些技能能做什么,对公司业务有哪些帮助,对个人有哪些帮助.介绍目前app数据抓取有哪些困难,面临的挑战,本实战课程会利用哪些工具来解决这些问题,以及本实战课程的特点 ... 1-1 python爬虫工程师必备技能--App数据抓取实战课程导学第2章 windows下搭建开发环境介绍项目开发需要安装的开发软件,讲解了安卓模拟器对比以及夜神安卓模拟器安装.介绍.简单使用和Genymotion安卓模拟器简单分析 介绍App应用抓包工具对比以及f

python爬虫--多任务异步协程, 快点,在快点......

多任务异步协程asyncio 特殊函数: - 就是async关键字修饰的一个函数的定义 - 特殊之处: - 特殊函数被调用后会返回一个协程对象 - 特殊函数调用后内部的程序语句没有被立即执行 - 协程 - 对象.协程==特殊的函数.协程表示的就是一组特定的操作. - 任务对象 - 高级的协程(对协程的进一步的封装) - 任务对象==协程==特殊的函数 - 任务对象==特殊的函数 - 绑定回调: - task.add_done_callback(task) - 参数task:当前回调函数对应的任务

Python从零开始写爬虫-3 获取需要抓取的URLs

Python从零开始写爬虫-3 获取需要抓取的URLs ??在一节中,我们学习了如果通过正则表达式来获取HTML里面指点便签的内容, 那么我今天就来看看实际的效果.在抓取小说之前, 我们需要知道小说有哪些章节,以及这些章节的顺序. ??刚开始我是通过获取一个章节, 然后从这个章节获取下个章节的链接, 然后发现这个方法问题很大. 该方法只能单线程操作, 对于抓取小说来非常的满, 几乎没有爬虫是单线程, 单线程的效率是无法被接受的. 鲁棒性差, 只要有一个章节没有正确的抓取下来, 那么整个程序就无法