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 太大了.
所以, 提升 scrapy 爬取效率的方式有:
1) 在 settings.py 里把 DOWNLOAD_DELAY 设置小一点 (保证 IP 不被封的情况下)
2) 提高并发数 ( CONCURRENT_REQUESTS ) #也并不是越多越好, CPU 调度有上限
3) 瓶颈在 IO , 所以很有可能 IO 跑满, 但是 CPU 没跑满, 所以你用 CPU 来加速抓取其实是不成立的. 不如开几个进程来跑, 这样 CPU 就跑满了
4) 在 setting.py 里面, 可以把单 IP 或者单 domain 的 concurrent 线程数改成 16 或者更高, 16 线程对一般的网站来说根本没问题, 而且 scrapy 自己的调度和重试系统可以保证每个页面都成功抓取
5) 动态页面最好找 Ajax 传输的 JSON 数据, 然后抓取其中需要的内容
6) 对于定向采集可以用正则取代 xpath(或 BS)
7) 代理
8) 可以考虑 gevent , 针对爬虫这种网络 IO 密集型的. 效率会很高
9) 搭建分布式爬虫
来源: https://www.cnblogs.com/heranly-go/p/10189023.html