【aiohttp】

异步爬虫(协程)

协程

协程是运行在线程基础之上的,协程的出现一是因为当线程的数量较多时线程会占用非常多的内存,二是过多的线程切换时会占用大量的系统时间,协程切换时在用户态。
100个线程每个线程上运行一个协程则可以处理10000个任务。这样运行任务的开销远比运行10000个线程的小。
协程只有和异步IO结合起来才能发挥最大的威力,原因是有可能在协程中同样会调用到阻塞线程的任务,所以需要避免这种情况的出现,还有一个办法是基于编程语言的原生支持。

用于编写单线程并发代码的库,通过套接字和其他方式多路复用I/O访问资源、正在运行的网络客户端和服务器以及其他相关原语。

ClientSession

在网络请求中,一个请求就是一个会话,aiohttp使用ClientSession管理会话。

async with aiohttp.ClientSession() as session:
        async with session.get('http://httpbin.org/get') as resp

get()的必须参数只能是str类和yarl.URL的实例,还有别的如put delete head options patch等
可以将参数设置到参数中,传入到url中。

params = {'key1': 'value1', 'key2': 'value2'}
async with session.get('http://httpbin.org/get',
                       params=params) as resp:
    expect = 'http://httpbin.org/get?key2=value2&key1=value1'
    assert str(resp.url) == expect

获取响应内容

async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get('http://httpbin.org/get') as resp:
            print(resp.status)
            print(await resp.text(encoding=utf-8))
            await resp.read()  #可以访问非文本内容格式,访问图片,这种形式返回的是二进制也可以读取到
            
"""输出结果:
200
<!doctype html>
<html lang="zh-CN">
<head>
.....

请求的自定义

自定义Headers

请求时可以自定义Headers,让服务器认为是一个浏览器。

headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko)"
                      " Chrome/78.0.3904.108 Safari/537.36"
    }
await session.post(url, headers=headers)

自定义cookie

url = 'http://httpbin.org/cookies'
cookies = {'cookies_are': 'working'}
async with ClientSession(cookies=cookies) as session:
    async with session.get(url) as resp:
        assert await resp.json() == {
           "cookies": {"cookies_are": "working"}}

和asyncio结合使用

asyncio被用作多个提供性能Python异步框架的基础,包括网络服务和网站服务,数据库连接库,分布式任务队列等。往往是构建IO密集型和高级结构化网络代码的最佳选择。

import asyncio
from datetime import datetime

import aiohttp
from lxml import etree
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit"
                         "/537.36 (KHTML, like Gecko) "
                         "Chrome/72.0.3626.121 Safari/537.36"}


async def get_movie_url():
    req_url = "https://movie.douban.com/chart"
    async with aiohttp.ClientSession(headers=headers) as session:
        async with session.get(url=req_url, headers=headers) as response:
            result = await response.text()
            result = etree.HTML(result)
        return result.xpath("//*[@id='content']/div/div[1]/div/div/table/tr/td/a/@href")


async def get_movie_content(movie_url):
    async with aiohttp.ClientSession(headers=headers) as session:
        async with session.get(url=movie_url, headers=headers) as response:
            result = await response.text()
            result = etree.HTML(result)
        movie = dict()
        name = result.xpath('//*[@id="content"]/h1/span[1]//text()')
        author = result.xpath('//*[@id="info"]/span[1]/span[2]//text()')
        movie["name"] = name
        movie["author"] = author
    return movie

if __name__ == '__main__':
    start = datetime.now()
    loop = asyncio.get_event_loop()
    movie_url_list = loop.run_until_complete(get_movie_url())
    tasks = [get_movie_content(url) for url in movie_url_list]
    movies = loop.run_until_complete(asyncio.gather(*tasks))
    print(movies)
    print("异步用时为:{}".format(datetime.now() - start))

参考文章:https://www.jianshu.com/p/20ca9daba85f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值