爬虫demo_爬虫(四)异步/分布式爬虫的常见库及优缺点总结

哈哈,之前说过的三四天一更,这次足足等了一周= =主要是没时间,趁着今天周六写点东西吧

这一篇主要介绍python中各异步/网络/分布式框架,教你如何不使用scrapy/pyspider进行异步/分布式爬虫。可能你会觉得,为什么有scrapy不用,要自己用别的库手写爬虫呢?其实很简单,scrapy是一个别人写好的框架,优点是提供了很多别人写好的接口,也可以通过简单的代码来自定义很多功能,而缺点其实也在于此,有些简单的功能其实只需要几行代码就能做到,而到了scrapy中你可能要用十多行甚至更多去实现它。另外,scrapy最大的缺点就是它的报错,由于它是基于twisted的,出错后并不会停止爬虫,而我们要捕捉错误就必须自定义中间件,使其通过我们自己想要的方式去处理它。因此,你必须提前想好哪儿可能出错,在爬虫之前去处理它,因为开始爬虫后,错误并不会终止你的爬虫程序。而自己写的异步处理就不会出现这种问题,你可以用一万种方式使程序出错后终止整个爬虫。

开始之前我们先来一段简单的requests爬虫以及多进程和scrapy爬虫,来看看他们的性能如何,方便后面的比较。目标网站:

正在播放《蜘蛛侠:英雄远征》 - 高清线路 - 小收影院​www.p4yy.com

这是百度搜蜘蛛侠英雄远征免费观看后出来的第一个网站,所以大家不要喷我分享盗版资源,是百度分享的。。。我们的目标是把这部电影爬下来。

0. requests爬虫

import requests
import re
import time

start_time = time.time()
url = 'https://rescdn.yishihui.com/longvideo/transcode/pic/live/2019070363431356wFLNws3GGuosTiVem.m3u8'
m3u8 = requests.get(url).text
url_list = re.findall(r'.*ts', m3u8)

with open('requests_spider.ts', 'wb') as f:
    for url in url_list:
        ts = requests.get('https://rescdn.yishihui.com/longvideo/transcode/pic/live/' + url).content
        f.write(ts)
        print(url, '下载完毕')

print('下载完毕n消耗时间:', time.time() - start_time)

下面是运行时间

2df90c2615287c721601f5ca8fe17cb2.png

可以看到只用requests爬虫,用了679秒下载完了整部电影

接下来是多线程,多线程thearding或者future都可以,这里贴一个future的demo:

import requests
import re
import time
import os
from concurrent import futures

start_time = time.time()
url = 'https://rescdn.yishihui.com/longvideo/transcode/pic/live/2019070363431356wFLNws3GGuosTiVem.m3u8'
m3u8 = requests.get(url).text
url_list = re.findall(r'.*ts', m3u8)

def get_ts(url):
    ts = requests.get('https://rescdn.yishihui.com/longvideo/transcode/pic/live/' + url).content
    with open(url[-8:], 'wb') as f:
        f.write(ts)
        print(url, '下载完毕')

executor = futures.ThreadPoolExecutor(max_workers=20)
future_tasks = [executor.submit(get_ts, url) for url in url_list]
futures.wait(future_tasks, return_when=futures.ALL_COMPLETED)

download_time = time.time() - start_time

with open('future_spider.ts', 'wb') as fff:
    for url in url_list:
        file_name = url[-8:]
        with open(file_name, 'rb') as f:
            byte = f.read()
            fff.write(byte)
            print(file_name, '加入完毕')
        os.remove(file_name)

print('下载完毕n下载消耗时间:',download_time , 'n总消耗时间:', time.time() - start_time)

需要注意的是,多线程和后面的异步/分布式都不能直接将ts片段拼接到一起,必须全部下载完毕后依次读取拼接,这是因为并发/异步/分布式都是发起/接收请求都是无序的。那我们看一下多线程的消耗时间

a99e9cb936c2ed48906cca58e1b60a7c.png

可以看到,多线程用了338秒,需要注意的是,由于在第一次测试中,打开文件的操作只有一次,而多线程中打开文件操作有着800多次,因此实际请求的时间应该还会再短一点。

再接下来是协程,即异步爬虫,gevent和aiohttp都可以写,鉴于aiohttp网上一堆教程(同时鉴于gevent代码量更少),写一个简单的gevent的demo

from gevent import monkey
monkey.patch_all()

import os
import re
import time
import gevent
import requests


start_time = time.time()
url = 'https://rescdn.yishihui.com/longvideo/transcode/pic/live/2019070363431356wFLNws3GGuosTiVem.m3u8'
m3u8 = requests.get(url).text
url_list = re.findall(r'.*ts', m3u8)

def get_ts(url):
    ts = requests.get('https://rescdn.yishihui.com/longvideo/transcode/pic/live/' + url).content
    with open(url[-8:], 'wb') as f:
        f.write(ts)
        print(url, '下载完毕')

gevent.joinall([gevent.spawn(get_ts, url) for url in url_list])

download_time = time.time() - start_time

#注意这是另一个文件
with open('gevent_spider.ts', 'wb') as fff:
    for url in url_list:
        file_name = url[-8:]
        with open(file_name, 'rb') as f:
            byte = f.read()
            fff.write(byte)
            print(file_name, '加入完毕')
        os.remove(file_name)

print('下载完毕n下载消耗时间:',download_time , 'n总消耗时间:', time.time() - start_time)

注意这段代码只能在linux上跑,windows上关于进程线程协程的程序总是随缘出错,线程协程尤为明显。(我本来用腾讯云的服务器跑了这段demo,但是之前的是用windows跑的,又懒得再拿linux跑+截图,而两者的网络环境/硬件都不一样,对比起来没什么意义,而且这段代码不是很严谨,patch_all会给文件的读写操作也打上猴子补丁,跟之前的几个没法比了,太快了)干脆直接告诉大家结果吧。。使用协程进行异步爬虫是远远快于前两个的。

说完这些暂停一下,介绍几个扩展库吧

  • grequests,是一个gevent和requests的结合,但是功能比较单一,适合写个小demo对网站爬虫测试用,以下为grequests源码
https://github.com/spyoungtech/grequests/blob/master/grequests.py​github.com

教程就不发了,因为用的确实不是很多,不过源码值得一看,能让你更熟练的运用gevent。

  • aiohttp,搭配asyncio即可进行异步爬虫,网上教程一大堆,也不多说。这个源码有兴趣的可以看看,没必要死磕,因为虽然很好但是大多数代码都用在了web搭建上,下面是一个简单的demo和源码
Python异步模块asyncio/aiohttp(链家爬虫实例)​www.jianshu.com
6ecd447c9d8bc2caa23eb129ee7256e7.png
链家爬虫代码_asyncio​www.jianshu.com
  • twisted,这个如果你是爬虫新手,不必了解太多,但是如果你不了解它,永远不要说自己精通scrapy。建议把下面链接收藏起来,平时没事的时候看两眼
我看到的最棒的Twisted入门教程! - 小西红柿 - 博客园​www.cnblogs.com
564774e5f9505ea971edf7ff60e7a71e.png

多线程和异步说完,就是分布式了。scrapy和pyspider实现分布式也不多说,百度一下你就知道。下面简单介绍几个分布式的框架

  • multiprocessing的managers模块。我们知道,multiprocessing是多进程模块,而它的子模块managers支持把进程分布到多台机器中,进而实现分布式程序。demo如下
https://blog.csdn.net/u012731379/article/details/64125766​blog.csdn.net

这是系统自带的库,源码可以自己在python/libs/site-packages中学习

  • celery,圈重点,这是一个非常强大的分布式框架,配合redis或rabbitMQ(你可以理解为一个和redis类似的消息收发中转站)能够简单快速的搭建分布式系统,它还自带定时功能,定时爬虫特别方便。不过......由于本人还在学习阶段,对它也并没有多深的理解,就直接甩给大家一份官方文档吧= =目前自己也在看这玩意儿。
Celery - Distributed Task Queue​docs.celeryproject.org
b5faf89b3430f1ec08aea02bf5efb665.png

celery源码:

celery/celery​github.com
43ef2be027eabe13ce03e9b58d1d9b67.png
  • gerapy,这是一个崔大大基于scrapy,scrapyd,scrapy-redis,scrapyd-api,scrapy-splash,jinjia2,django,vue.js,docker等编写的分布式爬虫框架。爬虫语法建构什么的和scrapy一样,支持直接部署爬虫,前端的可视化监控,一台主机管理整个分布式爬虫。安装直接pip install gerapy即可,源码如下:
Gerapy/Gerapy​github.com
2c595ff9c52713ccf6f455cf6c1115f6.png

其实大多都是调用已有的api进行封装,所以源码不是很难理解,建议没事可以看看,也算是巩固自己的scrapy了,用法在readme中有个大概,主要还是自己摸索,不是很难学会。崔大大nb!( 破音声~~)

这篇文章就到这儿了,以后每周一更,周六或者周日~

因为网上的app爬虫教程太少了,而且质量都很一般。pc端网页爬虫大多也是教你怎么反爬,很少有教你怎么全方面提高爬虫效率的,下一篇可能写这两个中的一个(app爬虫可能要连载好多)。想看哪个或者爬虫方面有问题的都可以评论留言(拯救零回复)或者直接私信探讨。点不点赞收不收藏评不评论其实都无所谓,大佬们给个关注行不行(手动狗头)

f747897a135c5858f9bb42a8672ade54.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值