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
snachx
V2EX  ›  Python

python 多线程用 requests 抓网页的话,限制单位时间的总请求数有没有什么好的写法呢?

  •  
  •   snachx ·
    snachx · 2015-02-03 14:42:50 +08:00 · 6965 次点击
    这是一个创建于 3584 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RT,为了不给被抓页面造成太大压力或者说为了规避429 error,最合理的做法是什么呢?
    几乎没怎么用过多线程,到处搜索没有找到看起来比较好的写法,求教。

    21 条回复    2015-03-03 00:22:14 +08:00
    gateswong
        1
    gateswong  
       2015-02-03 14:47:54 +08:00
    http://bitbucket.gatesice.com/iit-cs579-project/src/f32486eb41571533d881a6a4d63fe97b10706c83/collector/timing.py?at=master

    在这个基础上增加一个count统计这个时间段内访问了多少次就好了
    KentY
        2
    KentY  
       2015-02-03 16:21:32 +08:00 via Android
    这个要看人家服务器是怎么制定的ban规则吧,你的单位时间得在人家范围内。

    我也曾有这个麻烦,后来去抓代理,built个代理池,先凑合顶着
    mengskysama
        3
    mengskysama  
       2015-02-03 17:06:02 +08:00
    goagent
    ryd994
        4
    ryd994  
       2015-02-03 17:46:35 +08:00 via Android
    每个请求后加一个延时,然后反过来换算频率
    snachx
        5
    snachx  
    OP
       2015-02-03 17:53:43 +08:00 via Android
    @KentY
    @mengskysama

    我是想知道自己主动遵守限制具体应该怎么做,而不是说怎么绕过限制
    snachx
        6
    snachx  
    OP
       2015-02-03 17:55:41 +08:00 via Android
    @ryd994 每个请求加延时感觉只在单线程情况下有效吧?
    snachx
        7
    snachx  
    OP
       2015-02-03 18:00:26 +08:00 via Android
    @gateswong 其实不加count都行,我觉得只要有一个统一的manager来负责发请求,直接在manager里面限制就行了,可是不知道怎么在多线程情况下实现
    ryd994
        8
    ryd994  
       2015-02-03 18:07:35 +08:00 via Android
    @snachx 多线程也可以啊,只要你线程数有限制。
    平均一下差不多
    mengskysama
        9
    mengskysama  
       2015-02-03 18:47:15 +08:00
    @snachx 令牌桶,啊实现十来行代码?
    zhwei
        10
    zhwei  
       2015-02-03 18:58:33 +08:00 via iPad
    Redis
    clino
        11
    clino  
       2015-02-03 18:58:41 +08:00 via Android
    线程池?
    Sylv
        12
    Sylv  
       2015-02-03 19:42:18 +08:00 via iPhone   ❤️ 1
    count 加个锁
    每次请求 count + 1
    使 count 加到限制次数的线程进行延时,不释放锁
    其它线程因为阻塞就一起延时了
    延时线程延时结束后 count 置 0,释放锁
    jecrdhs
        13
    jecrdhs  
       2015-02-03 20:53:46 +08:00
    抓网页是指下载页面中的某些信息还是全部?
    ffffwh
        14
    ffffwh  
       2015-02-03 21:46:24 +08:00
    “非计算密集的任务不要另开线程”。
    单线程抓网页,这样控制请求频率很容易了。然后异步处理结果。
    snachx
        15
    snachx  
    OP
       2015-02-03 21:49:15 +08:00
    @jecrdhs 提取部分信息
    ShiehShieh
        16
    ShiehShieh  
       2015-02-03 21:49:41 +08:00
    可以试试使用协程代替线程,都能解决IO阻塞问题,而且理论上协程的内核开销更小。
    Gevent,一个基于协程的网络库。
    snachx
        17
    snachx  
    OP
       2015-02-03 21:53:02 +08:00
    @clino 线程池只能控制同时请求的数量吧,如果每个线程非抓取任务的处理很快,还是会超。
    clino
        18
    clino  
       2015-02-03 21:59:28 +08:00
    @snachx 要不就用一个网站一个线程的做法好了,这样线程这里可以自己控制频度如果频度太高就自己sleep下,如果怕开太多线程开销太大可以改用协程,开大量协程的开销比线程小很多
    snachx
        19
    snachx  
    OP
       2015-02-03 22:00:50 +08:00
    @Sylv 你说的这样好像可以,我去试一下
    gateswong
        20
    gateswong  
       2015-02-04 04:47:43 +08:00
    @snachx 用multiprocessing

    这个库里的Manager可以创建进程间的共享变量
    tolerious
        21
    tolerious  
       2015-03-03 00:22:14 +08:00 via iPhone
    @zhwei 具体?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1118 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:07 · PVG 03:07 · LAX 11:07 · JFK 14:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.