概述
scrapy基于twisted异步IO框架,downloader是多线程的。但是,由于python使用GIL(全局解释器锁,保证同时只有一个线程在使用解释器),这极大限制了并行性,在处理运算密集型程序的时候,Python的多线程效果很差,而如果开多个线程进行耗时的IO操作时,Python的多线程才能发挥出更大的作用。(因为Python在进行长时IO操作时会释放GIL)所以简单的说,scrapy是多线程的,不许要再设置了,由于目前版本python的特性,多线程地不是很完全,但实际测试scrapy效率还可以。
因为Python GIL的存在,scrapy无论如何设置都是单线程的。Scrapy里默认是10线程的设置是指的Twisted的线程,可以用来并行处理DNS之类的。但上面这些都不重要,因为爬虫是IO密集型的操作,所以只要有并发就可以了,无论是利用协程,callback还是其他方式实现并发。所以你要修改的不是线程数目而是Scrapy里request的并行数,只要这个数目大了一般速度都会增快,如果并行大了速度却没有提升,可能是DOWNLOAD_DELAY太大了,或者用了blocking的pipeline,等等原因吧需要自己去思考
-
在 settings.py 里把 TIMEOUT 设小点
-
提高并发数( CONCURRENT_REQUESTS )
-
瓶颈在 IO ,所以很有可能 IO 跑满,但是 CPU 没跑满,所以你用 CPU 来加速抓取其实是不成立的。不如开几个进程来跑死循环,这样 CPU 就跑满了
-
在 setting.py 里面,可以把单 IP 或者单 domain 的 concurrent 线程数改成 16 或者更高,我这两天发现 16 线程对一般的网站来说根本没问题,而且 scrapy 自己的调度和重试系统可以保证每个页面都成功抓取。
-
至于分布式,前提还是被抓的服务器可以接受,在这个前提下,我有个比较笨的方法:
-
假定页面数是已知的,而且主页面的 url 是有规律的,例如 wordpress 的很多就是 domain.com/page/2000 这样的,同样的工程开 100 个进程,每个进程的 starturl 分别是 page/1 , page/21,page/41 这样的,然后自己实现一个 stopurl ,让这 100 个进程均摊 2000 个页面。一方面速度快(假定没有物理瓶颈),另一方面这 100 个进程相互独立,就算哪个进程挂掉,重跑的风险也被分摊了。
-
动态页面最好找ajax传输的json数据,然后抓取其中需要的内容
-
对于定向采集可以用正则取代xpath
-
快代理还是不稳定的,如果使用额的是电信网络的话,可以试试路由重播更新IP
-
快速的link extractor。python的SGMLParser实在是太慢了,使用SgmlLinkExtractor会让爬虫把大部分的时间都浪费在解析网页上,最好自己写一个link extractor(我们基于lxml写了一个,也可以用soup之类的库)。也可以用正则表达式来写link extractor,速度快,问题是不理解html语义,会把注释里的链接也包含进来。另外基于javascript重定向url也要在这里提取出来。
-
默认启动的话,可以看到scrapy有10个线程。但是,进行download以及parse 等一般性操作的时候,都是单线程的——都是在同一个线程内。
-
可以考虑gevent ,针对爬虫这种网络IO密集型的。效率会很高
-
先去试试urllib和urllib2,熟悉一下爬虫的基本思维。然后熟悉了大概之后看看requests,这也是urlliburllib2封装的,熟悉抓包和分析页面成分,了解POST、GET都是什么原理和实用
作者:凡_小火
链接:https://www.jianshu.com/p/d55b75d67206
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
最后
以上就是傻傻猫咪为你收集整理的scrapy 速度优化的全部内容,希望文章能够帮你解决scrapy 速度优化所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复