协程:
在实现利用多进程方式爬取网站内容,首先得先知道什么是进程?
到这里,先来说说什么是同步和异步?
同步:比如我听完一首歌之后再听第二另首歌;
异步:比较好懂的是,我们经常去网盘下载东西,一般下载文件都比较多,这些文件同时都在下载,哪一个文件先下载好就先完成退出,而其他文件继续保持下载的状态。
那么,通过上面的例子介绍,显然是通过异步方式比同步方式的效率要高很多。
像爬虫的同步方式是向服务器发起请求并等待响应,服务器响应通知爬虫,爬虫响应,执行下一步的操作。
多协程原理:
这里引一下多协程原理:其实通过搜索引擎搜索就可以查看到详细的介绍。
用通俗易懂的话讲它就是一个任务在执行过程中,以下载文件为例:如果遇到等待下载的状态,就先去执行其他的任务,当等待结束之后,再回来继续下载之前的那个任务。一般这种任务来回切换是非常快速的,我们肉眼看上去就像多个任务在被同时执行一样,看不出区别来,但工作时间相比缩短很多,可以这么讲,多协程就是能够缩短工作时间的原理仅此而已。
gevent库:
好,接下来讲一个模块:叫monkey模块,在编写代码时候就从gevent库离导入monkey模块:
fromgeventimportmonkey
同时还需要写入这串代码:
monkey.patch_all()#也叫猴子补丁
作用:就是能够把程序变成协作方式运行,就是可以帮助程序实现异步的方式进行。
同时这里需要用到两个函数,分别是gevent.spawn(创建执行自定义函数的任务)和gevent.jionall(启动协程,执行任务列表里的所有任务)。
所以:gevent实现多协程爬取内容需要三步骤:1、自定义爬取函数;2、gevent.spawn创建任务;3、gevent.joinall执行任务。
queue队列:
这里面还需要提到一个queue模块:
queue模块也叫作队列模块,作用是可以用queue模块来存储任务,让任务都变成一条整齐的队列。因为queue其实是一种有序的数据结构,可以用来存取数据。这样,协程就可以从队列里把任务提取出来执行,直到队列空为止,任务也就处理完毕。
queue队列有以下几种方法,分别是:
put_nowait():往队列里存储数据;
get_nowait():从队列里提取数据;
empty():判断队列是否为空
full():判断队列是否为满;
qsize():判断队列还剩多少数量。
当然,queue模块也需要三步骤来建立,首先Queue()创建队列;其次用put_nowait()存储数据;最后用get_nowait()提取数据。
CSV文件存储写入和读写:
importcsv#导入csv模块#写文件file=open("demo.csv","w",newline="",encoding="utf-8")writer=csv.writer(file)writer.writerow(["链接","名称","点赞数"])#读文件file=open("demo.csv","r",newline="",encoding="utf-8")reader=csv.reader(file)forrowinreader:print(row)file.close()
准备的模块也准备得差不多了,下面就是程序的代码实现思路:
首先爬取内容,肯定是要有网站网址,爬取什么内容,以及HTML基础,以及上面所讲的模块整合运用,就可以实现了。
声明:
没经过别人网站的同意,这里不以真实站点来实现。仅以虚拟站点作为例子:如果
想要验证下,可以自己通过自己的博客等授权网站进行测试:
实现代码的过程都是从打开网址开始,然后打开Network刷新一下,查看第0个请求,看Response。如果我们能在Response里找到想要获取的信息,说明我们想要的数据存在HTML里。网站信息是HTML则可以直接退出,不是则查看XHR,继续翻看XHR,阅读下XHR的name或操作加载新的XHR。
这里是爬取某一个网站内容的代码,如下所示:
#下面是所有导入所需的库和模块fromgeventimportmonkeymonkey.patch_all()importrequests,gevent,time,csvfrombs4importBeautifulSoupfromgevent.queueimportQueuestart=time.time()work=Queue()#创建队列#写入csv表格存储数据file=open("article.csv","w",newline="",encoding="utf-8")writer=csv.writer(file)writer.writerow(["内容链接","内容名称","内容点赞数"])Url_1="foriinrange(1,4):forjinrange(1,4):Url=Url_1.format(number=i,data=j)work.put_nowait(Url)#存储数据#以上通过两个for循环,能设置分类的数字和页数的数字。然后,把构造好的网址用put_nowait添加进队列里Url_2="