爬网易云音乐评论数的优化历程

为什么要爬、怎么爬就不说了。

首先

我是第一次写爬虫。

使用的是Python,且没有使用爬虫框架。
仅仅靠requests和beautifulsoup来完成。

作者:轨迹。

方法一:最早使用的方法

爬取过程:
1、模拟请求
2、获取数据
3、入库

重复1-3来完成对一首音乐的评论数的爬取。

过程如图:
爬网易云音乐评论数的优化历程
该方法的不足之出在于:
每一次的网络IO都要等待本地IO,每一次的本地IO都要等待网络IO

实际操作时间:
爬100首:
爬网易云音乐评论数的优化历程

爬500首:
爬网易云音乐评论数的优化历程

爬5000首:
爬网易云音乐评论数的优化历程

我动了动小脑袋瓜,发现事情并没有这么简单:
平均一首需要:0.9秒
那么爬1,000,000就需要:900,000秒=250小时=10.4天
就算是个睿智都知道这划!不!来!

而且,当请求数不断得增加,即使本地IO保持稳定,但网络IO不好说呀。而且测试时间恰逢下午至晚上,这可能是网易云音乐服务器的高峰期,网络IO情况就更不容乐观了。

根据该方法的不足之处,我又写了一个方法二。

方法二:方法一的改进,让请求的只做请求,入库的只做入库。

既然方法一的网络IO和本地IO需要互相等待。

不如让网络IO跑在一个线程,本地IO跑在一个线程如何?
用FIFO队列作缓冲?

过程如图:
爬网易云音乐评论数的优化历程

爬100首:
爬网易云音乐评论数的优化历程
爬500首:
爬网易云音乐评论数的优化历程
爬5000首:
爬网易云音乐评论数的优化历程

很显然,时间消耗量下降了不是一点半点。

方法
100首 61.93 s 38.41 s
500首 445.23 s 418.30 s
5000首 4502.55 s 4974.57 s

方法三:多线程请求

在多线程上吃了点甜头之后,发现本地IO的消耗时间总是比网络IO的消耗时间多那么零点几秒。也就说,本地IO总是在等待网络IO请求到的数据。

为什么不多开几个网络IO的线程呢??

过程:
爬网易云音乐评论数的优化历程

等等,这不是生产者消费者问题吗!!

要不要加写锁?要不要加读锁?
额不不不,还好Python的Queue自带锁,是线程安全的!
那就放开写吧。

2线程各爬100:
爬网易云音乐评论数的优化历程
3线程各爬100:
爬网易云音乐评论数的优化历程
4线程各爬100:
爬网易云音乐评论数的优化历程
8线程各爬100:
爬网易云音乐评论数的优化历程
16线程各爬100:
爬网易云音乐评论数的优化历程

线程数 2 3 4 8 16
每个线程各100首 57.04s 63.57s 71.68s 120.43s 239.05s
平均每首 0.285s 0.2119s 0.1792s 0.1505s 0.1494s

很显然:
当网络IO的线程超过8后,提升非常小,可能是因为各网络IO线程在等待其他网络IO线程的写入。

最后

以0.15秒每首的速度爬一百万首,也需要1.73天。真让人头疼。。。