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

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

首先

我是第一次写爬虫。

使用的是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 s38.41 s
500首445.23 s418.30 s
5000首4502.55 s4974.57 s
方法三:多线程请求

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

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

过程:

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

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

2线程各爬100:

3线程各爬100:

4线程各爬100:

8线程各爬100:

16线程各爬100:

线程数234816
每个线程各100首57.04s63.57s71.68s120.43s239.05s
平均每首0.285s0.2119s0.1792s0.1505s0.1494s

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

最后

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

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

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

首先

我是第一次写爬虫。

使用的是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 s38.41 s
500首445.23 s418.30 s
5000首4502.55 s4974.57 s
方法三:多线程请求

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

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

过程:

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

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

2线程各爬100:

3线程各爬100:

4线程各爬100:

8线程各爬100:

16线程各爬100:

线程数234816
每个线程各100首57.04s63.57s71.68s120.43s239.05s
平均每首0.285s0.2119s0.1792s0.1505s0.1494s

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

最后

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