使用单线程爬取,多线程,协程爬取,异步爬取包图网视频

文章目录

  • 使用单线程爬取,多线程,协程爬取,异步爬取包图网视频
    • 第一步使用单线程爬取包图网视频
    • 多线程爬取视频
    • 用协程爬取
    • 基于协程的异步爬取

第一步使用单线程爬取包图网视频

第一:我先选择要爬取的目标网站

https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0

确定要爬取的目标后面,我们后面直接套取以前的1写过一些的爬取基本四部法:

#第一步:
url = "https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3863.400 QQBrowser/10.8.4334.400',
}# 第二步:发送请求response = requests.get(url=url, headers=headers)# 第三步:获取数据html_content = response.text# 第四部:保存在本地with open('baotuwang.html', 'w',encoding='utf-8') as f:f.write(html_content)

在这个基础上我们要进行一个延伸,还一个数据的提取,为了防止代码的冗余,我们对代码进行一个封装成函数来进行一个简化:

import requests
from lxml import etree
import os
import time
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3863.400 QQBrowser/10.8.4334.400',
}
#下载视频的函数
def downmp4(video_url,video_name):‘’‘要具体填充’‘
#数据提取和选择函数
def parsePage():# 第一步,确定爬虫地址url = "https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0"# 第二步:发送请求response = requests.get(url=url, headers=headers)# 第三步:获取数据html_content = response.text# 第四部:保存在本地# with open('baotuwang.html', 'w',encoding='utf-8') as f:#     f.write(html_content)#数据提取的步骤if __name__ == '__main__':parsePage()

下面就数据提取的详细网页分析解决一下:

打开浏览器自带的调试工具,我们可以按F12快捷键直接打开,也可以双击鼠标的右键打开

锁定要爬取的网页内容:

这个时候我们在要的网页内容里面点击鼠标的右键,出来如

copy 浏览器自带的xpath后,我们在xpath辅助上进行调

图片链接://div[2]/div[2]/ul/li/div/div/a/div[2]/img/@src
视频名字://div[2]/div[2]/ul/li/div/div/a/div[2]/img/@alt
或者//ul/li/@pr-data-title

后面我们就完成数据提取的部分:

#数据提取和选择函数
def parsePage():# 第一步,确定爬虫地址url = "https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0"# 第二步:发送请求response = requests.get(url=url, headers=headers)# 第三步:获取数据html_content = response.text# 第四部:保存在本地# with open('baotuwang.html', 'w',encoding='utf-8') as f:#     f.write(html_content)#提取a标签tree=etree.HTML(html_content)video_page_url=tree.xpath("//ul/li/div/div/a/div[1]/video/@src")print(video_page_url)video_name=tree.xpath("//ul/li/@pr-data-title")print(video_name)start_time=time.time()for i in range(len(video_page_url)):#调用视频下载的函数downmp4(video_page_url[i],video_name[i])finish_time=time.time()print("总共下载的时间是"+str(finish_time-start_time))

视频下载的函数:

#下载视频的函数
def downmp4(video_url,video_name):#定义一个视频下载后存储的文件夹path='包图网大国工匠视频2'#对当前目录下面的文件夹进行判断,如果没有自动创建一个文件夹拉存储if not os.path.exists(path):os.mkdir(path)start_time=time.time()video_url="https:"+video_urlvideo_name=video_name.strip().replace("<strong>","").replace("</strong>","")video_content = requests.get(url=video_url, headers=headers).contentwith open(path+'./%s.mp4'%video_name, "wb") as f:f.write(video_content)finish_time=time.time()-start_timereturn  "每个视频下载的时间"+str(finish_time)

单线程下载视频完整代码:

import requests
from lxml import etree
import os
import time
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3863.400 QQBrowser/10.8.4334.400',
}
#下载视频的函数
def downmp4(video_url,video_name):path='包图网大国工匠视频2'#对当前目录下面的文件夹进行判断,如果没有自动创建一个文件夹拉存储if not os.path.exists(path):os.mkdir(path)start_time=time.time()video_url="https:"+video_urlvideo_name=video_name.strip().replace("<strong>","").replace("</strong>","")video_content = requests.get(url=video_url, headers=headers).contentwith open(path+'./%s.mp4'%video_name, "wb") as f:f.write(video_content)finish_time=time.time()-start_timereturn  "每个视频下载的时间"+str(finish_time)
#数据提取和选择函数
def parsePage():# 第一步,确定爬虫地址url = "https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0"# 第二步:发送请求response = requests.get(url=url, headers=headers)# 第三步:获取数据html_content = response.text# 第四部:保存在本地# with open('baotuwang.html', 'w',encoding='utf-8') as f:#     f.write(html_content)#提取a标签tree=etree.HTML(html_content)video_page_url=tree.xpath("//ul/li/div/div/a/div[1]/video/@src")print(video_page_url)video_name=tree.xpath("//ul/li/@pr-data-title")print(video_name)start_time=time.time()for i in range(len(video_page_url)):downmp4(video_page_url[i],video_name[i])finish_time=time.time()print("总共下载的时间是"+str(finish_time-start_time))
if __name__ == '__main__':parsePage()

我们看看运行效果:

总共下载的时间是7.734321117401123

多线程爬取视频

我们先了解什么是多线程:

多线程类似于同时执行多个不同程序,多线程运行有如下优点:

  • 使用线程可以把占据长时间的程序中的任务放到后台去处理。
  • 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
  • 程序的运行速度可能加快。
  • 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。

指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。

  • 线程可以被抢占(中断)。
  • 在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) – 这就是线程的退让。

线程可以分为:

  • **内核线程:**由操作系统内核创建和撤销。
  • **用户线程:**不需要内核支持而在用户程序中实现的线程。

我们在上面的代码中创建一个线程池就可以了:

##################线程池的实现方法1################1.创建线程池,初始化线程数量executor=ThreadPoolExecutor(4)for i in range(len(video_page_url)):#进入到详情页面下载视频,封装成一个函数----相当于任务,call_back是回调函数executor.submit(downmp4,video_page_url[i],video_name[i]).add_done_callback(call_back) #提交任务#关闭线程executor.shutdown(True)

并且定义个线程函数:

#定义线程函数
def call_back(res):#完成线程的操作,进行回调的函数res=res.result()#获取结果# print(res)

再在下载视频函数里面添加等到线程相关信息的代码,就可以得到线程的详细信息

#得到进程线程相关的信息thread=threading.current_thread()  #得到当前的线程对象process=psutil.Process(os.getpid()) #得到当前的进程对象print(thread.ident,thread.name,process.pid,process.name())

多线程爬取完整代码:

import requests
from lxml import etree
import threading, psutil, os
import time
from concurrent.futures import ThreadPoolExecutorheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3863.400 QQBrowser/10.8.4334.400',
}
#定义线程函数
def call_back(res):#完成线程的操作,进行回调的函数res=res.result()#获取结果# print(res)
def downmp4(video_url,video_name):path='包图网大国工匠视频'#对当前目录下面的文件夹进行判断,如果没有自动创建一个文件夹拉存储if not os.path.exists(path):os.mkdir(path)#得到进程线程相关的信息thread=threading.current_thread()  #得到当前的线程对象process=psutil.Process(os.getpid()) #得到当前的进程对象print(thread.ident,thread.name,process.pid,process.name())start_time=time.time()video_url="https:"+video_urlvideo_name=video_name.strip().replace("<strong>","").replace("</strong>","")video_content = requests.get(url=video_url, headers=headers).contentwith open(path+'./%s.mp4'%video_name, "wb") as f:f.write(video_content)finish_time=time.time()-start_timereturn  "每个视频下载的时间"+str(finish_time)
def parsePage():# 第一步,确定爬虫地址url = "https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0"# 第二步:发送请求response = requests.get(url=url, headers=headers)# 第三步:获取数据html_content = response.text# 第四部:保存在本地# with open('baotuwang.html', 'w',encoding='utf-8') as f:#     f.write(html_content)#提取a标签tree=etree.HTML(html_content)video_page_url=tree.xpath("//ul/li/div/div/a/div[1]/video/@src")print(video_page_url)video_name=tree.xpath("//ul/li/@pr-data-title")print(video_name)start_time=time.time()##################线程池的实现方法1################1.创建线程池,初始化线程数量executor=ThreadPoolExecutor(4)for i in range(len(video_page_url)):#进入到详情页面下载视频,封装成一个函数----相当于任务,call_back是回调函数executor.submit(downmp4,video_page_url[i],video_name[i]).add_done_callback(call_back) #提交任务#关闭线程executor.shutdown(True)finish_time=time.time()print("总共下载的时间是"+str(finish_time-start_time))
if __name__ == '__main__':parsePage()

运行效果:

用协程爬取

什么是协程:

协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快

第一步导入异步IO包:

import asyncio  没有包的下载pip install asyncio

在单线程的代码上修改添加如下代码

#1.创建线程池,初始化线程数量#创建事件循环loop=asyncio.get_event_loop()downmp4Task=[]for i in range(len(video_page_url)):# 生成协程对象downMP4Proxy = downmp4(video_page_url[i], video_name[i])# 封装为future对象,为了观看协程的状态信息future = asyncio.ensure_future(downMP4Proxy)print(future)#把封装的协程对象future添加到数组中downmp4Task.append(future)#注册运行协程loop.run_until_complete(asyncio.wait(downmp4Task))loop.close()#关闭协程

在下载函数那里定义协程对象

async def downmp4(video_url,video_name):#定义协程对象

完整代码:

import requests
from lxml import etree
import threading, psutil, os
import time
from concurrent.futures import ThreadPoolExecutor
import asyncio
import aiohttpheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3863.400 QQBrowser/10.8.4334.400',
}
def call_back(res):data=res.result()print(data)#定义协程对象
async def downmp4(video_url,video_name):path = '包图网大国工匠视频4'# 对当前目录下面的文件夹进行判断,如果没有自动创建一个文件夹拉存储if not os.path.exists(path):os.mkdir(path)#得到进程线程相关的信息thread=threading.current_thread()  #得到当前的线程对象process=psutil.Process(os.getpid()) #得到当前的进程对象print(thread.ident,thread.name,process.pid,process.name())start_time=time.time()video_url="https:"+video_urlvideo_name=video_name.strip().replace("<strong>","").replace("</strong>","")video_content = requests.get(url=video_url, headers=headers).contentwith open(path + './%s.mp4' % video_name, "wb") as f:f.write(video_content)# finish_time=time.time()-start_time# return  "每个视频下载的时间"+str(finish_time)
def parsePage():# 第一步,确定爬虫地址url = "https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0"# 第二步:发送请求response = requests.get(url=url, headers=headers)# 第三步:获取数据html_content = response.text# 第四部:保存在本地# with open('baotuwang.html', 'w',encoding='utf-8') as f:#     f.write(html_content)#提取a标签tree=etree.HTML(html_content)video_page_url=tree.xpath("//ul/li/div/div/a/div[1]/video/@src")print(video_page_url)video_name=tree.xpath("//ul/li/@pr-data-title")print(video_name)start_time=time.time()#1.创建线程池,初始化线程数量loop=asyncio.get_event_loop()downmp4Task=[]for i in range(len(video_page_url)):# 生成协程对象downMP4Proxy = downmp4(video_page_url[i], video_name[i])# 封装为future对象,为了观看协程的状态信息future = asyncio.ensure_future(downMP4Proxy)print(future)downmp4Task.append(future)loop.run_until_complete(asyncio.wait(downmp4Task))loop.close()finish_time=time.time()print("总共下载的时间是"+str(finish_time-start_time))
if __name__ == '__main__':parsePage()

运行效果:

基于协程的异步爬取

第一步导入异步IO包:

import asyncio
import aiohttp 没有包的下载pip install asyncio ,pip install aiohttp

在协程的代码上修改添加如下代码

添加如下代码就可以:

 #建立session连接async with aiohttp.ClientSession() as session:#发起get,post请求async with session.get(url=video_url, headers=headers)as video_response:# 读取请求数据video_content = await video_response.read()

完整代码:

import requests
from lxml import etree
import threading, psutil, os
import time
from concurrent.futures import ThreadPoolExecutor
import asyncio
import aiohttpheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3863.400 QQBrowser/10.8.4334.400',
}
def call_back(res):data=res.result()print(data)
async def downmp4(video_url,video_name):path = '包图网大国工匠视频1'# 对当前目录下面的文件夹进行判断,如果没有自动创建一个文件夹拉存储if not os.path.exists(path):os.mkdir(path)#得到进程线程相关的信息thread=threading.current_thread()  #得到当前的线程对象process=psutil.Process(os.getpid()) #得到当前的进程对象print(thread.ident,thread.name,process.pid,process.name())start_time=time.time()video_url="https:"+video_urlvideo_name=video_name.strip().replace("<strong>","").replace("</strong>","")#建立session连接async with aiohttp.ClientSession() as session:#发起get,post请求async with session.get(url=video_url, headers=headers)as video_response:# 读取请求数据video_content = await video_response.read()# video_content = requests.get(url=video_url, headers=headers).contentwith open(path + './%s.mp4' % video_name, "wb") as f:f.write(video_content)# finish_time=time.time()-start_time# return  "每个视频下载的时间"+str(finish_time)
def parsePage():# 第一步,确定爬虫地址url = "https://ibaotu.com/tupian/gongjiangjingshen/7-0-0-0-0-0-0.html?format_type=0"# 第二步:发送请求response = requests.get(url=url, headers=headers)# 第三步:获取数据html_content = response.text# 第四部:保存在本地# with open('baotuwang.html', 'w',encoding='utf-8') as f:#     f.write(html_content)#提取a标签tree=etree.HTML(html_content)video_page_url=tree.xpath("//ul/li/div/div/a/div[1]/video/@src")print(video_page_url)video_name=tree.xpath("//ul/li/@pr-data-title")print(video_name)start_time=time.time()##################线程池的实现方法1################1.创建线程池,初始化线程数量loop=asyncio.get_event_loop()downmp4Task=[]for i in range(len(video_page_url)):# 生成协程对象downMP4Proxy = downmp4(video_page_url[i], video_name[i])# 封装为future对象,为了观看协程的状态信息future = asyncio.ensure_future(downMP4Proxy)print(future)downmp4Task.append(future)loop.run_until_complete(asyncio.wait(downmp4Task))finish_time=time.time()print("总共下载的时间是"+str(finish_time-start_time))
if __name__ == '__main__':parsePage()

效果:

上面爬虫的实现方式中线程池是最坏的选择,因为它既占用内存,又有线程竞争的危险需要程序员自己编程解决,而且产生的I/O阻塞也浪费了CPU占用时间。再来看看回调方式,它是一种异步方法,所以I/O阻塞的问题解决了,而且它是单线程的不会产生竞争,问题好像都解决了。然而它引入了新的问题,它的问题在于以这种方式编写的代码不好维护,也不容易debug。看来协程才是最好的选择,我们实现的协程异步编程模型使得一个单线程能够很容易地改写为协程。那是不是每一次做异步编程都要实现Task、Future呢?不是的,你可以直接使用asyncio官方标准协程库,它已经帮你把Task、Future封装好了,你根本不会感受到它们的存在,是不是很棒呢

使用单线程,多线程,协程,异步爬取包图网大国工匠视频相关推荐

  1. 多线程爬取包图网背景音乐

    本文旨在交流学习,勿作他用,否则后果自负 import csv import threading import random import requests from lxml import etre ...

  2. 爬虫学习(10):xpath爬取包图网高清模板视频

    暂时我就没有发xpath基础知识了,编辑太浪费时间了,需要了解或者有问题的可以加我群问我就好了,我也正在努力学习中,不废话了,上代码,解释都在注释. 先看效果: 开始的时候下载的还不是那么高清,后来我 ...

  3. 【Python 多线程vs协程】爬取西游记

    为了有效的学习和加深对于线程和协程的认知,将同一个任务用不同思路呈现很有帮助. 这里通过使用多线程以及协程两种方式对西游记的篇章内容进行爬取,来对比一下两者的耗时差异. 首先,多线程爬取. 这里没有限 ...

  4. python协程多任务爬取虎牙美女主播图片

      使用正则.协程多任务爬取虎牙海量美女图片,斗鱼也一样,只需将正则表达式中的内容换一下即可,由于斗鱼网站的变化,之前的正则已用不了,现贴出新的: re.findall(r"https:// ...

  5. 多线程 爬取 趣图网

    原文链接: 多线程 爬取 趣图网 上一篇: 百度网盘获取私密分享的文件 下一篇: 欧几里得距离.曼哈顿距离和切比雪夫距离 # coding=utf-8import urllib import urll ...

  6. 斗图斗不过小伙伴?python多线程爬取斗图网表情包,助你成为斗图帝!

    最近python基础课讲到了多线程,老师让交个多线程的实例练习.于是来试试多线程爬虫,正好复习一下mooc上自学的嵩天男神的爬虫知识.想法很美好,过程却很心酸,从早上开始写,每次出现各种奇怪问题,到现 ...

  7. 100行代码教你爬取斗图网(Python多线程队列)

    100行代码教你爬取斗图网(Python多线程队列) 前言 根据之前写的两篇文章,想必大家对多线程和队列有了一个初步的了解,今天这篇文章就来实战一下,用多线程 + 队列 爬取斗图网的全网图片. 你还在 ...

  8. python3爬虫——多线程爬取斗图网表情包

    本文用多线程生产者,消费者模式爬取斗图网的表情包,并下载保存到本地,get_page()函数负责获取页面的图片的url链接,downlod_img()函数通过图片url下载保存到本地文件夹中,开启多线 ...

  9. 爬虫笔记——多线程爬取斗图网表情包(threading)

    爬虫笔记--多线程爬取斗图网表情包(threading) 网站观察 爬取框架 具体代码 斗图网网址:斗图网,这里以爬取最新套图为例. 网站观察 在网页翻页操作中可以看到网页是非动态加载的(page为页 ...

最新文章

  1. 【AC自动机】【字符串】【字典树】AC自动机 学习笔记
  2. yii2组件之下拉框带搜索功能(yii-select2)
  3. c语言求100以内整除13的最大,VB程序设计的一道题,找出100以内能被3整除的所有数之和,并把值保存在一维数组中...
  4. html打开显示脚本错误,IE浏览器显示脚本错误怎么办 IE浏览器脚本错误解决方法图文教程...
  5. Java项目课程02:系统概述
  6. [原创]java WEB学习笔记58:Struts2学习之路---Result 详解 type属性,通配符映射
  7. Python与开源GIS:在OGR中使用SQL语句进行查询
  8. vue源码分析系列之响应式数据(三)
  9. [经典好文] 谈笑色影间,人生本无忌 (转于色影无忌)
  10. astah新建一个项目_Astah SysML
  11. 计算机的键盘应用,电脑键盘应用小知识
  12. 【华为灰度管理法】之读书思维导图及感想分享
  13. Zookeeper轻松上手
  14. API v3版微信支付平台证书获取与自动更新
  15. c语言求100以内被7整除的最大自然数,编程,求100以内被7整除的最大自然数
  16. 如何做推广?利用今日头条吸引大量精准粉丝
  17. 定时任务的10种写法,长见识了
  18. [2001-2003美/新等合拍经典奇幻大片][魔戒1-3][BD-RMVB][中英字幕/1280x720高清晰版]
  19. 【jsPlumb】使用记录
  20. 太原计算机学校专科代码,(全国高等院校学校代码查询).doc

热门文章

  1. 大学生励志创业成为破烂王
  2. 计算机自带的音乐剪辑怎么打开,音乐剪切器怎么使用,音乐剪切器使用教程
  3. Java裁剪音乐,利用IO流
  4. 【Java刷题笔记】牛客网Java入门 1~4
  5. 【51单片机】HX711智能电子秤设计
  6. cnzz统计 检测浏览器原理(跨浏览器开发实用源码)
  7. 【让我们为你连接到网络】未识别的网络进行修复
  8. 【SDX65】WCN6856启动出现系统崩溃问题
  9. HTK学习笔记(一)
  10. CVE-2007-1157(jboss CSRF漏洞)