是我对于协程的用法有误还是 http 请求本身就这么消耗资源 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
just1
V2EX    Python

是我对于协程的用法有误还是 http 请求本身就这么消耗资源

  •  
  •   just1 2020-06-29 19:13:59 +08:00 4281 次点击
    这是一个创建于 1931 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原有的代码是爬虫,化简完代码是这样

    import asyncio import aiohttp async def worker(): while 1: try: async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=5)) as session: async with session.post('https://www.baidu.com') as r: _ = await r.text() except RuntimeError: break async def main(): await asyncio.wait([worker() for _ in range(100)]) if __name__ == '__main__': loop = asyncio.get_event_loop() loop.run_until_complete(main()) loop.close() 

    只需要不到 100 个协程,cpu 单核就可以 100%,是我对于协程有错误的理解吗,求指点

    21 条回复    2020-07-02 11:12:33 +08:00
    xiaolinjia
        1
    xiaolinjia  
       2020-06-29 19:32:27 +08:00
    你这不是 100 个。是 100 x while 循环的次数个。
    arrow8899
        2
    arrow8899  
       2020-06-29 19:43:08 +08:00
    不是你这么用的。。。
    j0hnj
        3
    j0hnj  
       2020-06-29 19:52:38 +08:00   1
    百度要被你干死了……
    just1
        4
    just1  
    OP
       2020-06-29 20:00:04 +08:00 via Android
    @xiaolinjia
    @arrow8899
    @j0hnj 求指点...实际工作的脚本应该是从 queue 获得目标 url,这里简化写成了死循环而已
    14v45mJPBYJW8dT7
        5
    14v45mJPBYJW8dT7  
       2020-06-29 20:02:47 +08:00
    ```import asyncio

    import aiohttp


    async def worker(url):
    try:
    async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=5)) as session:
    async with session.post(url) as r:
    _ = await r.text()
    except RuntimeError:
    break


    async def main():
    urls = ["https://baidu.com", "https://baidu.com"]
    await asyncio.wait([worker(url) for url in range(urls)])


    if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()```
    Vibra
        6
    Vibra  
       2020-06-29 20:02:59 +08:00 via iPhone
    @j0hnj 没有 ua 百度不会理你的
    just1
        7
    just1  
    OP
       2020-06-29 20:19:26 +08:00 via Android
    @rimutuyuan 实际工作的脚本应该是从 queue 获得目标 url,这里简化写成了死循环而已
    crella
        8
    crella  
       2020-06-29 21:39:42 +08:00   1
    如果你要爬取得网站网速快的话,那么平均每两次下载的时间间隔很小,而代码中又是 100 个 worker(),那么可以认为每两次下载时间没有空闲时间,cpu 的单核占用就是达到了 100%
    just1
        9
    just1  
    OP
       2020-06-29 22:18:52 +08:00
    @crella #8 大概可能是这个情况,但是我的疑惑在于 http 会这么消耗 cpu 吗?运行时网络不过是大概 send340kb/s,recv900kb/s (不过小包比较多)
    如果这样好像除了堆机器、开多进程,是不是没有办法优化了?
    silencefly
        10
    silencefly  
       2020-06-29 22:22:43 +08:00 via iPhone
    如一楼的意思 是 100 个 job 一起跑 不是一个 job 跑 100 次
    just1
        11
    just1  
    OP
       2020-06-29 22:44:10 +08:00
    @silencefly #10 就是 100 个 job 一起所以引入协程,不然一个个太慢了
    tolerance
        12
    tolerance  
       2020-06-29 22:59:09 +08:00
    求教,写爬虫怎么才能不违法
    linvaux
        13
    linvaux  
       2020-06-29 23:12:58 +08:00
    @tolerance 做搜索引擎,而且体量要很大的那种
    imn1
        14
    imn1  
       2020-06-29 23:22:49 +08:00
    如果用的是板载网卡,是需要 CPU 处理数据的
    用那种死贵的独立网卡,可以卡内处理数据,省点 CPU
    msg7086
        15
    msg7086  
       2020-06-30 03:30:05 +08:00   1
    这也不是 HTTP 啊,这明明是 HTTPS 啊,初始化 TLS 秘钥交换多次握手不要钱的啊……
    leer
        16
    leer  
       2020-06-30 07:45:36 +08:00 via iPhone
    @tolerance 自己研究不违法,遵守爬虫协议
    lpts007
        17
    lpts007  
       2020-06-30 09:47:37 +08:00
    @just1 你知道 while 1 的意思吗 死循环内异步 单核满载不是意料之中吗,跟 http 协议有什么关系?
    再说你实际业务生产待爬 url 的速度 也不可能就是 while 1 吧。
    注意点别人网站的承受能力,别一不小心搞成攻击了。
    BingoXuan
        18
    BingoXuan  
       2020-06-30 10:04:03 +08:00   2
    https 需要消耗一定 cpu 资源去加解密的,而且你写的是 100x 的死循环请求。假如你一秒单线程能完成 10 次,那么实际就是 1000 次请求了。

    你需要去掉 while 循环,通过 asyncio 创建 size 为 100 的 queue,不断从 queue 中获取任务,通过 futures 来设置 result 或者 error
    yzk66880
        19
    yzk66880  
       2020-06-30 18:09:49 +08:00
    你这 while 1 。。。
    just1
        20
    just1  
    OP
       2020-06-30 20:01:54 +08:00
    @yzk66880 #19 怎么都不看题啊
    yucongo
        21
    yucongo  
       2020-07-02 11:12:33 +08:00
    网上有个 limited_as_completed ( asyncioplus )包,或许适应你要做的。limited_as_completed 的原始作者试过建议将 limited_as_completed 作为 asyncio 的内置标准函数,但好像不成功。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5460 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 08:33 PVG 16:33 LAX 01:33 JFK 04:33
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86